Although I'm not quite sure what changed or why, in Python3 you can't create a weak-reference to a method the way you can in Python2.
So here's the way I create weak method references in Dmedia and Novacut:
The reason I needed weak method references is that idiomatic OO Python tends to be plagued with circular references when your GObject signal callbacks happen to be methods. It's surprisingly difficult to avoid this without creating convoluted, non-idiomatic code. But wrapping your callbacks with
The Dmedia App Indicator is only shown when the importer is actually running, which potentially could be started and stopped many times during the process life-cycle. I couldn't figure out why my App Indicator didn't go away when I seemingly de-referenced the
By the way,
So here's the way I create weak method references in Dmedia and Novacut:
#!/usr/bin/python3
import weakref
class WeakMethod:
def __init__(self, inst, method_name):
self.proxy = weakref.proxy(inst)
self.method_name = method_name
def __call__(self, *args):
return getattr(self.proxy, self.method_name)(*args)
class Foo:
def bar(self, msg):
return msg
foo = Foo()
callback = WeakMethod(foo, 'bar')
print(callback('baz'))
The reason I needed weak method references is that idiomatic OO Python tends to be plagued with circular references when your GObject signal callbacks happen to be methods. It's surprisingly difficult to avoid this without creating convoluted, non-idiomatic code. But wrapping your callbacks with
WeakMethod
solves the problem, without making a mess.The Dmedia App Indicator is only shown when the importer is actually running, which potentially could be started and stopped many times during the process life-cycle. I couldn't figure out why my App Indicator didn't go away when I seemingly de-referenced the
AppIndicator3.Indicator
instance. But after some help from the friendly and infinitely wise Ted Gould, I finally realized it was my fault (of course!). A circular reference meant a chain of objects were never getting garbage collected.By the way,
sys.getrefcount()
is your friend when trying to debug circular references or test for them in your unit-tests. Note that the ref-count will always be one greater than you expect because the sys.getrefcount()
function argument will create an additional reference during the function call.