weakmeth.py 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. from weakref import ref
  2. class _weak_callable:
  3. def __init__(self,obj,func):
  4. self._obj = obj
  5. self._meth = func
  6. def __call__(self,*args,**kws):
  7. if self._obj is not None:
  8. return self._meth(self._obj,*args,**kws)
  9. else:
  10. return self._meth(*args,**kws)
  11. def __getattr__(self,attr):
  12. if attr == 'im_self':
  13. return self._obj
  14. if attr == 'im_func':
  15. return self._meth
  16. raise AttributeError(attr)
  17. class WeakMethod:
  18. """ Wraps a function or, more importantly, a bound method, in
  19. a way that allows a bound method's object to be GC'd, while
  20. providing the same interface as a normal weak reference. """
  21. def __init__(self,fn):
  22. try:
  23. self._obj = ref(fn.im_self)
  24. self._meth = fn.im_func
  25. except AttributeError:
  26. # It's not a bound method.
  27. self._obj = None
  28. self._meth = fn
  29. def __call__(self):
  30. if self._dead(): return None
  31. return _weak_callable(self._obj(),self._meth)
  32. def _dead(self):
  33. return self._obj is not None and self._obj() is None