about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/wrapt/patches.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/wrapt/patches.py')
-rw-r--r--.venv/lib/python3.12/site-packages/wrapt/patches.py141
1 files changed, 141 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/wrapt/patches.py b/.venv/lib/python3.12/site-packages/wrapt/patches.py
new file mode 100644
index 00000000..e22adf7c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/wrapt/patches.py
@@ -0,0 +1,141 @@
+import inspect
+import sys
+
+PY2 = sys.version_info[0] == 2
+
+if PY2:
+    string_types = basestring,
+else:
+    string_types = str,
+
+from .__wrapt__ import FunctionWrapper
+
+# Helper functions for applying wrappers to existing functions.
+
+def resolve_path(module, name):
+    if isinstance(module, string_types):
+        __import__(module)
+        module = sys.modules[module]
+
+    parent = module
+
+    path = name.split('.')
+    attribute = path[0]
+
+    # We can't just always use getattr() because in doing
+    # that on a class it will cause binding to occur which
+    # will complicate things later and cause some things not
+    # to work. For the case of a class we therefore access
+    # the __dict__ directly. To cope though with the wrong
+    # class being given to us, or a method being moved into
+    # a base class, we need to walk the class hierarchy to
+    # work out exactly which __dict__ the method was defined
+    # in, as accessing it from __dict__ will fail if it was
+    # not actually on the class given. Fallback to using
+    # getattr() if we can't find it. If it truly doesn't
+    # exist, then that will fail.
+
+    def lookup_attribute(parent, attribute):
+        if inspect.isclass(parent):
+            for cls in inspect.getmro(parent):
+                if attribute in vars(cls):
+                    return vars(cls)[attribute]
+            else:
+                return getattr(parent, attribute)
+        else:
+            return getattr(parent, attribute)
+
+    original = lookup_attribute(parent, attribute)
+
+    for attribute in path[1:]:
+        parent = original
+        original = lookup_attribute(parent, attribute)
+
+    return (parent, attribute, original)
+
+def apply_patch(parent, attribute, replacement):
+    setattr(parent, attribute, replacement)
+
+def wrap_object(module, name, factory, args=(), kwargs={}):
+    (parent, attribute, original) = resolve_path(module, name)
+    wrapper = factory(original, *args, **kwargs)
+    apply_patch(parent, attribute, wrapper)
+    return wrapper
+
+# Function for applying a proxy object to an attribute of a class
+# instance. The wrapper works by defining an attribute of the same name
+# on the class which is a descriptor and which intercepts access to the
+# instance attribute. Note that this cannot be used on attributes which
+# are themselves defined by a property object.
+
+class AttributeWrapper(object):
+
+    def __init__(self, attribute, factory, args, kwargs):
+        self.attribute = attribute
+        self.factory = factory
+        self.args = args
+        self.kwargs = kwargs
+
+    def __get__(self, instance, owner):
+        value = instance.__dict__[self.attribute]
+        return self.factory(value, *self.args, **self.kwargs)
+
+    def __set__(self, instance, value):
+        instance.__dict__[self.attribute] = value
+
+    def __delete__(self, instance):
+        del instance.__dict__[self.attribute]
+
+def wrap_object_attribute(module, name, factory, args=(), kwargs={}):
+    path, attribute = name.rsplit('.', 1)
+    parent = resolve_path(module, path)[2]
+    wrapper = AttributeWrapper(attribute, factory, args, kwargs)
+    apply_patch(parent, attribute, wrapper)
+    return wrapper
+
+# Functions for creating a simple decorator using a FunctionWrapper,
+# plus short cut functions for applying wrappers to functions. These are
+# for use when doing monkey patching. For a more featured way of
+# creating decorators see the decorator decorator instead.
+
+def function_wrapper(wrapper):
+    def _wrapper(wrapped, instance, args, kwargs):
+        target_wrapped = args[0]
+        if instance is None:
+            target_wrapper = wrapper
+        elif inspect.isclass(instance):
+            target_wrapper = wrapper.__get__(None, instance)
+        else:
+            target_wrapper = wrapper.__get__(instance, type(instance))
+        return FunctionWrapper(target_wrapped, target_wrapper)
+    return FunctionWrapper(wrapper, _wrapper)
+
+def wrap_function_wrapper(module, name, wrapper):
+    return wrap_object(module, name, FunctionWrapper, (wrapper,))
+
+def patch_function_wrapper(module, name, enabled=None):
+    def _wrapper(wrapper):
+        return wrap_object(module, name, FunctionWrapper, (wrapper, enabled))
+    return _wrapper
+
+def transient_function_wrapper(module, name):
+    def _decorator(wrapper):
+        def _wrapper(wrapped, instance, args, kwargs):
+            target_wrapped = args[0]
+            if instance is None:
+                target_wrapper = wrapper
+            elif inspect.isclass(instance):
+                target_wrapper = wrapper.__get__(None, instance)
+            else:
+                target_wrapper = wrapper.__get__(instance, type(instance))
+            def _execute(wrapped, instance, args, kwargs):
+                (parent, attribute, original) = resolve_path(module, name)
+                replacement = FunctionWrapper(original, target_wrapper)
+                setattr(parent, attribute, replacement)
+                try:
+                    return wrapped(*args, **kwargs)
+                finally:
+                    setattr(parent, attribute, original)
+            return FunctionWrapper(target_wrapped, _execute)
+        return FunctionWrapper(wrapper, _wrapper)
+    return _decorator