update to python fastpi
This commit is contained in:
239
Backend/venv/lib/python3.12/site-packages/wrapt/patches.py
Normal file
239
Backend/venv/lib/python3.12/site-packages/wrapt/patches.py
Normal file
@@ -0,0 +1,239 @@
|
||||
import inspect
|
||||
import sys
|
||||
|
||||
from .__wrapt__ import FunctionWrapper
|
||||
|
||||
# Helper functions for applying wrappers to existing functions.
|
||||
|
||||
|
||||
def resolve_path(target, name):
|
||||
"""
|
||||
Resolves the dotted path supplied as `name` to an attribute on a target
|
||||
object. The `target` can be a module, class, or instance of a class. If the
|
||||
`target` argument is a string, it is assumed to be the name of a module,
|
||||
which will be imported if necessary and then used as the target object.
|
||||
Returns a tuple containing the parent object holding the attribute lookup
|
||||
resolved to, the attribute name (path prefix removed if present), and the
|
||||
original attribute value.
|
||||
"""
|
||||
|
||||
if isinstance(target, str):
|
||||
__import__(target)
|
||||
target = sys.modules[target]
|
||||
|
||||
parent = target
|
||||
|
||||
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):
|
||||
"""
|
||||
Convenience function for applying a patch to an attribute. Currently this
|
||||
maps to the standard setattr() function, but in the future may be extended
|
||||
to support more complex patching strategies.
|
||||
"""
|
||||
|
||||
setattr(parent, attribute, replacement)
|
||||
|
||||
|
||||
def wrap_object(target, name, factory, args=(), kwargs={}):
|
||||
"""
|
||||
Wraps an object which is the attribute of a target object with a wrapper
|
||||
object created by the `factory` function. The `target` can be a module,
|
||||
class, or instance of a class. In the special case of `target` being a
|
||||
string, it is assumed to be the name of a module, with the module being
|
||||
imported if necessary and then used as the target object. The `name` is a
|
||||
string representing the dotted path to the attribute. The `factory` function
|
||||
should accept the original object and may accept additional positional and
|
||||
keyword arguments which will be set by unpacking input arguments using
|
||||
`*args` and `**kwargs` calling conventions. The factory function should
|
||||
return a new object that will replace the original object.
|
||||
"""
|
||||
|
||||
(parent, attribute, original) = resolve_path(target, 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:
|
||||
|
||||
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={}):
|
||||
"""
|
||||
Wraps an object which is the attribute of a class instance with a wrapper
|
||||
object created by the `factory` function. It does this by patching the
|
||||
class, not the instance, with a descriptor that intercepts access to the
|
||||
instance attribute. The `module` can be a module, class, or instance of a
|
||||
class. In the special case of `module` being a string, it is assumed to be
|
||||
the name of a module, with the module being imported if necessary and then
|
||||
used as the target object. The `name` is a string representing the dotted
|
||||
path to the attribute. The `factory` function should accept the original
|
||||
object and may accept additional positional and keyword arguments which will
|
||||
be set by unpacking input arguments using `*args` and `**kwargs` calling
|
||||
conventions. The factory function should return a new object that will
|
||||
replace the original object.
|
||||
"""
|
||||
|
||||
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):
|
||||
"""
|
||||
Creates a decorator for wrapping a function with a `wrapper` function.
|
||||
The decorator which is returned may also be applied to any other callable
|
||||
objects such as lambda functions, methods, classmethods, and staticmethods,
|
||||
or objects which implement the `__call__()` method. The `wrapper` function
|
||||
should accept the `wrapped` function, `instance`, `args`, and `kwargs`,
|
||||
arguments and return the result of calling the wrapped function or some
|
||||
other appropriate value.
|
||||
"""
|
||||
|
||||
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(target, name, wrapper):
|
||||
"""
|
||||
Wraps a function which is the attribute of a target object with a `wrapper`
|
||||
function. The `target` can be a module, class, or instance of a class. In
|
||||
the special case of `target` being a string, it is assumed to be the name
|
||||
of a module, with the module being imported if necessary. The `name` is a
|
||||
string representing the dotted path to the attribute. The `wrapper` function
|
||||
should accept the `wrapped` function, `instance`, `args`, and `kwargs`
|
||||
arguments, and would return the result of calling the wrapped attribute or
|
||||
some other appropriate value.
|
||||
"""
|
||||
|
||||
return wrap_object(target, name, FunctionWrapper, (wrapper,))
|
||||
|
||||
|
||||
def patch_function_wrapper(target, name, enabled=None):
|
||||
"""
|
||||
Creates a decorator which can be applied to a wrapper function, where the
|
||||
wrapper function will be used to wrap a function which is the attribute of
|
||||
a target object. The `target` can be a module, class, or instance of a class.
|
||||
In the special case of `target` being a string, it is assumed to be the name
|
||||
of a module, with the module being imported if necessary. The `name` is a
|
||||
string representing the dotted path to the attribute. The `enabled`
|
||||
argument can be a boolean or a callable that returns a boolean. When a
|
||||
callable is provided, it will be called each time the wrapper is invoked to
|
||||
determine if the wrapper function should be executed or whether the wrapped
|
||||
function should be called directly. If `enabled` is not provided, the
|
||||
wrapper is enabled by default.
|
||||
"""
|
||||
|
||||
def _wrapper(wrapper):
|
||||
return wrap_object(target, name, FunctionWrapper, (wrapper, enabled))
|
||||
|
||||
return _wrapper
|
||||
|
||||
|
||||
def transient_function_wrapper(target, name):
|
||||
"""Creates a decorator that patches a target function with a wrapper
|
||||
function, but only for the duration of the call that the decorator was
|
||||
applied to. The `target` can be a module, class, or instance of a class.
|
||||
In the special case of `target` being a string, it is assumed to be the name
|
||||
of a module, with the module being imported if necessary. The `name` is a
|
||||
string representing the dotted path to the attribute.
|
||||
"""
|
||||
|
||||
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(target, 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
|
||||
Reference in New Issue
Block a user