GNOME Bugzilla – Bug 681477
Can't inherit GtkTreeModelSort and pass a model to the parent constructor
Last modified: 2012-08-15 20:23:12 UTC
Previously in pygtk was possible to do this: class MyModel(gtk.TreeModelSort): def __init__(self): self._model = gtk.ListStore(int, str) self._model_filter = self._model.filter_new() gtk.TreeModelSort.__init__(self, self._model_filter) Now I'm trying to port a similar code to GTK+3 - PyGi but this is not possible: class MyModel(Gtk.TreeModelSort): def __init__(self): self._model = Gtk.ListStore(int, str) self._model_filter = self._model.filter_new() # FIXME, can't call the parent constructor with a model: Gtk.TreeModelSort.__init__(self, self._model_filter) The constructor is gtk-tree-model-sort-new-with-model in the documentation: http://developer.gnome.org/gtk3/stable/GtkTreeModelSort.html#gtk-tree-model-sort-new-with-model
I think construction properties (or any properties) can be passed using keyword args with gi. Gtk.TreeModelSort.__init__(self, model=self._model_filter) Should fix the immediate problem. I'm not sure if the pygobject devs want to also create an compatibility override as well though...
Thanks Simon for the tip, works fine. Looking at the Gtk override in PyGobject we do the same kind of overriding for other widgets like GtkButton, you can pass a label with or without specifying the keyword argument. Actually there is an upside when specifying the keyword arguments: the code gets more readable imho. The override parts that helps you with the argument detection is nice in one way when you come from Pygtk but probably hides the issues you run into with widgets that are not part of it. All in all, maybe it is good practice to always specify the keyword for the arguments.
I tend to agree that keyword args make things more readable. But I also think trying to make it compatible with PyGtk is important as I'm still going through lots of problems trying to upgrade to gi myself. I think in this particular case the model arg should probably go in an override as a required parameter (not keyword arg) because the model property is set to G_PARAM_CONSTRUCT_ONLY and there is no way to set it after the fact (making it a useless sort model). See: https://bugzilla.gnome.org/show_bug.cgi?id=675648 as this ticket proposes a required constructor flag which could have helper out here. Furthermore, there is no pydoc giving any information about the magic keyword args. A nice future to gi might be for it to auto pydoc __init__ methods with any properties set to G_PARAM_CONSTRUCT_ONLY. I can log a separate ticket for that. Stylistically, you can also pass required args as keyword args when calling, this might give the best of both worlds for this particular case: def spam(model): pass spam(model=someModel)
Created attachment 220773 [details] [review] Added override for Gtk.TreeModelSort
Review of attachment 220773 [details] [review]: Don't you need to keep **kwds in the __init__ and to propagate it so that one can still specify properties? In general constructor overrides are a bit of a slippery slope and we probably added too many of them in the 3.0 rush to try to make pygtk migration easy, so we will have to draw a line somewhere. But in this case the override probably makes sense, even the C api only has _new_with_model
Created attachment 220780 [details] [review] Added **kwds The **kwds didn't seem necessary because the TreeModelSort only has one property which is the model. However, it does make sense for future extensibility (in case a new property is added to TreeModelSort). I'm curious if it would be possible to implement these initializer overrides deeper in the system and generically by looking at things like properties flagged as G_PARAM_CONSTRUCT. For example, gtk_button marks label, use-underline, use-stock, always-show-image as G_PARAM_CONSTRUCT. These are mostly what show up as the keyword args for the Gtk.Button override although in a different ordering.
Created attachment 220782 [details] Property flag check script That first check with Gtk.Button keyword args being flagged as construct might have just been serendipitous. Attached is a script which prints out all the class __init__ override param names and if they are flagged as CONSTRUCT or CONSTRUCT_ONLY.
Review of attachment 220780 [details] [review]: I committed the override after moving it after the TreeSortable override, otherwise you get this test failure. FAIL: test_inheritance (test_overrides.TestGtk) ---------------------------------------------------------------------- Traceback (most recent call last):
+ Trace 230676
"%r does not inherit from override %r" % (klass, over,))
I also added a unit test
What about the script in comment #7? Do you want to file a separate bug to track the generic issue? In the mean time I am closing this specific report
Thanks Paolo, Sorry for the lack of clarity, the script was showing a generic solution doesn't seem possible. I had incorrectly correlated CONSTRUCT flagged properties with what overrides were using as initializer args, but looking at all of them shows otherwise. I might look at a generic solution for generating initializers for CONSTRUCT_ONLY flagged properties as these are trickier to know about from within python. I was actually unable to run tests for a while because I was hitting this: https://bugzilla.gnome.org/show_bug.cgi?id=675985#c6 But I just verified things are fixed up.