After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 721226 - Add constructor dispatching based on keyword arguments
Add constructor dispatching based on keyword arguments
Status: RESOLVED OBSOLETE
Product: pygobject
Classification: Bindings
Component: introspection
unspecified
Other Linux
: Normal enhancement
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
: 654048 (view as bug list)
Depends on:
Blocks: 708060
 
 
Reported: 2013-12-30 01:59 UTC by Thierry Vignaud
Modified: 2018-01-10 20:36 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
python-gi regression reproducer (56 bytes, text/x-python)
2013-12-30 01:59 UTC, Thierry Vignaud
Details
demo of working Plug usage with pygtk (37 bytes, text/plain)
2013-12-30 04:45 UTC, Thierry Vignaud
Details

Description Thierry Vignaud 2013-12-30 01:59:58 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
  • File "/tmp/reproducer.py", line 2 in <module>
    p = Gtk.Plug(123)
  • File "/usr/lib64/python2.7/site-packages/gi/overrides/Gtk.py", line 442 in __init__
    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
Comment 1 Christoph Reiter (lazka) 2013-12-30 02:39:13 UTC
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.
Comment 2 Thierry Vignaud 2013-12-30 04:45:26 UTC
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)>
Comment 3 Gian Mario Tagliaretti 2013-12-30 09:59:56 UTC
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)>
>>>
Comment 4 Simon Feltman 2013-12-30 11:10:49 UTC
(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.
Comment 5 Simon Feltman 2013-12-30 11:48:10 UTC
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
Comment 6 Simon Feltman 2014-01-02 05:03:58 UTC
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)
Comment 7 Simon Feltman 2014-01-02 05:04:33 UTC
*** Bug 654048 has been marked as a duplicate of this bug. ***
Comment 8 GNOME Infrastructure Team 2018-01-10 20:36:05 UTC
-- 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.