GNOME Bugzilla – Bug 721226
Add constructor dispatching based on keyword arguments
Last modified: 2018-01-10 20:36:05 UTC
Created attachment 265016 [details] python-gi regression reproducer There's a regression when going from pygtk to gobject: creating a Gtk.Plug no longer works: $ python /tmp/reproducer.py
+ Trace 232969
p = Gtk.Plug(123)
traceback.print_stack() /usr/lib64/python2.7/site-packages/gi/overrides/Gtk.py:447: Warning: value "((GtkWindowType) 123)" of type 'GtkWindowType' is invalid or out of range for property 'type' of type 'GtkWindowType' Gtk.Window.__init__(self, type=type, **kwds)
See https://bugs.mageia.org/show_bug.cgi?id=11546 This breaks Mageia Linux: we patched years ago system-config-printer to use a Gtk.Plug instead of a Gtk.Window when embedded in our Control Center. This no longer works since it has been ported to gtk3 /usr/lib64/python2.7/site-packages/gi/overrides/Gtk.py:445: Warning: value "((GtkWindowType) 56640845)" of type 'GtkWindowType' is invalid or out of range for property 'type' of type 'GtkWindowType' Gtk.Window.__init__(self, type=type, **kwds) See https://bugs.mageia.org/show_bug.cgi?id=11541 I've workarounded this by explicitely calling the .new() method but this isn't pythonish... See http://svnweb.mageia.org/packages/cauldron/system-config-printer/current/SOURCES/system-config-printer-1.4.2-mga_custom-embedded_window.patch?r1=547330&r2=547337&sortby=date Can you add an override for Plug in gobject? Thanks
PyGObject isn't API compatible with pygtk. Gtk.Plug inherits the Gtk.Window __init__ overrides which allows the first argument to be a Gtk.WindowType (so 1 or 0). So this should have never worked with PyGObject as far as I can see.
Created attachment 265020 [details] demo of working Plug usage with pygtk Yeah sure it does't work with pygtk.... $ python ~/Téléchargement/reproducer-pygtk.py <gtk.Plug object at 0x2262460 (GtkPlug at 0x1ef90d0)>
Thierry see if the following works for you: Python 2.7.5 (default, Nov 12 2013, 16:45:58) [GCC 4.8.2 20131017 (Red Hat 4.8.2-1)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from gi.repository import Gtk >>> p = Gtk.Plug.new(socket_id=123) >>> print p <Plug object at 0xb6b44e3c (GtkPlug at 0x8673160)> >>>
(In reply to comment #2) > Yeah sure it does't work with pygtk.... I think what Christoph said is that it could have never worked in PyGObject and therefore this is not really a "regression" so to speak. Because PyGObject is not API compatible with PyGTK. If you run the example with git master, you'll notice a new deprecation warning being printed in addition to the GtkWindowType error: >>> Gtk.Plug(123) PyGTKDeprecationWarning: Using positional arguments with the GObject constructor has been deprecated. Please specify keywords for type or use a class specific constructor. See: https://wiki.gnome.org/PyGObject/InitializerDeprecations The wiki document basically says that we are actively trying to get rid of overrides where possible. This bug very related to bug 711487 which is listed as part of the reasoning. So instead of adding overrides, the effort needs to go into generalized annotation techniques, in this case for default constructors. There is a large pile of tickets related to all of this: https://bugzilla.gnome.org/showdependencytree.cgi?id=708060&hide_resolved=1 So for now, I think we have to make due with using an occasional "new" as ugly as it might be. The closest related ticket in that pile is bug 654048, so I think this should be closed as a dup of that. As a side note, I also see no problem with adding a monkey patched version of Plug.__new__ into pygtkcompat which is intended to be API compatible with PyGTK.
An additional thought about this... We could overload __new__ by default which then dispatches to GI constructors based on the keyword args passed in and constructor signatures. A mockup implementation would do something like: def __new__(cls, *args, **kwargs): # Don't attempt dealing with positional args to allow deprecations if args: return GObject.Object.__new__(cls, *args, **kwargs) for constructor in cls.get_constructors(): if constructor.arg_names === kwargs.keys(): return constructor(**kwargs) # fallback to g_object_newv return GObject.Object.__new__(cls, *args, **kwargs) At which point things like: Gtk.Plug(socket_id=123) would dispatch to Gtk.Plug.new. Of course we would definitely need to list the constructor variations in the class docstring like Python does... >>> type? Docstring: type(object) -> the object's type type(name, bases, dict) -> a new type
Re-purposing ticket with the idea that construction related issues could be fixed up a bit with dispatching based on keyword args. The caveat is I would like to limit this to keyword args only by reason that they give necessary information for readers of code, especially in an overloading situation. The idea is the following could work via a dispatching constructor: >>> Gtk.Plug(socket_id=123) but this would fail: >>> Gtk.Plug(123) TypeError: Gtk.Plug() does not accept positional arguments, use keywords. See: help(Gtk.Plug) Mockup of help: >>> Gtk.Plug? :Constructors: Plug(**properties) Plug(socket_id:int) Plug(display:Gdk.Display, socket_id:int)
*** Bug 654048 has been marked as a duplicate of this bug. ***
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/pygobject/issues/61.