GNOME Bugzilla – Bug 633999
Provide bindable version of signal handler query functions
Last modified: 2015-02-07 16:52:59 UTC
There are many g_signal_handler query functions (find, block_matched, disconnect_matched, etc) that were never bound in pygobject (and now crash when used with PyGI -- bug 633927) because they use many difficult to bind constructs like generic gpointers, GQuarks, and closures. Is it possible to either annotate those correctly or provide a different API that is binding-friendly?
Generally I've been saying that anything in GLib/GObject may require manual overrides. In this case, it's hard to say...what exactly are you trying to do? Probably the right thing is to add some sort of lowlevel API to pygobject for this.
I was writing a python function to automatically connect signals to methods on a class with a well-defined handler name pattern. But I wanted to avoid doing so if glade had already setup the same connection. So I wanted to query to see if a given signal had been connected to a given method yet, before I made that same connection.
That makes sense (having these real-world use cases is really helpful for evaluating bugs). The problem with this case is that the binding layer (pygobject) is going to be dynamically creating C closures for the signal handlers, and that's all that GObject knows about. In other words when you do: def foo(w, c): print "drawing on " + c foo.connect('draw', foo) There's a new C function created, and there's no sane way to say e.g.: foo.has_connected('draw', foo) without traversing the internal binding layer. In other words - reassigning to pygobject if you want this, it needs to be there.
Though to be clear, in my specific example, I didn't want to call a fictional has_connected to check for connections made by pygobject but by the C glade library. For which you would have enough information, right?
Sorry, that's probably non-sensical. I actually assume there would still need to be python-side connection code (probably by the python glade bindings).
I wouldn't use python-glade with PyGI. First glade is deprecated in favour of GtkBuilder, second, python-glade pulls in PyGTK, which definitely won't work with PyGI. In any case this seems like a really hard thing to support from the python side. It would be a lot of bookkeeping code to be able to translate bidirectionally between the C closure and the python method. All of that for an edge usecase. An application should be able to track these things for themselves. Perhaps I am not fully understanding the example but most of the convenience methods boil down to a gobject.connect_object_* call. We never magically hook up callbacks to the point that an application couldn't replicate the methods, adding some bookkeeping in between. Since you can dictate what goes into the apps you can specify developers must use your bookkeeping methods to hook up callbacks. If you look at the GtkBuilder override we provide we simply call the Gtk.Builder.connect_signals_full method with a function and an object (or dictionary of callbacks). For each signal defined in the UI file, the builder calls the function we provided and passes the object as user data. We then look at the handler name defined in the UI file and see if there is a corresponding method and hook it up using the connect_object_* API. You could simply copy and paste that and add your bookkeeping code. The one thing I can see us adding here is a hook that gets called if it can't find the handler which an application could use to add their own logic to hooking up a signal to a handler. That would avoid bookkeeping. [1] http://git.gnome.org/browse/pygobject/tree/gi/overrides/Gtk.py#n267
Is there an update on this issue whether it can be fixed or not?
If I read it right, this is WONTFIX. Please reopen if this is not the case.
Re-opening as a number of these functions are easily fixed by supplying a type annotation to the instance argument: /** * g_signal_stop_emission: * @instance: (type GObject.Object): ... ... */
Created attachment 228748 [details] [review] Add GObject.Object type annotation to all g_signal_* functions.
It also seems plausible these functions accept instance types besides GObjects. If that is the case than we should change the annotations to (skip) unless someone has a better idea?
Signals also work on other fundamental objects as far as I know. However, this patch would turn "does not work for anything through GI" into "only works for GObjects through GI", which is certainly a huge improvement, as that covers the vast majority of use cases.
These annotations will allow easy removal of the following statically implemented methods in pygobject: pygobject_disconnect pygobject_handler_is_connected pygobject_handler_block pygobject_handler_unblock pygobject_stop_emission And with a bit of work we should be able to remove the following: pygobject_connect pygobject_connect_after pygobject_connect_object pygobject_connect_object_after pygobject_emit Together, all of this could be a significant reduction in the amount of code in pygobject.c I think for now using GObject.Object for the annotations will help a lot. And eventually the goal should be to change the annotations use a special "any gtype" annotation, but that will require a log more changes across the board.
Closing as this will no longer be needed. We are able to overcome the problem by exposing a pointer to the underlying GObject by wrapping it with a PyCapsule as a private attribute (__gpointer__). pygi marshaling can then extract the raw pointer from the capsule and pass it in. This will also allow us to have thin wrappers which work for other types, not just GObjects.
Comment on attachment 228748 [details] [review] Add GObject.Object type annotation to all g_signal_* functions. Need replaced by other means, see: bug 692918
Changing to dup for future reference. *** This bug has been marked as a duplicate of bug 685387 ***
[Mass-moving gobject-introspection tickets to its own Bugzilla product - see bug 708029. Mass-filter your bugmail for this message: introspection20150207 ]