diff options
Diffstat (limited to 'venv/Lib/site-packages/wrapt')
-rw-r--r-- | venv/Lib/site-packages/wrapt/__init__.py | 16 | ||||
-rw-r--r-- | venv/Lib/site-packages/wrapt/__pycache__/__init__.cpython-37.pyc | bin | 984 -> 0 bytes | |||
-rw-r--r-- | venv/Lib/site-packages/wrapt/__pycache__/decorators.cpython-37.pyc | bin | 8918 -> 0 bytes | |||
-rw-r--r-- | venv/Lib/site-packages/wrapt/__pycache__/importer.cpython-37.pyc | bin | 4242 -> 0 bytes | |||
-rw-r--r-- | venv/Lib/site-packages/wrapt/__pycache__/wrappers.cpython-37.pyc | bin | 24030 -> 0 bytes | |||
-rw-r--r-- | venv/Lib/site-packages/wrapt/decorators.py | 514 | ||||
-rw-r--r-- | venv/Lib/site-packages/wrapt/importer.py | 230 | ||||
-rw-r--r-- | venv/Lib/site-packages/wrapt/wrappers.py | 943 |
8 files changed, 0 insertions, 1703 deletions
diff --git a/venv/Lib/site-packages/wrapt/__init__.py b/venv/Lib/site-packages/wrapt/__init__.py deleted file mode 100644 index 8e858a0..0000000 --- a/venv/Lib/site-packages/wrapt/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -__version_info__ = ('1', '11', '2') -__version__ = '.'.join(__version_info__) - -from .wrappers import (ObjectProxy, CallableObjectProxy, FunctionWrapper, - BoundFunctionWrapper, WeakFunctionProxy, PartialCallableObjectProxy, - resolve_path, apply_patch, wrap_object, wrap_object_attribute, - function_wrapper, wrap_function_wrapper, patch_function_wrapper, - transient_function_wrapper) - -from .decorators import (adapter_factory, AdapterFactory, decorator, - synchronized) - -from .importer import (register_post_import_hook, when_imported, - notify_module_loaded, discover_post_import_hooks) - -from inspect import getcallargs diff --git a/venv/Lib/site-packages/wrapt/__pycache__/__init__.cpython-37.pyc b/venv/Lib/site-packages/wrapt/__pycache__/__init__.cpython-37.pyc Binary files differdeleted file mode 100644 index 2e30dcf..0000000 --- a/venv/Lib/site-packages/wrapt/__pycache__/__init__.cpython-37.pyc +++ /dev/null diff --git a/venv/Lib/site-packages/wrapt/__pycache__/decorators.cpython-37.pyc b/venv/Lib/site-packages/wrapt/__pycache__/decorators.cpython-37.pyc Binary files differdeleted file mode 100644 index aee61e9..0000000 --- a/venv/Lib/site-packages/wrapt/__pycache__/decorators.cpython-37.pyc +++ /dev/null diff --git a/venv/Lib/site-packages/wrapt/__pycache__/importer.cpython-37.pyc b/venv/Lib/site-packages/wrapt/__pycache__/importer.cpython-37.pyc Binary files differdeleted file mode 100644 index d468b2d..0000000 --- a/venv/Lib/site-packages/wrapt/__pycache__/importer.cpython-37.pyc +++ /dev/null diff --git a/venv/Lib/site-packages/wrapt/__pycache__/wrappers.cpython-37.pyc b/venv/Lib/site-packages/wrapt/__pycache__/wrappers.cpython-37.pyc Binary files differdeleted file mode 100644 index c21924d..0000000 --- a/venv/Lib/site-packages/wrapt/__pycache__/wrappers.cpython-37.pyc +++ /dev/null diff --git a/venv/Lib/site-packages/wrapt/decorators.py b/venv/Lib/site-packages/wrapt/decorators.py deleted file mode 100644 index 11e11de..0000000 --- a/venv/Lib/site-packages/wrapt/decorators.py +++ /dev/null @@ -1,514 +0,0 @@ -"""This module implements decorators for implementing other decorators -as well as some commonly used decorators. - -""" - -import sys - -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - -if PY3: - string_types = str, - - import builtins - exec_ = getattr(builtins, "exec") - del builtins - -else: - string_types = basestring, - - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - -from functools import partial -from inspect import ismethod, isclass, formatargspec -from collections import namedtuple -from threading import Lock, RLock - -try: - from inspect import signature -except ImportError: - pass - -from .wrappers import (FunctionWrapper, BoundFunctionWrapper, ObjectProxy, - CallableObjectProxy) - -# Adapter wrapper for the wrapped function which will overlay certain -# properties from the adapter function onto the wrapped function so that -# functions such as inspect.getargspec(), inspect.getfullargspec(), -# inspect.signature() and inspect.getsource() return the correct results -# one would expect. - -class _AdapterFunctionCode(CallableObjectProxy): - - def __init__(self, wrapped_code, adapter_code): - super(_AdapterFunctionCode, self).__init__(wrapped_code) - self._self_adapter_code = adapter_code - - @property - def co_argcount(self): - return self._self_adapter_code.co_argcount - - @property - def co_code(self): - return self._self_adapter_code.co_code - - @property - def co_flags(self): - return self._self_adapter_code.co_flags - - @property - def co_kwonlyargcount(self): - return self._self_adapter_code.co_kwonlyargcount - - @property - def co_varnames(self): - return self._self_adapter_code.co_varnames - -class _AdapterFunctionSurrogate(CallableObjectProxy): - - def __init__(self, wrapped, adapter): - super(_AdapterFunctionSurrogate, self).__init__(wrapped) - self._self_adapter = adapter - - @property - def __code__(self): - return _AdapterFunctionCode(self.__wrapped__.__code__, - self._self_adapter.__code__) - - @property - def __defaults__(self): - return self._self_adapter.__defaults__ - - @property - def __kwdefaults__(self): - return self._self_adapter.__kwdefaults__ - - @property - def __signature__(self): - if 'signature' not in globals(): - return self._self_adapter.__signature__ - else: - # Can't allow this to fail on Python 3 else it falls - # through to using __wrapped__, but that will be the - # wrong function we want to derive the signature - # from. Thus generate the signature ourselves. - - return signature(self._self_adapter) - - if PY2: - func_code = __code__ - func_defaults = __defaults__ - -class _BoundAdapterWrapper(BoundFunctionWrapper): - - @property - def __func__(self): - return _AdapterFunctionSurrogate(self.__wrapped__.__func__, - self._self_parent._self_adapter) - - if PY2: - im_func = __func__ - -class AdapterWrapper(FunctionWrapper): - - __bound_function_wrapper__ = _BoundAdapterWrapper - - def __init__(self, *args, **kwargs): - adapter = kwargs.pop('adapter') - super(AdapterWrapper, self).__init__(*args, **kwargs) - self._self_surrogate = _AdapterFunctionSurrogate( - self.__wrapped__, adapter) - self._self_adapter = adapter - - @property - def __code__(self): - return self._self_surrogate.__code__ - - @property - def __defaults__(self): - return self._self_surrogate.__defaults__ - - @property - def __kwdefaults__(self): - return self._self_surrogate.__kwdefaults__ - - if PY2: - func_code = __code__ - func_defaults = __defaults__ - - @property - def __signature__(self): - return self._self_surrogate.__signature__ - -class AdapterFactory(object): - def __call__(self, wrapped): - raise NotImplementedError() - -class DelegatedAdapterFactory(AdapterFactory): - def __init__(self, factory): - super(DelegatedAdapterFactory, self).__init__() - self.factory = factory - def __call__(self, wrapped): - return self.factory(wrapped) - -adapter_factory = DelegatedAdapterFactory - -# Decorator for creating other decorators. This decorator and the -# wrappers which they use are designed to properly preserve any name -# attributes, function signatures etc, in addition to the wrappers -# themselves acting like a transparent proxy for the original wrapped -# function so the wrapper is effectively indistinguishable from the -# original wrapped function. - -def decorator(wrapper=None, enabled=None, adapter=None): - # The decorator should be supplied with a single positional argument - # which is the wrapper function to be used to implement the - # decorator. This may be preceded by a step whereby the keyword - # arguments are supplied to customise the behaviour of the - # decorator. The 'adapter' argument is used to optionally denote a - # separate function which is notionally used by an adapter - # decorator. In that case parts of the function '__code__' and - # '__defaults__' attributes are used from the adapter function - # rather than those of the wrapped function. This allows for the - # argument specification from inspect.getargspec() and similar - # functions to be overridden with a prototype for a different - # function than what was wrapped. The 'enabled' argument provides a - # way to enable/disable the use of the decorator. If the type of - # 'enabled' is a boolean, then it is evaluated immediately and the - # wrapper not even applied if it is False. If not a boolean, it will - # be evaluated when the wrapper is called for an unbound wrapper, - # and when binding occurs for a bound wrapper. When being evaluated, - # if 'enabled' is callable it will be called to obtain the value to - # be checked. If False, the wrapper will not be called and instead - # the original wrapped function will be called directly instead. - - if wrapper is not None: - # Helper function for creating wrapper of the appropriate - # time when we need it down below. - - def _build(wrapped, wrapper, enabled=None, adapter=None): - if adapter: - if isinstance(adapter, AdapterFactory): - adapter = adapter(wrapped) - - if not callable(adapter): - ns = {} - if not isinstance(adapter, string_types): - adapter = formatargspec(*adapter) - exec_('def adapter{}: pass'.format(adapter), ns, ns) - adapter = ns['adapter'] - - return AdapterWrapper(wrapped=wrapped, wrapper=wrapper, - enabled=enabled, adapter=adapter) - - return FunctionWrapper(wrapped=wrapped, wrapper=wrapper, - enabled=enabled) - - # The wrapper has been provided so return the final decorator. - # The decorator is itself one of our function wrappers so we - # can determine when it is applied to functions, instance methods - # or class methods. This allows us to bind the instance or class - # method so the appropriate self or cls attribute is supplied - # when it is finally called. - - def _wrapper(wrapped, instance, args, kwargs): - # We first check for the case where the decorator was applied - # to a class type. - # - # @decorator - # class mydecoratorclass(object): - # def __init__(self, arg=None): - # self.arg = arg - # def __call__(self, wrapped, instance, args, kwargs): - # return wrapped(*args, **kwargs) - # - # @mydecoratorclass(arg=1) - # def function(): - # pass - # - # In this case an instance of the class is to be used as the - # decorator wrapper function. If args was empty at this point, - # then it means that there were optional keyword arguments - # supplied to be used when creating an instance of the class - # to be used as the wrapper function. - - if instance is None and isclass(wrapped) and not args: - # We still need to be passed the target function to be - # wrapped as yet, so we need to return a further function - # to be able to capture it. - - def _capture(target_wrapped): - # Now have the target function to be wrapped and need - # to create an instance of the class which is to act - # as the decorator wrapper function. Before we do that, - # we need to first check that use of the decorator - # hadn't been disabled by a simple boolean. If it was, - # the target function to be wrapped is returned instead. - - _enabled = enabled - if type(_enabled) is bool: - if not _enabled: - return target_wrapped - _enabled = None - - # Now create an instance of the class which is to act - # as the decorator wrapper function. Any arguments had - # to be supplied as keyword only arguments so that is - # all we pass when creating it. - - target_wrapper = wrapped(**kwargs) - - # Finally build the wrapper itself and return it. - - return _build(target_wrapped, target_wrapper, - _enabled, adapter) - - return _capture - - # We should always have the target function to be wrapped at - # this point as the first (and only) value in args. - - target_wrapped = args[0] - - # Need to now check that use of the decorator hadn't been - # disabled by a simple boolean. If it was, then target - # function to be wrapped is returned instead. - - _enabled = enabled - if type(_enabled) is bool: - if not _enabled: - return target_wrapped - _enabled = None - - # We now need to build the wrapper, but there are a couple of - # different cases we need to consider. - - if instance is None: - if isclass(wrapped): - # In this case the decorator was applied to a class - # type but optional keyword arguments were not supplied - # for initialising an instance of the class to be used - # as the decorator wrapper function. - # - # @decorator - # class mydecoratorclass(object): - # def __init__(self, arg=None): - # self.arg = arg - # def __call__(self, wrapped, instance, - # args, kwargs): - # return wrapped(*args, **kwargs) - # - # @mydecoratorclass - # def function(): - # pass - # - # We still need to create an instance of the class to - # be used as the decorator wrapper function, but no - # arguments are pass. - - target_wrapper = wrapped() - - else: - # In this case the decorator was applied to a normal - # function, or possibly a static method of a class. - # - # @decorator - # def mydecoratorfuntion(wrapped, instance, - # args, kwargs): - # return wrapped(*args, **kwargs) - # - # @mydecoratorfunction - # def function(): - # pass - # - # That normal function becomes the decorator wrapper - # function. - - target_wrapper = wrapper - - else: - if isclass(instance): - # In this case the decorator was applied to a class - # method. - # - # class myclass(object): - # @decorator - # @classmethod - # def decoratorclassmethod(cls, wrapped, - # instance, args, kwargs): - # return wrapped(*args, **kwargs) - # - # instance = myclass() - # - # @instance.decoratorclassmethod - # def function(): - # pass - # - # This one is a bit strange because binding was actually - # performed on the wrapper created by our decorator - # factory. We need to apply that binding to the decorator - # wrapper function which which the decorator factory - # was applied to. - - target_wrapper = wrapper.__get__(None, instance) - - else: - # In this case the decorator was applied to an instance - # method. - # - # class myclass(object): - # @decorator - # def decoratorclassmethod(self, wrapped, - # instance, args, kwargs): - # return wrapped(*args, **kwargs) - # - # instance = myclass() - # - # @instance.decoratorclassmethod - # def function(): - # pass - # - # This one is a bit strange because binding was actually - # performed on the wrapper created by our decorator - # factory. We need to apply that binding to the decorator - # wrapper function which which the decorator factory - # was applied to. - - target_wrapper = wrapper.__get__(instance, type(instance)) - - # Finally build the wrapper itself and return it. - - return _build(target_wrapped, target_wrapper, _enabled, adapter) - - # We first return our magic function wrapper here so we can - # determine in what context the decorator factory was used. In - # other words, it is itself a universal decorator. The decorator - # function is used as the adapter so that linters see a signature - # corresponding to the decorator and not the wrapper it is being - # applied to. - - return _build(wrapper, _wrapper, adapter=decorator) - - else: - # The wrapper still has not been provided, so we are just - # collecting the optional keyword arguments. Return the - # decorator again wrapped in a partial using the collected - # arguments. - - return partial(decorator, enabled=enabled, adapter=adapter) - -# Decorator for implementing thread synchronization. It can be used as a -# decorator, in which case the synchronization context is determined by -# what type of function is wrapped, or it can also be used as a context -# manager, where the user needs to supply the correct synchronization -# context. It is also possible to supply an object which appears to be a -# synchronization primitive of some sort, by virtue of having release() -# and acquire() methods. In that case that will be used directly as the -# synchronization primitive without creating a separate lock against the -# derived or supplied context. - -def synchronized(wrapped): - # Determine if being passed an object which is a synchronization - # primitive. We can't check by type for Lock, RLock, Semaphore etc, - # as the means of creating them isn't the type. Therefore use the - # existence of acquire() and release() methods. This is more - # extensible anyway as it allows custom synchronization mechanisms. - - if hasattr(wrapped, 'acquire') and hasattr(wrapped, 'release'): - # We remember what the original lock is and then return a new - # decorator which accesses and locks it. When returning the new - # decorator we wrap it with an object proxy so we can override - # the context manager methods in case it is being used to wrap - # synchronized statements with a 'with' statement. - - lock = wrapped - - @decorator - def _synchronized(wrapped, instance, args, kwargs): - # Execute the wrapped function while the original supplied - # lock is held. - - with lock: - return wrapped(*args, **kwargs) - - class _PartialDecorator(CallableObjectProxy): - - def __enter__(self): - lock.acquire() - return lock - - def __exit__(self, *args): - lock.release() - - return _PartialDecorator(wrapped=_synchronized) - - # Following only apply when the lock is being created automatically - # based on the context of what was supplied. In this case we supply - # a final decorator, but need to use FunctionWrapper directly as we - # want to derive from it to add context manager methods in case it is - # being used to wrap synchronized statements with a 'with' statement. - - def _synchronized_lock(context): - # Attempt to retrieve the lock for the specific context. - - lock = vars(context).get('_synchronized_lock', None) - - if lock is None: - # There is no existing lock defined for the context we - # are dealing with so we need to create one. This needs - # to be done in a way to guarantee there is only one - # created, even if multiple threads try and create it at - # the same time. We can't always use the setdefault() - # method on the __dict__ for the context. This is the - # case where the context is a class, as __dict__ is - # actually a dictproxy. What we therefore do is use a - # meta lock on this wrapper itself, to control the - # creation and assignment of the lock attribute against - # the context. - - with synchronized._synchronized_meta_lock: - # We need to check again for whether the lock we want - # exists in case two threads were trying to create it - # at the same time and were competing to create the - # meta lock. - - lock = vars(context).get('_synchronized_lock', None) - - if lock is None: - lock = RLock() - setattr(context, '_synchronized_lock', lock) - - return lock - - def _synchronized_wrapper(wrapped, instance, args, kwargs): - # Execute the wrapped function while the lock for the - # desired context is held. If instance is None then the - # wrapped function is used as the context. - - with _synchronized_lock(instance or wrapped): - return wrapped(*args, **kwargs) - - class _FinalDecorator(FunctionWrapper): - - def __enter__(self): - self._self_lock = _synchronized_lock(self.__wrapped__) - self._self_lock.acquire() - return self._self_lock - - def __exit__(self, *args): - self._self_lock.release() - - return _FinalDecorator(wrapped=wrapped, wrapper=_synchronized_wrapper) - -synchronized._synchronized_meta_lock = Lock() diff --git a/venv/Lib/site-packages/wrapt/importer.py b/venv/Lib/site-packages/wrapt/importer.py deleted file mode 100644 index 9e617cd..0000000 --- a/venv/Lib/site-packages/wrapt/importer.py +++ /dev/null @@ -1,230 +0,0 @@ -"""This module implements a post import hook mechanism styled after what is -described in PEP-369. Note that it doesn't cope with modules being reloaded. - -""" - -import sys -import threading - -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - -if PY3: - import importlib - string_types = str, -else: - string_types = basestring, - -from .decorators import synchronized - -# The dictionary registering any post import hooks to be triggered once -# the target module has been imported. Once a module has been imported -# and the hooks fired, the list of hooks recorded against the target -# module will be truncacted but the list left in the dictionary. This -# acts as a flag to indicate that the module had already been imported. - -_post_import_hooks = {} -_post_import_hooks_init = False -_post_import_hooks_lock = threading.RLock() - -# Register a new post import hook for the target module name. This -# differs from the PEP-369 implementation in that it also allows the -# hook function to be specified as a string consisting of the name of -# the callback in the form 'module:function'. This will result in a -# proxy callback being registered which will defer loading of the -# specified module containing the callback function until required. - -def _create_import_hook_from_string(name): - def import_hook(module): - module_name, function = name.split(':') - attrs = function.split('.') - __import__(module_name) - callback = sys.modules[module_name] - for attr in attrs: - callback = getattr(callback, attr) - return callback(module) - return import_hook - -@synchronized(_post_import_hooks_lock) -def register_post_import_hook(hook, name): - # Create a deferred import hook if hook is a string name rather than - # a callable function. - - if isinstance(hook, string_types): - hook = _create_import_hook_from_string(hook) - - # Automatically install the import hook finder if it has not already - # been installed. - - global _post_import_hooks_init - - if not _post_import_hooks_init: - _post_import_hooks_init = True - sys.meta_path.insert(0, ImportHookFinder()) - - # Determine if any prior registration of a post import hook for - # the target modules has occurred and act appropriately. - - hooks = _post_import_hooks.get(name, None) - - if hooks is None: - # No prior registration of post import hooks for the target - # module. We need to check whether the module has already been - # imported. If it has we fire the hook immediately and add an - # empty list to the registry to indicate that the module has - # already been imported and hooks have fired. Otherwise add - # the post import hook to the registry. - - module = sys.modules.get(name, None) - - if module is not None: - _post_import_hooks[name] = [] - hook(module) - - else: - _post_import_hooks[name] = [hook] - - elif hooks == []: - # A prior registration of port import hooks for the target - # module was done and the hooks already fired. Fire the hook - # immediately. - - module = sys.modules[name] - hook(module) - - else: - # A prior registration of port import hooks for the target - # module was done but the module has not yet been imported. - - _post_import_hooks[name].append(hook) - -# Register post import hooks defined as package entry points. - -def _create_import_hook_from_entrypoint(entrypoint): - def import_hook(module): - __import__(entrypoint.module_name) - callback = sys.modules[entrypoint.module_name] - for attr in entrypoint.attrs: - callback = getattr(callback, attr) - return callback(module) - return import_hook - -def discover_post_import_hooks(group): - try: - import pkg_resources - except ImportError: - return - - for entrypoint in pkg_resources.iter_entry_points(group=group): - callback = _create_import_hook_from_entrypoint(entrypoint) - register_post_import_hook(callback, entrypoint.name) - -# Indicate that a module has been loaded. Any post import hooks which -# were registered against the target module will be invoked. If an -# exception is raised in any of the post import hooks, that will cause -# the import of the target module to fail. - -@synchronized(_post_import_hooks_lock) -def notify_module_loaded(module): - name = getattr(module, '__name__', None) - hooks = _post_import_hooks.get(name, None) - - if hooks: - _post_import_hooks[name] = [] - - for hook in hooks: - hook(module) - -# A custom module import finder. This intercepts attempts to import -# modules and watches out for attempts to import target modules of -# interest. When a module of interest is imported, then any post import -# hooks which are registered will be invoked. - -class _ImportHookLoader: - - def load_module(self, fullname): - module = sys.modules[fullname] - notify_module_loaded(module) - - return module - -class _ImportHookChainedLoader: - - def __init__(self, loader): - self.loader = loader - - def load_module(self, fullname): - module = self.loader.load_module(fullname) - notify_module_loaded(module) - - return module - -class ImportHookFinder: - - def __init__(self): - self.in_progress = {} - - @synchronized(_post_import_hooks_lock) - def find_module(self, fullname, path=None): - # If the module being imported is not one we have registered - # post import hooks for, we can return immediately. We will - # take no further part in the importing of this module. - - if not fullname in _post_import_hooks: - return None - - # When we are interested in a specific module, we will call back - # into the import system a second time to defer to the import - # finder that is supposed to handle the importing of the module. - # We set an in progress flag for the target module so that on - # the second time through we don't trigger another call back - # into the import system and cause a infinite loop. - - if fullname in self.in_progress: - return None - - self.in_progress[fullname] = True - - # Now call back into the import system again. - - try: - if PY3: - # For Python 3 we need to use find_spec().loader - # from the importlib.util module. It doesn't actually - # import the target module and only finds the - # loader. If a loader is found, we need to return - # our own loader which will then in turn call the - # real loader to import the module and invoke the - # post import hooks. - try: - import importlib.util - loader = importlib.util.find_spec(fullname).loader - except (ImportError, AttributeError): - loader = importlib.find_loader(fullname, path) - if loader: - return _ImportHookChainedLoader(loader) - - else: - # For Python 2 we don't have much choice but to - # call back in to __import__(). This will - # actually cause the module to be imported. If no - # module could be found then ImportError will be - # raised. Otherwise we return a loader which - # returns the already loaded module and invokes - # the post import hooks. - - __import__(fullname) - - return _ImportHookLoader() - - finally: - del self.in_progress[fullname] - -# Decorator for marking that a function should be called as a post -# import hook when the target module is imported. - -def when_imported(name): - def register(hook): - register_post_import_hook(hook, name) - return hook - return register diff --git a/venv/Lib/site-packages/wrapt/wrappers.py b/venv/Lib/site-packages/wrapt/wrappers.py deleted file mode 100644 index 1d6131d..0000000 --- a/venv/Lib/site-packages/wrapt/wrappers.py +++ /dev/null @@ -1,943 +0,0 @@ -import os -import sys -import functools -import operator -import weakref -import inspect - -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - -if PY3: - string_types = str, -else: - string_types = basestring, - -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - return meta("NewBase", bases, {}) - -class _ObjectProxyMethods(object): - - # We use properties to override the values of __module__ and - # __doc__. If we add these in ObjectProxy, the derived class - # __dict__ will still be setup to have string variants of these - # attributes and the rules of descriptors means that they appear to - # take precedence over the properties in the base class. To avoid - # that, we copy the properties into the derived class type itself - # via a meta class. In that way the properties will always take - # precedence. - - @property - def __module__(self): - return self.__wrapped__.__module__ - - @__module__.setter - def __module__(self, value): - self.__wrapped__.__module__ = value - - @property - def __doc__(self): - return self.__wrapped__.__doc__ - - @__doc__.setter - def __doc__(self, value): - self.__wrapped__.__doc__ = value - - # We similar use a property for __dict__. We need __dict__ to be - # explicit to ensure that vars() works as expected. - - @property - def __dict__(self): - return self.__wrapped__.__dict__ - - # Need to also propagate the special __weakref__ attribute for case - # where decorating classes which will define this. If do not define - # it and use a function like inspect.getmembers() on a decorator - # class it will fail. This can't be in the derived classes. - - @property - def __weakref__(self): - return self.__wrapped__.__weakref__ - -class _ObjectProxyMetaType(type): - def __new__(cls, name, bases, dictionary): - # Copy our special properties into the class so that they - # always take precedence over attributes of the same name added - # during construction of a derived class. This is to save - # duplicating the implementation for them in all derived classes. - - dictionary.update(vars(_ObjectProxyMethods)) - - return type.__new__(cls, name, bases, dictionary) - -class ObjectProxy(with_metaclass(_ObjectProxyMetaType)): - - __slots__ = '__wrapped__' - - def __init__(self, wrapped): - object.__setattr__(self, '__wrapped__', wrapped) - - # Python 3.2+ has the __qualname__ attribute, but it does not - # allow it to be overridden using a property and it must instead - # be an actual string object instead. - - try: - object.__setattr__(self, '__qualname__', wrapped.__qualname__) - except AttributeError: - pass - - @property - def __name__(self): - return self.__wrapped__.__name__ - - @__name__.setter - def __name__(self, value): - self.__wrapped__.__name__ = value - - @property - def __class__(self): - return self.__wrapped__.__class__ - - @__class__.setter - def __class__(self, value): - self.__wrapped__.__class__ = value - - @property - def __annotations__(self): - return self.__wrapped__.__annotations__ - - @__annotations__.setter - def __annotations__(self, value): - self.__wrapped__.__annotations__ = value - - def __dir__(self): - return dir(self.__wrapped__) - - def __str__(self): - return str(self.__wrapped__) - - if PY3: - def __bytes__(self): - return bytes(self.__wrapped__) - - def __repr__(self): - return '<{} at 0x{:x} for {} at 0x{:x}>'.format( - type(self).__name__, id(self), - type(self.__wrapped__).__name__, - id(self.__wrapped__)) - - def __reversed__(self): - return reversed(self.__wrapped__) - - if PY3: - def __round__(self): - return round(self.__wrapped__) - - def __lt__(self, other): - return self.__wrapped__ < other - - def __le__(self, other): - return self.__wrapped__ <= other - - def __eq__(self, other): - return self.__wrapped__ == other - - def __ne__(self, other): - return self.__wrapped__ != other - - def __gt__(self, other): - return self.__wrapped__ > other - - def __ge__(self, other): - return self.__wrapped__ >= other - - def __hash__(self): - return hash(self.__wrapped__) - - def __nonzero__(self): - return bool(self.__wrapped__) - - def __bool__(self): - return bool(self.__wrapped__) - - def __setattr__(self, name, value): - if name.startswith('_self_'): - object.__setattr__(self, name, value) - - elif name == '__wrapped__': - object.__setattr__(self, name, value) - try: - object.__delattr__(self, '__qualname__') - except AttributeError: - pass - try: - object.__setattr__(self, '__qualname__', value.__qualname__) - except AttributeError: - pass - - elif name == '__qualname__': - setattr(self.__wrapped__, name, value) - object.__setattr__(self, name, value) - - elif hasattr(type(self), name): - object.__setattr__(self, name, value) - - else: - setattr(self.__wrapped__, name, value) - - def __getattr__(self, name): - # If we are being to lookup '__wrapped__' then the - # '__init__()' method cannot have been called. - - if name == '__wrapped__': - raise ValueError('wrapper has not been initialised') - - return getattr(self.__wrapped__, name) - - def __delattr__(self, name): - if name.startswith('_self_'): - object.__delattr__(self, name) - - elif name == '__wrapped__': - raise TypeError('__wrapped__ must be an object') - - elif name == '__qualname__': - object.__delattr__(self, name) - delattr(self.__wrapped__, name) - - elif hasattr(type(self), name): - object.__delattr__(self, name) - - else: - delattr(self.__wrapped__, name) - - def __add__(self, other): - return self.__wrapped__ + other - - def __sub__(self, other): - return self.__wrapped__ - other - - def __mul__(self, other): - return self.__wrapped__ * other - - def __div__(self, other): - return operator.div(self.__wrapped__, other) - - def __truediv__(self, other): - return operator.truediv(self.__wrapped__, other) - - def __floordiv__(self, other): - return self.__wrapped__ // other - - def __mod__(self, other): - return self.__wrapped__ % other - - def __divmod__(self, other): - return divmod(self.__wrapped__, other) - - def __pow__(self, other, *args): - return pow(self.__wrapped__, other, *args) - - def __lshift__(self, other): - return self.__wrapped__ << other - - def __rshift__(self, other): - return self.__wrapped__ >> other - - def __and__(self, other): - return self.__wrapped__ & other - - def __xor__(self, other): - return self.__wrapped__ ^ other - - def __or__(self, other): - return self.__wrapped__ | other - - def __radd__(self, other): - return other + self.__wrapped__ - - def __rsub__(self, other): - return other - self.__wrapped__ - - def __rmul__(self, other): - return other * self.__wrapped__ - - def __rdiv__(self, other): - return operator.div(other, self.__wrapped__) - - def __rtruediv__(self, other): - return operator.truediv(other, self.__wrapped__) - - def __rfloordiv__(self, other): - return other // self.__wrapped__ - - def __rmod__(self, other): - return other % self.__wrapped__ - - def __rdivmod__(self, other): - return divmod(other, self.__wrapped__) - - def __rpow__(self, other, *args): - return pow(other, self.__wrapped__, *args) - - def __rlshift__(self, other): - return other << self.__wrapped__ - - def __rrshift__(self, other): - return other >> self.__wrapped__ - - def __rand__(self, other): - return other & self.__wrapped__ - - def __rxor__(self, other): - return other ^ self.__wrapped__ - - def __ror__(self, other): - return other | self.__wrapped__ - - def __iadd__(self, other): - self.__wrapped__ += other - return self - - def __isub__(self, other): - self.__wrapped__ -= other - return self - - def __imul__(self, other): - self.__wrapped__ *= other - return self - - def __idiv__(self, other): - self.__wrapped__ = operator.idiv(self.__wrapped__, other) - return self - - def __itruediv__(self, other): - self.__wrapped__ = operator.itruediv(self.__wrapped__, other) - return self - - def __ifloordiv__(self, other): - self.__wrapped__ //= other - return self - - def __imod__(self, other): - self.__wrapped__ %= other - return self - - def __ipow__(self, other): - self.__wrapped__ **= other - return self - - def __ilshift__(self, other): - self.__wrapped__ <<= other - return self - - def __irshift__(self, other): - self.__wrapped__ >>= other - return self - - def __iand__(self, other): - self.__wrapped__ &= other - return self - - def __ixor__(self, other): - self.__wrapped__ ^= other - return self - - def __ior__(self, other): - self.__wrapped__ |= other - return self - - def __neg__(self): - return -self.__wrapped__ - - def __pos__(self): - return +self.__wrapped__ - - def __abs__(self): - return abs(self.__wrapped__) - - def __invert__(self): - return ~self.__wrapped__ - - def __int__(self): - return int(self.__wrapped__) - - def __long__(self): - return long(self.__wrapped__) - - def __float__(self): - return float(self.__wrapped__) - - def __complex__(self): - return complex(self.__wrapped__) - - def __oct__(self): - return oct(self.__wrapped__) - - def __hex__(self): - return hex(self.__wrapped__) - - def __index__(self): - return operator.index(self.__wrapped__) - - def __len__(self): - return len(self.__wrapped__) - - def __contains__(self, value): - return value in self.__wrapped__ - - def __getitem__(self, key): - return self.__wrapped__[key] - - def __setitem__(self, key, value): - self.__wrapped__[key] = value - - def __delitem__(self, key): - del self.__wrapped__[key] - - def __getslice__(self, i, j): - return self.__wrapped__[i:j] - - def __setslice__(self, i, j, value): - self.__wrapped__[i:j] = value - - def __delslice__(self, i, j): - del self.__wrapped__[i:j] - - def __enter__(self): - return self.__wrapped__.__enter__() - - def __exit__(self, *args, **kwargs): - return self.__wrapped__.__exit__(*args, **kwargs) - - def __iter__(self): - return iter(self.__wrapped__) - - def __copy__(self): - raise NotImplementedError('object proxy must define __copy__()') - - def __deepcopy__(self, memo): - raise NotImplementedError('object proxy must define __deepcopy__()') - - def __reduce__(self): - raise NotImplementedError( - 'object proxy must define __reduce_ex__()') - - def __reduce_ex__(self, protocol): - raise NotImplementedError( - 'object proxy must define __reduce_ex__()') - -class CallableObjectProxy(ObjectProxy): - - def __call__(self, *args, **kwargs): - return self.__wrapped__(*args, **kwargs) - -class PartialCallableObjectProxy(ObjectProxy): - - def __init__(self, *args, **kwargs): - if len(args) < 1: - raise TypeError('partial type takes at least one argument') - - wrapped, args = args[0], args[1:] - - if not callable(wrapped): - raise TypeError('the first argument must be callable') - - super(PartialCallableObjectProxy, self).__init__(wrapped) - - self._self_args = args - self._self_kwargs = kwargs - - def __call__(self, *args, **kwargs): - _args = self._self_args + args - - _kwargs = dict(self._self_kwargs) - _kwargs.update(kwargs) - - return self.__wrapped__(*_args, **_kwargs) - -class _FunctionWrapperBase(ObjectProxy): - - __slots__ = ('_self_instance', '_self_wrapper', '_self_enabled', - '_self_binding', '_self_parent') - - def __init__(self, wrapped, instance, wrapper, enabled=None, - binding='function', parent=None): - - super(_FunctionWrapperBase, self).__init__(wrapped) - - object.__setattr__(self, '_self_instance', instance) - object.__setattr__(self, '_self_wrapper', wrapper) - object.__setattr__(self, '_self_enabled', enabled) - object.__setattr__(self, '_self_binding', binding) - object.__setattr__(self, '_self_parent', parent) - - def __get__(self, instance, owner): - # This method is actually doing double duty for both unbound and - # bound derived wrapper classes. It should possibly be broken up - # and the distinct functionality moved into the derived classes. - # Can't do that straight away due to some legacy code which is - # relying on it being here in this base class. - # - # The distinguishing attribute which determines whether we are - # being called in an unbound or bound wrapper is the parent - # attribute. If binding has never occurred, then the parent will - # be None. - # - # First therefore, is if we are called in an unbound wrapper. In - # this case we perform the binding. - # - # We have one special case to worry about here. This is where we - # are decorating a nested class. In this case the wrapped class - # would not have a __get__() method to call. In that case we - # simply return self. - # - # Note that we otherwise still do binding even if instance is - # None and accessing an unbound instance method from a class. - # This is because we need to be able to later detect that - # specific case as we will need to extract the instance from the - # first argument of those passed in. - - if self._self_parent is None: - if not inspect.isclass(self.__wrapped__): - descriptor = self.__wrapped__.__get__(instance, owner) - - return self.__bound_function_wrapper__(descriptor, instance, - self._self_wrapper, self._self_enabled, - self._self_binding, self) - - return self - - # Now we have the case of binding occurring a second time on what - # was already a bound function. In this case we would usually - # return ourselves again. This mirrors what Python does. - # - # The special case this time is where we were originally bound - # with an instance of None and we were likely an instance - # method. In that case we rebind against the original wrapped - # function from the parent again. - - if self._self_instance is None and self._self_binding == 'function': - descriptor = self._self_parent.__wrapped__.__get__( - instance, owner) - - return self._self_parent.__bound_function_wrapper__( - descriptor, instance, self._self_wrapper, - self._self_enabled, self._self_binding, - self._self_parent) - - return self - - def __call__(self, *args, **kwargs): - # If enabled has been specified, then evaluate it at this point - # and if the wrapper is not to be executed, then simply return - # the bound function rather than a bound wrapper for the bound - # function. When evaluating enabled, if it is callable we call - # it, otherwise we evaluate it as a boolean. - - if self._self_enabled is not None: - if callable(self._self_enabled): - if not self._self_enabled(): - return self.__wrapped__(*args, **kwargs) - elif not self._self_enabled: - return self.__wrapped__(*args, **kwargs) - - # This can occur where initial function wrapper was applied to - # a function that was already bound to an instance. In that case - # we want to extract the instance from the function and use it. - - if self._self_binding == 'function': - if self._self_instance is None: - instance = getattr(self.__wrapped__, '__self__', None) - if instance is not None: - return self._self_wrapper(self.__wrapped__, instance, - args, kwargs) - - # This is generally invoked when the wrapped function is being - # called as a normal function and is not bound to a class as an - # instance method. This is also invoked in the case where the - # wrapped function was a method, but this wrapper was in turn - # wrapped using the staticmethod decorator. - - return self._self_wrapper(self.__wrapped__, self._self_instance, - args, kwargs) - -class BoundFunctionWrapper(_FunctionWrapperBase): - - def __call__(self, *args, **kwargs): - # If enabled has been specified, then evaluate it at this point - # and if the wrapper is not to be executed, then simply return - # the bound function rather than a bound wrapper for the bound - # function. When evaluating enabled, if it is callable we call - # it, otherwise we evaluate it as a boolean. - - if self._self_enabled is not None: - if callable(self._self_enabled): - if not self._self_enabled(): - return self.__wrapped__(*args, **kwargs) - elif not self._self_enabled: - return self.__wrapped__(*args, **kwargs) - - # We need to do things different depending on whether we are - # likely wrapping an instance method vs a static method or class - # method. - - if self._self_binding == 'function': - if self._self_instance is None: - # This situation can occur where someone is calling the - # instancemethod via the class type and passing the instance - # as the first argument. We need to shift the args before - # making the call to the wrapper and effectively bind the - # instance to the wrapped function using a partial so the - # wrapper doesn't see anything as being different. - - if not args: - raise TypeError('missing 1 required positional argument') - - instance, args = args[0], args[1:] - wrapped = PartialCallableObjectProxy(self.__wrapped__, instance) - return self._self_wrapper(wrapped, instance, args, kwargs) - - return self._self_wrapper(self.__wrapped__, self._self_instance, - args, kwargs) - - else: - # As in this case we would be dealing with a classmethod or - # staticmethod, then _self_instance will only tell us whether - # when calling the classmethod or staticmethod they did it via an - # instance of the class it is bound to and not the case where - # done by the class type itself. We thus ignore _self_instance - # and use the __self__ attribute of the bound function instead. - # For a classmethod, this means instance will be the class type - # and for a staticmethod it will be None. This is probably the - # more useful thing we can pass through even though we loose - # knowledge of whether they were called on the instance vs the - # class type, as it reflects what they have available in the - # decoratored function. - - instance = getattr(self.__wrapped__, '__self__', None) - - return self._self_wrapper(self.__wrapped__, instance, args, - kwargs) - -class FunctionWrapper(_FunctionWrapperBase): - - __bound_function_wrapper__ = BoundFunctionWrapper - - def __init__(self, wrapped, wrapper, enabled=None): - # What it is we are wrapping here could be anything. We need to - # try and detect specific cases though. In particular, we need - # to detect when we are given something that is a method of a - # class. Further, we need to know when it is likely an instance - # method, as opposed to a class or static method. This can - # become problematic though as there isn't strictly a fool proof - # method of knowing. - # - # The situations we could encounter when wrapping a method are: - # - # 1. The wrapper is being applied as part of a decorator which - # is a part of the class definition. In this case what we are - # given is the raw unbound function, classmethod or staticmethod - # wrapper objects. - # - # The problem here is that we will not know we are being applied - # in the context of the class being set up. This becomes - # important later for the case of an instance method, because in - # that case we just see it as a raw function and can't - # distinguish it from wrapping a normal function outside of - # a class context. - # - # 2. The wrapper is being applied when performing monkey - # patching of the class type afterwards and the method to be - # wrapped was retrieved direct from the __dict__ of the class - # type. This is effectively the same as (1) above. - # - # 3. The wrapper is being applied when performing monkey - # patching of the class type afterwards and the method to be - # wrapped was retrieved from the class type. In this case - # binding will have been performed where the instance against - # which the method is bound will be None at that point. - # - # This case is a problem because we can no longer tell if the - # method was a static method, plus if using Python3, we cannot - # tell if it was an instance method as the concept of an - # unnbound method no longer exists. - # - # 4. The wrapper is being applied when performing monkey - # patching of an instance of a class. In this case binding will - # have been perfomed where the instance was not None. - # - # This case is a problem because we can no longer tell if the - # method was a static method. - # - # Overall, the best we can do is look at the original type of the - # object which was wrapped prior to any binding being done and - # see if it is an instance of classmethod or staticmethod. In - # the case where other decorators are between us and them, if - # they do not propagate the __class__ attribute so that the - # isinstance() checks works, then likely this will do the wrong - # thing where classmethod and staticmethod are used. - # - # Since it is likely to be very rare that anyone even puts - # decorators around classmethod and staticmethod, likelihood of - # that being an issue is very small, so we accept it and suggest - # that those other decorators be fixed. It is also only an issue - # if a decorator wants to actually do things with the arguments. - # - # As to not being able to identify static methods properly, we - # just hope that that isn't something people are going to want - # to wrap, or if they do suggest they do it the correct way by - # ensuring that it is decorated in the class definition itself, - # or patch it in the __dict__ of the class type. - # - # So to get the best outcome we can, whenever we aren't sure what - # it is, we label it as a 'function'. If it was already bound and - # that is rebound later, we assume that it will be an instance - # method and try an cope with the possibility that the 'self' - # argument it being passed as an explicit argument and shuffle - # the arguments around to extract 'self' for use as the instance. - - if isinstance(wrapped, classmethod): - binding = 'classmethod' - - elif isinstance(wrapped, staticmethod): - binding = 'staticmethod' - - elif hasattr(wrapped, '__self__'): - if inspect.isclass(wrapped.__self__): - binding = 'classmethod' - else: - binding = 'function' - - else: - binding = 'function' - - super(FunctionWrapper, self).__init__(wrapped, None, wrapper, - enabled, binding) - -try: - if not os.environ.get('WRAPT_DISABLE_EXTENSIONS'): - from ._wrappers import (ObjectProxy, CallableObjectProxy, - PartialCallableObjectProxy, FunctionWrapper, - BoundFunctionWrapper, _FunctionWrapperBase) -except ImportError: - pass - -# 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] - - original = getattr(parent, attribute) - for attribute in path[1:]: - parent = original - - # 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. - - if inspect.isclass(original): - for cls in inspect.getmro(original): - if attribute in vars(cls): - original = vars(cls)[attribute] - break - else: - original = getattr(original, attribute) - - else: - original = getattr(original, 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): - def _wrapper(wrapper): - return wrap_object(module, name, FunctionWrapper, (wrapper,)) - 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 - -# 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__(self, *args, **kwargs): - # 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) |