123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- """
- weakref_backports is a partial backport of the weakref module for python
- versions below 3.4.
- Copyright (C) 2013 Python Software Foundation, see license.python.txt for
- details.
- The following changes were made to the original sources during backporting:
- * Added `self` to `super` calls.
- * Removed `from None` when raising exceptions.
- """
- from weakref import ref
- class WeakMethod(ref):
- """
- A custom `weakref.ref` subclass which simulates a weak reference to
- a bound method, working around the lifetime problem of bound methods.
- """
- __slots__ = "_func_ref", "_meth_type", "_alive", "__weakref__"
- def __new__(cls, meth, callback=None):
- try:
- obj = meth.__self__
- func = meth.__func__
- except AttributeError:
- raise TypeError("argument should be a bound method, not {}"
- .format(type(meth)))
- def _cb(arg):
- # The self-weakref trick is needed to avoid creating a reference
- # cycle.
- self = self_wr()
- if self._alive:
- self._alive = False
- if callback is not None:
- callback(self)
- self = ref.__new__(cls, obj, _cb)
- self._func_ref = ref(func, _cb)
- self._meth_type = type(meth)
- self._alive = True
- self_wr = ref(self)
- return self
- def __call__(self):
- obj = super(WeakMethod, self).__call__()
- func = self._func_ref()
- if obj is None or func is None:
- return None
- return self._meth_type(func, obj)
- def __eq__(self, other):
- if isinstance(other, WeakMethod):
- if not self._alive or not other._alive:
- return self is other
- return ref.__eq__(self, other) and self._func_ref == other._func_ref
- return False
- def __ne__(self, other):
- if isinstance(other, WeakMethod):
- if not self._alive or not other._alive:
- return self is not other
- return ref.__ne__(self, other) or self._func_ref != other._func_ref
- return True
- __hash__ = ref.__hash__
|