GNOME Bugzilla – Bug 633347
Cannot add GtkHBox to a GtkButton
Last modified: 2010-11-07 18:14:16 UTC
GtkButton seems to do too harsh type checks when acting as a container. The code Gtk.Button().add(Gtk.HBox()) throws: TypeError: argument 1: Must be Gtk.Widget, not HBox
Thanks for the bug report. This particular bug has already been reported into our bug tracking system, but please feel free to report any further bugs you find. *** This bug has been marked as a duplicate of bug 631631 ***
This works fine for me, even without the patch in bug 631631. Can you check if the latest pygobject in git works for you?
I just tried in an interactive python console (in a jhbuild shell) with latest pygobject from git via jhbuild. [jhbuild] hb@host:~$ python Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import pygtk >>> pygtk.require("2.0") >>> from gi.repository import Gtk >>> Gtk.Button().add(Gtk.Label()) Traceback (most recent call last):
+ Trace 224452
return info.invoke(*args)
>>>
Ok, so I see the issue. I'm not sure why my instance isn't erroring out. In any case we override both Widget and Container so all of out other overrides must inherit from them. I just committed a fix. See if that works for you.
While trying to come up with a unittest to check inheritance I encountered a problem: >>> from gi.repository import Gtk >>> ali = Gtk.Alignment() >>> ali.get_name() Traceback (most recent call last):
+ Trace 224465
We do not override Alignment, but Widget, of course. In the patch you mentioned you manually inherited from the overwritten classes, does this mean we have to overwrite every class that inherits from Widget to get this right? This of course not only applies to Widget but all overrides.
I was under the impression that if there is an override when constructing the wrapper we automatically inherit from the override
So the interesting thing is we are inheriting the methods from the overridden object but we aren't an instance of that object. I'm not sure how we remedy it. My patch doesn't help in this code path
Narrowed it down to a race condition. Basically the overrides module doesn't exist until it is fully imported. Inside the overrides module we are instantiating and caching each base type in the class hierarchy for any class that is overridden. In the case of GtkAlignment, it inherits from GtkBin which in turn inherits from GtkContainer, etc. When GtkButton is overridden in the overrides it too inherits from GtkBin, so it sets up the GtkBin wrapper class which in turn inherits from GtkContainer. If this was done outside the overrides, GtkBin would find Gtk.overrides.Container and everything would be right in the world. Since it is done inside the overrides, GtkBin is now cached with a base of GtkContainer. When GtkAlignment is instantiated it looks up its base which happens to be GtkBin. This is where we lose. Since GtkBin is cached with the wrong base hierarchy we end up not inheriting from Gtk.overrides.Container (or Widget for that matter).
to simplify the explanation, it is a reentrancy error. We are constructing a class in the overrides which jumps out to modules.py which in turn tries to reenter the overrides module to check if there are any overrides. Since the override module isn't fully loaded, module.py assumes there are no overrides and proceeds to construct the actual Gtk class instead. I'm not quite sure how to fix this issue.
Created attachment 173830 [details] [review] Add a overrides registry so we can refrence overrides inside the module * Overrides have a reentrancy issue when doing inheritance. If an override inherits from another override down the stack it won't see the override because the module is not finished loading and will inherit from the non-overriden object instead. This causes type errors later. * By adding the overrides to a registry outside of the module we can order registration and make the override available as soon as the class is parsed, not when the whole module is parsed.
This patch is just a first pass. It still needs tests and it breaks the dialogs tests for some reason
It breaks dialogs because I was relying on the broken inheritance behavior to work around a name clash in the various constructors. Namely that Gtk.Dialog overloads the buttons keyword to take a list of buttons while some of the Gtk.Dialog sub classes send in an Enum (which is the original behavior). So in otherwords the dialogs got broken in a good way. It means this patch is working correctly.
Created attachment 173841 [details] [review] Add tests This patch adds the test I was talking about in comment 5. I admit it's kind of dirty, but I couldn't find a better way to get all super classes. The test currently stays in the Gtk namespace to avoid name clashes such as GActionGroup and GtkActionGroup.
*** This bug has been marked as a duplicate of bug 631631 ***
Opps, Wrong way around
*** Bug 631631 has been marked as a duplicate of this bug. ***
Since IRC discussion and debugging turned out extremely weird results on my setup, I now did a fresh jhbuild checkout and build, and don't have this problem anymore with current git master (no additional patches applied, neither from this bug nor from the duplicate). I suspect I had some funky version mismatch of gtk2/gtk3 mixtures. Nice to know that you still found an issue (so I'm leaving the bug open), and that I didn't just send you on useless missions of ghost hunting. Thanks for your patient support.
Ya it was great. I need to remind people that if they bug me enough I spend more time on the issue :) Really if someone show interest enough to engage me I end up really wanting to solve their issue so feel free to hit us up again if you run into other problems. As it is this patch is still not complete. The test case brought up a ref counting issue with the base_info's so I need to fix that and hopefully I can get a release out this weekend during the GNOME Summit.
Also I will eventually move to getting all overrides registered, not just GObject overrides. This will allow us to remove most of the funky calls to __import__.
Ref counting error went away in a gobject-introspection HEAD