Removing the dynamic_cast causes the code to fail compilation, as .root() returns a Root, but set_transient expects a Window. However, the dynamic_cast is fine, because if the object returned by .root() is not convertible to a Window, the return value will be None, and cause the second expect to panic.
Once cast, root is a Window, as it does in fact return the ApplicationWindow which contains the button (I checked), and an ApplicationWindow is also a Window.
I think the issue is probably internal to GTK. As the way dialogs work has completely changed in the meanwhile, and it’s a very minor issue, I will just ignore it.