aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/wrapt/weakrefs.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/wrapt/weakrefs.py')
-rw-r--r--.venv/lib/python3.12/site-packages/wrapt/weakrefs.py98
1 files changed, 98 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/wrapt/weakrefs.py b/.venv/lib/python3.12/site-packages/wrapt/weakrefs.py
new file mode 100644
index 00000000..f931b60d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/wrapt/weakrefs.py
@@ -0,0 +1,98 @@
+import functools
+import weakref
+
+from .__wrapt__ import ObjectProxy, _FunctionWrapperBase
+
+# A weak function proxy. This will work on instance methods, class
+# methods, static methods and regular functions. Special treatment is
+# needed for the method types because the bound method is effectively a
+# transient object and applying a weak reference to one will immediately
+# result in it being destroyed and the weakref callback called. The weak
+# reference is therefore applied to the instance the method is bound to
+# and the original function. The function is then rebound at the point
+# of a call via the weak function proxy.
+
+def _weak_function_proxy_callback(ref, proxy, callback):
+ if proxy._self_expired:
+ return
+
+ proxy._self_expired = True
+
+ # This could raise an exception. We let it propagate back and let
+ # the weakref.proxy() deal with it, at which point it generally
+ # prints out a short error message direct to stderr and keeps going.
+
+ if callback is not None:
+ callback(proxy)
+
+class WeakFunctionProxy(ObjectProxy):
+
+ __slots__ = ('_self_expired', '_self_instance')
+
+ def __init__(self, wrapped, callback=None):
+ # We need to determine if the wrapped function is actually a
+ # bound method. In the case of a bound method, we need to keep a
+ # reference to the original unbound function and the instance.
+ # This is necessary because if we hold a reference to the bound
+ # function, it will be the only reference and given it is a
+ # temporary object, it will almost immediately expire and
+ # the weakref callback triggered. So what is done is that we
+ # hold a reference to the instance and unbound function and
+ # when called bind the function to the instance once again and
+ # then call it. Note that we avoid using a nested function for
+ # the callback here so as not to cause any odd reference cycles.
+
+ _callback = callback and functools.partial(
+ _weak_function_proxy_callback, proxy=self,
+ callback=callback)
+
+ self._self_expired = False
+
+ if isinstance(wrapped, _FunctionWrapperBase):
+ self._self_instance = weakref.ref(wrapped._self_instance,
+ _callback)
+
+ if wrapped._self_parent is not None:
+ super(WeakFunctionProxy, self).__init__(
+ weakref.proxy(wrapped._self_parent, _callback))
+
+ else:
+ super(WeakFunctionProxy, self).__init__(
+ weakref.proxy(wrapped, _callback))
+
+ return
+
+ try:
+ self._self_instance = weakref.ref(wrapped.__self__, _callback)
+
+ super(WeakFunctionProxy, self).__init__(
+ weakref.proxy(wrapped.__func__, _callback))
+
+ except AttributeError:
+ self._self_instance = None
+
+ super(WeakFunctionProxy, self).__init__(
+ weakref.proxy(wrapped, _callback))
+
+ def __call__(*args, **kwargs):
+ def _unpack_self(self, *args):
+ return self, args
+
+ self, args = _unpack_self(*args)
+
+ # We perform a boolean check here on the instance and wrapped
+ # function as that will trigger the reference error prior to
+ # calling if the reference had expired.
+
+ instance = self._self_instance and self._self_instance()
+ function = self.__wrapped__ and self.__wrapped__
+
+ # If the wrapped function was originally a bound function, for
+ # which we retained a reference to the instance and the unbound
+ # function we need to rebind the function and then call it. If
+ # not just called the wrapped function.
+
+ if instance is None:
+ return self.__wrapped__(*args, **kwargs)
+
+ return function.__get__(instance, type(instance))(*args, **kwargs)