I recently ported indicator-jenkins to Gtk3 using the python GObject Introspection Repository (gir) bindings. Ted Gould did most of the work, I just cleaned some bits up and made sure everything worked. One issue that puzzled me for a while is that the GObject library changed the way it's "notify" signal works between GObject 2 and GObject 3. I've not seen any documentation of this change, so I'll describe it here.
For this example, let's make a very simple class that has a single property:
import gobject
class MyClass(gobject.GObject):
prop = gobject.property(type=int)
...and a very simple callback function that we want to call whenever the value of 'prop' changes:
def cb(sender, prop):
print "property '%s' changed on %r." % (prop.name, sender)
Finally, with GObject 2 we can create an instance of 'MyClass' and connect to the 'notify' signal like this:
inst = MyClass()
inst.connect("notify", cb)
inst.prop = 42
When we run this simple program we get the following output:
property 'prop' changed on
... which is what we expected. However, if we port this code to GObject 3, it should look like this:
from gi.repository import GObject
class MyClass(GObject.GObject):
prop = GObject.property(type=int)
def cb(sender, prop):
print "property '%s' changed on %r." % (prop.name, sender)
inst = MyClass()
inst.connect("notify", cb)
inst.prop = 42
However, running this gives an error:
/usr/lib/python2.7/dist-packages/gi/_gobject/propertyhelper.py:171: Warning: g_value_get_object: assertion `G_VALUE_HOLDS_OBJECT (value)' failed
instance.set_property(self.name, value)
Traceback (most recent call last):
File "gobject3.py", line 8, in cb
print "property '%s' changed on %r." % (prop.name, sender)
AttributeError: 'NoneType' object has no attribute 'name'
The 'prop' parameter in the callback is set to None.
There is a solution however - connecting the callback to a more specific notification signal works as expected:
from gi.repository import GObject
class MyClass(GObject.GObject):
prop = GObject.property(type=int)
def cb(sender, prop):
print "property '%s' changed on %r." % (prop.name, sender)
inst = MyClass()
inst.connect("notify::prop", cb)
inst.prop = 42
It took me a while to figure this out - hopefully I've saved someone else that work.