52 lines
1.7 KiB
Python
52 lines
1.7 KiB
Python
import types
|
|
import weakref
|
|
|
|
|
|
def ref(function):
|
|
return CallableWeakReference(function)
|
|
|
|
|
|
class CallableWeakReference(object):
|
|
|
|
def __init__(self, function):
|
|
'Create a weak reference to a callable'
|
|
try:
|
|
if function.im_self:
|
|
# We have a bound method or class method
|
|
self._reference = weakref.ref(function.im_self)
|
|
else:
|
|
# We have an unbound method
|
|
self._reference = None
|
|
self._function = function.im_func
|
|
self._class = function.im_class
|
|
except AttributeError:
|
|
try:
|
|
function.func_code
|
|
# We have a normal function or static method
|
|
self._reference = None
|
|
self._function = function
|
|
self._class = None
|
|
except AttributeError:
|
|
function = function.__call__
|
|
# We have a class masquerading as a function
|
|
self._reference = weakref.ref(function.im_self)
|
|
self._function = function.im_func
|
|
self._class = function.im_class
|
|
|
|
def __call__(self):
|
|
if self.dead:
|
|
return
|
|
if self._reference:
|
|
# We have a bound method
|
|
return types.MethodType(self._function, self._reference(), self._class)
|
|
elif self._class:
|
|
return types.MethodType(self._function, None, self._class)
|
|
else:
|
|
return self._function
|
|
|
|
@property
|
|
def dead(self):
|
|
if self._reference and not self._reference():
|
|
# We have a bound method whose parent reference has died
|
|
return True
|
|
return False
|