GNOME Bugzilla – Bug 672207
Add signal accessors for all GObjects
Last modified: 2018-01-10 20:14:59 UTC
Most of the python UI toolkits lack an easily accessible signal API on objects. A direct accessor of signals on objects would allow for inspection and support of programming editors with auto-completion. * Qt uses C function signatures as strings for connections. * Gtk uses simple strings. * wx at uses a variable but it is on a huge wx namespace that will freeze up auto completers when you type "wx." All these toolkits (among many others in other languages) share the common problem of rote memorization of what signals are allowed on the objects or you have to constantly reference documentation. The idea is to add accessors to the GObject base class which provide a list of available signals on GObject and derived classes. This is similar to 'event' objects in C# forms. Here is an example with variations for consideration: button.clicked.connect(onClicked) This variation is the simplest but may tend to muddy up the Gtk.Widget namespace as all available signals would be exposed this way. button.signals.clicked.connect(onClicked) This gives concise grouping of available signals and is similar to the existing "props" accessor. button.event_clicked.connect(onClicked) button.signal_clicked.connect(onClicked) Variations similar to the "signals" but directly on the object and would group alphabetically in docs and auto-completors. This proposal should make use of the Signal object submitted as a patch in: https://bugzilla.gnome.org/show_bug.cgi?id=434924
I have some mixed feelings about this. The idea of gobject-introspection is to keep it as close to the C API as possible, and only add overrides when the C API is extremely difficult or unintuitive to use. But button.clicked.connect(onClicked) isn't any easier than button.connect('clicked', onClicked) Also as all the existing glib/gtk documentation uses the second form. Python can't do static code checks anyway, so we don't even have the benefit of (reliably) checking whether the signal exists statically (i. e. whatever pendant of "compile time" there is). IMHO this would be a rather arbitrary API change. Also, signal names can (and often do) contain spaces, and perhaps other symbols which are not valid in identifiers. I keep it as an enhancement request, though.
Points well taken. Comparing the text side by side definitely doesn't show it to be any easier. However, while using an editor or console with auto-completion and call-tips/documentation there is a difference in productivity (eclipse, wing, bpython, ipython, ...). For instance, if I'm reading code and don't know the details of what a signal does, I can mouse over it and documentation should popup in a tooltip. Or if I don't remember or know a signal name I'm looking for, I can start typing and a list of available signals show up with and allow auto-completion of the signal name. As for signal names, would it be different than what properties go through to canonicalize their names? I think the "props" accessor was a nice edition to GObject and this just provides a parallel in regards to signals. Thanks for your feedback!
Created attachment 223880 [details] [review] Working and tested implementation Most of this work piggy backs off of the Signal helper that has been added to pygobject. GObjects pulled in through gi are now assigned signal accessors based on introspection information. Some refactoring was done to break core functionality of Signal into BaseSignal. BaseSignal is used to wrap existing signals from introspection information and Signal is a sub-class of this used specifically for creation of new signals within python. The patch exposes "get_signals" on ObjectInfo which returns SignalInfo objects based on CallableInfo from gi. This allows the python gi.types code to inspect signals and apply them after methods have been added to a class. Some tricky bits were there are cases (in Gtk) where methods with the same name as a signal already exist on the object, generally theses methods simply emit the signal of the same name. But to be on the safe side, the original method is stored within a BaseSignal instance and used instead of emit directly. This will guarantee any existing methods with signals of the same name will still work the same as they always have.
Created attachment 227709 [details] [review] Rebased patch on top of current HEAD
Created attachment 227713 [details] [review] Rebase with fixed test function names.
Created attachment 227714 [details] [review] More cleanup after rebase, removed global type cruft in test_signals.
Created attachment 228619 [details] [review] Add signal accessors to GObject based classes Rebased patch and add bug 681967 as a dependency. This update now adds doc signatures to the signal helpers coming from gi, for example: class Widget(gi.repository.Gtk.Widget) ... | key_press_event(...) | key_press_event(self, event:Gdk.EventKey)
Review of attachment 228619 [details] [review]: This needs to be broken out into multiple patches. 1. Refactoring of BaseSignal but keeps the functionality the same 2. Adds signals to all objects, this also needs to take performance implications into account from bug 704037 in terms of lazy docs and potentially using info objects directly.
-- 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/25.