Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/wrapt/wrappers.py: 31%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Core object proxy and function wrapper implementations."""
3import inspect
4import operator
5import sys
6import types
9class WrapperNotInitializedError(ValueError):
10 """
11 Exception raised when a wrapper is in an inconsistent state: __init__ was
12 called but __wrapped__ is not set. Inherits from ValueError only, so it is
13 not silently swallowed by hasattr/getattr/except AttributeError patterns.
14 """
16 pass
19class _ObjectProxyMethods:
21 # We use properties to override the values of __module__ and
22 # __doc__. If we add these in ObjectProxy, the derived class
23 # __dict__ will still be setup to have string variants of these
24 # attributes and the rules of descriptors means that they appear to
25 # take precedence over the properties in the base class. To avoid
26 # that, we copy the properties into the derived class type itself
27 # via a meta class. In that way the properties will always take
28 # precedence.
29 #
30 # Note that because these properties end up in the class __dict__,
31 # type-level access (e.g. ObjectProxy.__module__) would return the
32 # property object rather than a string, since CPython's
33 # type.__module__ getter does a raw dict lookup without invoking the
34 # descriptor protocol. The metaclass has its own __module__ and
35 # __doc__ properties to handle type-level access correctly.
37 @property
38 def __module__(self):
39 return self.__wrapped__.__module__
41 @__module__.setter
42 def __module__(self, value):
43 self.__wrapped__.__module__ = value
45 @property
46 def __doc__(self):
47 return self.__wrapped__.__doc__
49 @__doc__.setter
50 def __doc__(self, value):
51 self.__wrapped__.__doc__ = value
53 # We similar use a property for __dict__. We need __dict__ to be
54 # explicit to ensure that vars() works as expected.
56 @property
57 def __dict__(self):
58 return self.__wrapped__.__dict__
60 # Need to also propagate the special __weakref__ attribute for case
61 # where decorating classes which will define this. If do not define
62 # it and use a function like inspect.getmembers() on a decorator
63 # class it will fail. This can't be in the derived classes.
65 @property
66 def __weakref__(self):
67 return self.__wrapped__.__weakref__
70class _ObjectProxyDictBase:
71 """Base class whose sole purpose is to provide a ``getset_descriptor``
72 for ``__dict__`` that is valid for all ``ObjectProxy`` subclasses.
73 The metaclass installs this descriptor as ``__self_dict__`` so that
74 the real instance dictionary of the proxy can always be accessed,
75 even though ``ObjectProxy`` replaces ``__dict__`` with a property
76 that delegates to the wrapped object."""
78 pass
81_REAL_DICT_DESCRIPTOR = type.__dict__["__dict__"].__get__(_ObjectProxyDictBase)[
82 "__dict__"
83]
86def _get_self_dict(self):
87 return _REAL_DICT_DESCRIPTOR.__get__(self)
90# Wrapping the descriptor in a read-only property ensures that
91# ``proxy.__self_dict__ = value`` raises AttributeError rather than
92# replacing the real instance dictionary (which would break the proxy).
94_SELF_DICT_PROPERTY = property(_get_self_dict)
97class _ObjectProxyMetaType(type):
98 # Properties on the metaclass control type-level access to __module__
99 # and __doc__ (e.g. ObjectProxy.__module__). Without these, the
100 # instance-level properties copied from _ObjectProxyMethods into each
101 # class dict would shadow the string values that type.__new__ sets,
102 # causing type.__module__ to return a property object instead of a
103 # string. The metaclass properties read from internal keys where the
104 # real values are saved.
106 @property
107 def __module__(cls):
108 return cls.__dict__.get("_cls_real_module", "builtins")
110 @__module__.setter
111 def __module__(cls, value):
112 type.__setattr__(cls, "_cls_real_module", value)
114 @property
115 def __doc__(cls):
116 return cls.__dict__.get("_cls_real_doc")
118 @__doc__.setter
119 def __doc__(cls, value):
120 type.__setattr__(cls, "_cls_real_doc", value)
122 def __new__(cls, name, bases, dictionary):
123 # Copy our special properties into the class so that they
124 # always take precedence over attributes of the same name added
125 # during construction of a derived class. This is to save
126 # duplicating the implementation for them in all derived classes.
127 #
128 # Because this overwrites the __module__ and __doc__ strings
129 # that would normally be in the class dict with property objects,
130 # we save the original values first and store them under internal
131 # keys. The metaclass properties above read from these keys to
132 # ensure type-level access (e.g. MyProxy.__module__) returns a
133 # string rather than a property object.
135 real_module = dictionary.get("__module__")
136 real_doc = dictionary.get("__doc__")
138 # If the subclass defines its own __dict__ property, preserve it
139 # rather than overwriting it with the default delegating property
140 # from _ObjectProxyMethods. When __dict__ is not explicitly
141 # defined in the class body, it will not be present in the
142 # dictionary at this point.
144 custom_dict = dictionary.get("__dict__")
146 dictionary.update(vars(_ObjectProxyMethods))
148 if custom_dict is not None:
149 dictionary["__dict__"] = custom_dict
151 dictionary.setdefault("__self_dict__", _SELF_DICT_PROPERTY)
153 klass = type.__new__(cls, name, bases, dictionary)
155 if real_module is not None:
156 type.__setattr__(klass, "_cls_real_module", real_module)
157 if real_doc is not None:
158 type.__setattr__(klass, "_cls_real_doc", real_doc)
160 return klass
163class ObjectProxy(_ObjectProxyDictBase, metaclass=_ObjectProxyMetaType):
164 """A transparent object proxy that delegates attribute access to a
165 wrapped object."""
167 __class_getitem__ = classmethod(types.GenericAlias)
169 def __init__(self, wrapped):
170 """Create an object proxy around the given object."""
172 if wrapped is None:
173 try:
174 callback = object.__getattribute__(self, "__wrapped_factory__")
175 except AttributeError:
176 callback = None
178 if callback is not None:
179 # If wrapped is none and class has a __wrapped_factory__
180 # method, then we don't set __wrapped__ yet and instead will
181 # defer creation of the wrapped object until it is first
182 # needed.
184 pass
186 else:
187 object.__setattr__(self, "__wrapped__", wrapped)
188 else:
189 object.__setattr__(self, "__wrapped__", wrapped)
191 object.__setattr__(self, "__init_called__", True)
193 # Python 3.2+ has the __qualname__ attribute, but it does not
194 # allow it to be overridden using a property and it must instead
195 # be an actual string object instead.
197 try:
198 object.__setattr__(self, "__qualname__", wrapped.__qualname__)
199 except AttributeError:
200 pass
202 # Python 3.10 onwards also does not allow itself to be overridden
203 # using a property and it must instead be set explicitly. Python
204 # 3.14 onwards uses deferred evaluation of annotations via the
205 # __annotate__ attribute, so we copy that instead to avoid
206 # triggering eager evaluation which can fail if names referenced
207 # in annotations have been shadowed.
209 if sys.version_info >= (3, 14):
210 try:
211 object.__setattr__(self, "__annotate__", wrapped.__annotate__)
212 except AttributeError:
213 pass
214 else:
215 try:
216 object.__setattr__(self, "__annotations__", wrapped.__annotations__)
217 except AttributeError:
218 pass
220 @property
221 def __object_proxy__(self):
222 return ObjectProxy
224 def __self_setattr__(self, name, value):
225 object.__setattr__(self, name, value)
227 @property
228 def __name__(self):
229 return self.__wrapped__.__name__
231 @__name__.setter
232 def __name__(self, value):
233 self.__wrapped__.__name__ = value
235 @property
236 def __class__(self):
237 return self.__wrapped__.__class__
239 @__class__.setter
240 def __class__(self, value):
241 self.__wrapped__.__class__ = value
243 def __dir__(self):
244 return dir(self.__wrapped__)
246 def __str__(self):
247 return str(self.__wrapped__)
249 def __bytes__(self):
250 return bytes(self.__wrapped__)
252 def __repr__(self):
253 return f"<{type(self).__name__} at 0x{id(self):x} for {type(self.__wrapped__).__name__} at 0x{id(self.__wrapped__):x}>"
255 def __format__(self, format_spec):
256 return format(self.__wrapped__, format_spec)
258 def __reversed__(self):
259 return reversed(self.__wrapped__)
261 def __round__(self, ndigits=None):
262 return round(self.__wrapped__, ndigits)
264 def __mro_entries__(self, bases):
265 if not isinstance(self.__wrapped__, type) and hasattr(
266 self.__wrapped__, "__mro_entries__"
267 ):
268 return self.__wrapped__.__mro_entries__(bases)
269 return (self.__wrapped__,)
271 def __lt__(self, other):
272 return self.__wrapped__ < other
274 def __le__(self, other):
275 return self.__wrapped__ <= other
277 def __eq__(self, other):
278 return self.__wrapped__ == other
280 def __ne__(self, other):
281 return self.__wrapped__ != other
283 def __gt__(self, other):
284 return self.__wrapped__ > other
286 def __ge__(self, other):
287 return self.__wrapped__ >= other
289 def __hash__(self):
290 return hash(self.__wrapped__)
292 def __bool__(self):
293 return bool(self.__wrapped__)
295 def __setattr__(self, name, value):
296 if name.startswith("_self_"):
297 object.__setattr__(self, name, value)
299 elif name == "__wrapped__":
300 object.__setattr__(self, name, value)
302 try:
303 object.__delattr__(self, "__qualname__")
304 except AttributeError:
305 pass
306 try:
307 object.__setattr__(self, "__qualname__", value.__qualname__)
308 except AttributeError:
309 pass
310 if sys.version_info >= (3, 14):
311 try:
312 object.__delattr__(self, "__annotate__")
313 except AttributeError:
314 pass
315 try:
316 object.__setattr__(self, "__annotate__", value.__annotate__)
317 except AttributeError:
318 pass
319 else:
320 try:
321 object.__delattr__(self, "__annotations__")
322 except AttributeError:
323 pass
324 try:
325 object.__setattr__(self, "__annotations__", value.__annotations__)
326 except AttributeError:
327 pass
329 __wrapped_setattr_fixups__ = getattr(
330 self, "__wrapped_setattr_fixups__", None
331 )
333 if __wrapped_setattr_fixups__ is not None:
334 __wrapped_setattr_fixups__()
336 elif name == "__qualname__":
337 setattr(self.__wrapped__, name, value)
338 object.__setattr__(self, name, value)
340 elif name == "__annotations__":
341 setattr(self.__wrapped__, name, value)
342 object.__setattr__(self, name, value)
344 elif name == "__annotate__":
345 setattr(self.__wrapped__, name, value)
346 object.__setattr__(self, name, value)
348 elif hasattr(type(self), name):
349 object.__setattr__(self, name, value)
351 else:
352 setattr(self.__wrapped__, name, value)
354 def __getattr__(self, name):
355 # If we need to lookup `__wrapped__` then the `__init__()` method
356 # cannot have been called, or this is a lazy object proxy which is
357 # deferring creation of the wrapped object until it is first needed.
359 if name == "__wrapped__":
360 # Note that we use existance of `__wrapped_factory__` to gate whether
361 # we can attempt to initialize the wrapped object lazily, but it is
362 # `__wrapped_get__` that we actually call to do the initialization.
363 # This is so that we can handle multithreading correctly by having
364 # `__wrapped_get__` use a lock to protect against multiple threads
365 # trying to initialize the wrapped object at the same time.
367 try:
368 object.__getattribute__(self, "__wrapped_factory__")
369 except AttributeError:
370 pass
371 else:
372 return object.__getattribute__(self, "__wrapped_get__")()
374 # If __init__ was called but __wrapped__ is not set, the wrapper
375 # is in an inconsistent state. Raise WrapperNotInitializedError
376 # (a ValueError, not AttributeError) so it is not silently
377 # swallowed by hasattr/getattr patterns.
379 try:
380 object.__getattribute__(self, "__init_called__")
381 except AttributeError:
382 raise AttributeError(
383 f"'{type(self).__name__}' object has no attribute " f"'__wrapped__'"
384 )
386 raise WrapperNotInitializedError(
387 "wrapper is in an inconsistent state: __wrapped__ is not set"
388 )
390 return getattr(self.__wrapped__, name)
392 def __delattr__(self, name):
393 if name.startswith("_self_"):
394 object.__delattr__(self, name)
396 elif name == "__wrapped__":
397 raise TypeError("can't delete __wrapped__ attribute")
399 elif name == "__qualname__":
400 object.__delattr__(self, name)
401 delattr(self.__wrapped__, name)
403 elif name == "__annotations__":
404 try:
405 object.__delattr__(self, name)
406 except AttributeError:
407 pass
408 delattr(self.__wrapped__, name)
410 elif name == "__annotate__":
411 try:
412 object.__delattr__(self, name)
413 except AttributeError:
414 pass
415 delattr(self.__wrapped__, name)
417 elif hasattr(type(self), name):
418 object.__delattr__(self, name)
420 else:
421 delattr(self.__wrapped__, name)
423 def __add__(self, other):
424 return self.__wrapped__ + other
426 def __sub__(self, other):
427 return self.__wrapped__ - other
429 def __mul__(self, other):
430 return self.__wrapped__ * other
432 def __truediv__(self, other):
433 return operator.truediv(self.__wrapped__, other)
435 def __floordiv__(self, other):
436 return self.__wrapped__ // other
438 def __mod__(self, other):
439 return self.__wrapped__ % other
441 def __divmod__(self, other):
442 return divmod(self.__wrapped__, other)
444 def __pow__(self, other, *args):
445 return pow(self.__wrapped__, other, *args)
447 def __lshift__(self, other):
448 return self.__wrapped__ << other
450 def __rshift__(self, other):
451 return self.__wrapped__ >> other
453 def __and__(self, other):
454 return self.__wrapped__ & other
456 def __xor__(self, other):
457 return self.__wrapped__ ^ other
459 def __or__(self, other):
460 return self.__wrapped__ | other
462 def __radd__(self, other):
463 return other + self.__wrapped__
465 def __rsub__(self, other):
466 return other - self.__wrapped__
468 def __rmul__(self, other):
469 return other * self.__wrapped__
471 def __rtruediv__(self, other):
472 return operator.truediv(other, self.__wrapped__)
474 def __rfloordiv__(self, other):
475 return other // self.__wrapped__
477 def __rmod__(self, other):
478 return other % self.__wrapped__
480 def __rdivmod__(self, other):
481 return divmod(other, self.__wrapped__)
483 def __rpow__(self, other, *args):
484 return pow(other, self.__wrapped__, *args)
486 def __rlshift__(self, other):
487 return other << self.__wrapped__
489 def __rrshift__(self, other):
490 return other >> self.__wrapped__
492 def __rand__(self, other):
493 return other & self.__wrapped__
495 def __rxor__(self, other):
496 return other ^ self.__wrapped__
498 def __ror__(self, other):
499 return other | self.__wrapped__
501 def __iadd__(self, other):
502 if hasattr(self.__wrapped__, "__iadd__"):
503 self.__wrapped__ += other
504 return self
505 else:
506 return self.__object_proxy__(self.__wrapped__ + other)
508 def __isub__(self, other):
509 if hasattr(self.__wrapped__, "__isub__"):
510 self.__wrapped__ -= other
511 return self
512 else:
513 return self.__object_proxy__(self.__wrapped__ - other)
515 def __imul__(self, other):
516 if hasattr(self.__wrapped__, "__imul__"):
517 self.__wrapped__ *= other
518 return self
519 else:
520 return self.__object_proxy__(self.__wrapped__ * other)
522 def __itruediv__(self, other):
523 if hasattr(self.__wrapped__, "__itruediv__"):
524 self.__wrapped__ /= other
525 return self
526 else:
527 return self.__object_proxy__(self.__wrapped__ / other)
529 def __ifloordiv__(self, other):
530 if hasattr(self.__wrapped__, "__ifloordiv__"):
531 self.__wrapped__ //= other
532 return self
533 else:
534 return self.__object_proxy__(self.__wrapped__ // other)
536 def __imod__(self, other):
537 if hasattr(self.__wrapped__, "__imod__"):
538 self.__wrapped__ %= other
539 return self
540 else:
541 return self.__object_proxy__(self.__wrapped__ % other)
543 def __ipow__(self, other): # type: ignore[misc]
544 if hasattr(self.__wrapped__, "__ipow__"):
545 self.__wrapped__ **= other
546 return self
547 else:
548 return self.__object_proxy__(self.__wrapped__**other)
550 def __ilshift__(self, other):
551 if hasattr(self.__wrapped__, "__ilshift__"):
552 self.__wrapped__ <<= other
553 return self
554 else:
555 return self.__object_proxy__(self.__wrapped__ << other)
557 def __irshift__(self, other):
558 if hasattr(self.__wrapped__, "__irshift__"):
559 self.__wrapped__ >>= other
560 return self
561 else:
562 return self.__object_proxy__(self.__wrapped__ >> other)
564 def __iand__(self, other):
565 if hasattr(self.__wrapped__, "__iand__"):
566 self.__wrapped__ &= other
567 return self
568 else:
569 return self.__object_proxy__(self.__wrapped__ & other)
571 def __ixor__(self, other):
572 if hasattr(self.__wrapped__, "__ixor__"):
573 self.__wrapped__ ^= other
574 return self
575 else:
576 return self.__object_proxy__(self.__wrapped__ ^ other)
578 def __ior__(self, other):
579 if hasattr(self.__wrapped__, "__ior__"):
580 self.__wrapped__ |= other
581 return self
582 else:
583 return self.__object_proxy__(self.__wrapped__ | other)
585 def __neg__(self):
586 return -self.__wrapped__
588 def __pos__(self):
589 return +self.__wrapped__
591 def __abs__(self):
592 return abs(self.__wrapped__)
594 def __invert__(self):
595 return ~self.__wrapped__
597 def __int__(self):
598 return int(self.__wrapped__)
600 def __float__(self):
601 return float(self.__wrapped__)
603 def __complex__(self):
604 return complex(self.__wrapped__)
606 def __index__(self):
607 return operator.index(self.__wrapped__)
609 def __matmul__(self, other):
610 return self.__wrapped__ @ other
612 def __rmatmul__(self, other):
613 return other @ self.__wrapped__
615 def __imatmul__(self, other):
616 if hasattr(self.__wrapped__, "__imatmul__"):
617 self.__wrapped__ @= other
618 return self
619 else:
620 return self.__object_proxy__(self.__wrapped__ @ other)
622 def __len__(self):
623 return len(self.__wrapped__)
625 def __contains__(self, value):
626 return value in self.__wrapped__
628 def __getitem__(self, key):
629 return self.__wrapped__[key]
631 def __setitem__(self, key, value):
632 self.__wrapped__[key] = value
634 def __delitem__(self, key):
635 del self.__wrapped__[key]
637 def __enter__(self):
638 return self.__wrapped__.__enter__()
640 def __exit__(self, *args, **kwargs):
641 return self.__wrapped__.__exit__(*args, **kwargs)
643 def __aenter__(self):
644 return self.__wrapped__.__aenter__()
646 def __aexit__(self, *args, **kwargs):
647 return self.__wrapped__.__aexit__(*args, **kwargs)
649 def __copy__(self):
650 raise NotImplementedError("object proxy must define __copy__()")
652 def __deepcopy__(self, memo):
653 raise NotImplementedError("object proxy must define __deepcopy__()")
655 def __reduce__(self):
656 raise NotImplementedError("object proxy must define __reduce__()")
658 def __instancecheck__(self, instance):
659 return isinstance(instance, self.__wrapped__)
661 def __subclasscheck__(self, subclass):
662 if hasattr(subclass, "__wrapped__"):
663 return issubclass(subclass.__wrapped__, self.__wrapped__)
664 else:
665 return issubclass(subclass, self.__wrapped__)
668class CallableObjectProxy(ObjectProxy):
669 """An object proxy for callable objects that also forwards calls."""
671 def __call__(*args, **kwargs):
672 def _unpack_self(self, *args):
673 return self, args
675 self, args = _unpack_self(*args)
677 return self.__wrapped__(*args, **kwargs)
680class PartialCallableObjectProxy(ObjectProxy):
681 """A callable object proxy that supports partial application of arguments
682 and keywords.
683 """
685 def __init__(*args, **kwargs):
686 """Create a callable object proxy with partial application of the given
687 arguments and keywords. This behaves the same as `functools.partial`, but
688 implemented using the `ObjectProxy` class to provide better support for
689 introspection.
690 """
692 def _unpack_self(self, *args):
693 return self, args
695 self, args = _unpack_self(*args)
697 if len(args) < 1:
698 raise TypeError("partial type takes at least one argument")
700 wrapped, args = args[0], args[1:]
702 if not callable(wrapped):
703 raise TypeError("the first argument must be callable")
705 # Explicit class in super() is used because the proxy overrides
706 # __class__ and MRO-related methods to delegate to the wrapped
707 # object, which can interfere with bare super().
708 super(PartialCallableObjectProxy, self).__init__(wrapped)
710 self._self_args = args
711 self._self_kwargs = kwargs
713 def __call__(*args, **kwargs):
714 def _unpack_self(self, *args):
715 return self, args
717 self, args = _unpack_self(*args)
719 _args = self._self_args + args
721 _kwargs = dict(self._self_kwargs)
722 _kwargs.update(kwargs)
724 return self.__wrapped__(*_args, **_kwargs)
727class _FunctionWrapperBase(ObjectProxy):
729 def __init__(
730 self,
731 wrapped,
732 instance,
733 wrapper,
734 enabled=None,
735 binding="callable",
736 parent=None,
737 owner=None,
738 ):
740 # Explicit class in super() is used because the proxy overrides
741 # __class__ and MRO-related methods to delegate to the wrapped
742 # object, which can interfere with bare super().
743 super(_FunctionWrapperBase, self).__init__(wrapped)
745 object.__setattr__(self, "_self_instance", instance)
746 object.__setattr__(self, "_self_wrapper", wrapper)
747 object.__setattr__(self, "_self_enabled", enabled)
748 object.__setattr__(self, "_self_binding", binding)
749 object.__setattr__(self, "_self_parent", parent)
750 object.__setattr__(self, "_self_owner", owner)
752 def __get__(self, instance, owner):
753 # This method handles both unbound and bound derived wrapper classes.
754 # It is kept in the base class as the amount of common code makes it
755 # impractical to split into the derived classes.
756 #
757 # The distinguishing attribute which determines whether we are being
758 # called in an unbound or bound wrapper is the parent attribute. If
759 # binding has never occurred, then the parent will be None.
760 #
761 # First therefore, is if we are called in an unbound wrapper. In this
762 # case we perform the binding.
763 #
764 # We have two special cases to worry about here. These are where we are
765 # decorating a class or builtin function as neither provide a __get__()
766 # method to call. In this case we simply return self.
767 #
768 # Note that we otherwise still do binding even if instance is None and
769 # accessing an unbound instance method from a class. This is because we
770 # need to be able to later detect that specific case as we will need to
771 # extract the instance from the first argument of those passed in.
773 if self._self_parent is None:
774 # Technically can probably just check for existence of __get__ on
775 # the wrapped object, but this is more explicit.
777 if self._self_binding == "builtin":
778 return self
780 if self._self_binding == "class":
781 return self
783 binder = getattr(self.__wrapped__, "__get__", None)
785 if binder is None:
786 return self
788 descriptor = binder(instance, owner)
790 return self.__bound_function_wrapper__(
791 descriptor,
792 instance,
793 self._self_wrapper,
794 self._self_enabled,
795 self._self_binding,
796 self,
797 owner,
798 )
800 # Now we have the case of binding occurring a second time on what was
801 # already a bound function. In this case we would usually return
802 # ourselves again. This mirrors what Python does.
803 #
804 # The special case this time is where we were originally bound with an
805 # instance of None and we were likely an instance method. In that case
806 # we rebind against the original wrapped function from the parent again.
808 if self._self_instance is None and self._self_binding in (
809 "function",
810 "instancemethod",
811 "callable",
812 ):
813 descriptor = self._self_parent.__wrapped__.__get__(instance, owner)
815 return self._self_parent.__bound_function_wrapper__(
816 descriptor,
817 instance,
818 self._self_wrapper,
819 self._self_enabled,
820 self._self_binding,
821 self._self_parent,
822 owner,
823 )
825 return self
827 def __call__(*args, **kwargs):
828 def _unpack_self(self, *args):
829 return self, args
831 self, args = _unpack_self(*args)
833 # If enabled has been specified, then evaluate it at this point
834 # and if the wrapper is not to be executed, then simply return
835 # the bound function rather than a bound wrapper for the bound
836 # function. When evaluating enabled, if it is callable we call
837 # it, otherwise we evaluate it as a boolean.
839 if self._self_enabled is not None:
840 if callable(self._self_enabled):
841 if not self._self_enabled():
842 return self.__wrapped__(*args, **kwargs)
843 elif not self._self_enabled:
844 return self.__wrapped__(*args, **kwargs)
846 # This can occur where initial function wrapper was applied to
847 # a function that was already bound to an instance. In that case
848 # we want to extract the instance from the function and use it.
850 if self._self_binding in (
851 "function",
852 "instancemethod",
853 "classmethod",
854 "callable",
855 ):
856 if self._self_instance is None:
857 instance = getattr(self.__wrapped__, "__self__", None)
858 if instance is not None:
859 return self._self_wrapper(self.__wrapped__, instance, args, kwargs)
861 # This is generally invoked when the wrapped function is being
862 # called as a normal function and is not bound to a class as an
863 # instance method. This is also invoked in the case where the
864 # wrapped function was a method, but this wrapper was in turn
865 # wrapped using the staticmethod decorator.
867 return self._self_wrapper(self.__wrapped__, self._self_instance, args, kwargs)
869 def __set_name__(self, owner, name):
870 # This is a special method use to supply information to
871 # descriptors about what the name of variable in a class
872 # definition is. Not wanting to add this to ObjectProxy as not
873 # sure of broader implications of doing that. Thus restrict to
874 # FunctionWrapper used by decorators.
876 if hasattr(self.__wrapped__, "__set_name__"):
877 self.__wrapped__.__set_name__(owner, name)
880_FUNCTION_WRAPPER_SLOTS = frozenset(
881 (
882 "_self_instance",
883 "_self_wrapper",
884 "_self_enabled",
885 "_self_binding",
886 "_self_parent",
887 "_self_owner",
888 )
889)
892class BoundFunctionWrapper(_FunctionWrapperBase):
893 """A wrapper for bound methods, classmethods, and staticmethods."""
895 def __setattr__(self, name, value):
896 if name.startswith("_self_") and name not in _FUNCTION_WRAPPER_SLOTS:
897 if self._self_parent is not None:
898 object.__setattr__(self._self_parent, name, value)
899 return
900 super().__setattr__(name, value)
902 def __getattr__(self, name):
903 if self._self_parent is not None:
904 try:
905 return getattr(self._self_parent, name)
906 except AttributeError:
907 pass
908 return super().__getattr__(name)
910 def __call__(*args, **kwargs):
911 def _unpack_self(self, *args):
912 return self, args
914 self, args = _unpack_self(*args)
916 # If enabled has been specified, then evaluate it at this point and if
917 # the wrapper is not to be executed, then simply return the bound
918 # function rather than a bound wrapper for the bound function. When
919 # evaluating enabled, if it is callable we call it, otherwise we
920 # evaluate it as a boolean.
922 if self._self_enabled is not None:
923 if callable(self._self_enabled):
924 if not self._self_enabled():
925 return self.__wrapped__(*args, **kwargs)
926 elif not self._self_enabled:
927 return self.__wrapped__(*args, **kwargs)
929 # We need to do things different depending on whether we are likely
930 # wrapping an instance method vs a static method or class method.
932 if self._self_binding == "function":
933 if self._self_instance is None and args:
934 instance, newargs = args[0], args[1:]
935 if isinstance(instance, self._self_owner):
936 wrapped = PartialCallableObjectProxy(self.__wrapped__, instance)
937 return self._self_wrapper(wrapped, instance, newargs, kwargs)
939 return self._self_wrapper(
940 self.__wrapped__, self._self_instance, args, kwargs
941 )
943 elif self._self_binding == "callable":
944 if self._self_instance is None and args:
945 # This situation can occur where someone is calling the
946 # instancemethod via the class type and passing the instance as
947 # the first argument. We need to shift the args before making
948 # the call to the wrapper and effectively bind the instance to
949 # the wrapped function using a partial so the wrapper doesn't
950 # see anything as being different.
952 instance, newargs = args[0], args[1:]
953 if isinstance(instance, self._self_owner):
954 wrapped = PartialCallableObjectProxy(self.__wrapped__, instance)
955 return self._self_wrapper(wrapped, instance, newargs, kwargs)
957 return self._self_wrapper(
958 self.__wrapped__, self._self_instance, args, kwargs
959 )
961 else:
962 # As in this case we would be dealing with a classmethod or
963 # staticmethod, then _self_instance will only tell us whether
964 # when calling the classmethod or staticmethod they did it via an
965 # instance of the class it is bound to and not the case where
966 # done by the class type itself. We thus ignore _self_instance
967 # and use the __self__ attribute of the bound function instead.
968 # For a classmethod, this means instance will be the class type
969 # and for a staticmethod it will be None. This is probably the
970 # more useful thing we can pass through even though we loose
971 # knowledge of whether they were called on the instance vs the
972 # class type, as it reflects what they have available in the
973 # decoratored function.
975 instance = getattr(self.__wrapped__, "__self__", None)
977 return self._self_wrapper(self.__wrapped__, instance, args, kwargs)
980class FunctionWrapper(_FunctionWrapperBase):
981 """
982 A wrapper for callable objects that can be used to apply decorators to
983 functions, methods, classmethods, and staticmethods, or any other callable.
984 It handles binding and unbinding of methods, and allows for the wrapper to
985 be enabled or disabled.
986 """
988 __bound_function_wrapper__ = BoundFunctionWrapper
990 def __init__(self, wrapped, wrapper, enabled=None):
991 """
992 Initialize the `FunctionWrapper` with the `wrapped` callable, the
993 `wrapper` function, and an optional `enabled` argument. The `enabled`
994 argument can be a boolean or a callable that returns a boolean. When a
995 callable is provided, it will be called each time the wrapper is
996 invoked to determine if the wrapper function should be executed or
997 whether the wrapped function should be called directly. If `enabled`
998 is not provided, the wrapper is enabled by default.
999 """
1001 # What it is we are wrapping here could be anything. We need to
1002 # try and detect specific cases though. In particular, we need
1003 # to detect when we are given something that is a method of a
1004 # class. Further, we need to know when it is likely an instance
1005 # method, as opposed to a class or static method. This can
1006 # become problematic though as there isn't strictly a fool proof
1007 # method of knowing.
1008 #
1009 # The situations we could encounter when wrapping a method are:
1010 #
1011 # 1. The wrapper is being applied as part of a decorator which
1012 # is a part of the class definition. In this case what we are
1013 # given is the raw unbound function, classmethod or staticmethod
1014 # wrapper objects.
1015 #
1016 # The problem here is that we will not know we are being applied
1017 # in the context of the class being set up. This becomes
1018 # important later for the case of an instance method, because in
1019 # that case we just see it as a raw function and can't
1020 # distinguish it from wrapping a normal function outside of
1021 # a class context.
1022 #
1023 # 2. The wrapper is being applied when performing monkey
1024 # patching of the class type afterwards and the method to be
1025 # wrapped was retrieved direct from the __dict__ of the class
1026 # type. This is effectively the same as (1) above.
1027 #
1028 # 3. The wrapper is being applied when performing monkey
1029 # patching of the class type afterwards and the method to be
1030 # wrapped was retrieved from the class type. In this case
1031 # binding will have been performed where the instance against
1032 # which the method is bound will be None at that point.
1033 #
1034 # This case is a problem because we can no longer tell if the
1035 # method was a static method, plus if using Python3, we cannot
1036 # tell if it was an instance method as the concept of an
1037 # unnbound method no longer exists.
1038 #
1039 # 4. The wrapper is being applied when performing monkey
1040 # patching of an instance of a class. In this case binding will
1041 # have been performed where the instance was not None.
1042 #
1043 # This case is a problem because we can no longer tell if the
1044 # method was a static method.
1045 #
1046 # Overall, the best we can do is look at the original type of the
1047 # object which was wrapped prior to any binding being done and
1048 # see if it is an instance of classmethod or staticmethod. In
1049 # the case where other decorators are between us and them, if
1050 # they do not propagate the __class__ attribute so that the
1051 # isinstance() checks works, then likely this will do the wrong
1052 # thing where classmethod and staticmethod are used.
1053 #
1054 # Since it is likely to be very rare that anyone even puts
1055 # decorators around classmethod and staticmethod, likelihood of
1056 # that being an issue is very small, so we accept it and suggest
1057 # that those other decorators be fixed. It is also only an issue
1058 # if a decorator wants to actually do things with the arguments.
1059 #
1060 # As to not being able to identify static methods properly, we
1061 # just hope that that isn't something people are going to want
1062 # to wrap, or if they do suggest they do it the correct way by
1063 # ensuring that it is decorated in the class definition itself,
1064 # or patch it in the __dict__ of the class type.
1065 #
1066 # So to get the best outcome we can, whenever we aren't sure what
1067 # it is, we label it as a 'callable'. If it was already bound and
1068 # that is rebound later, we assume that it will be an instance
1069 # method and try and cope with the possibility that the 'self'
1070 # argument it being passed as an explicit argument and shuffle
1071 # the arguments around to extract 'self' for use as the instance.
1073 binding = None
1075 if isinstance(wrapped, _FunctionWrapperBase):
1076 binding = wrapped._self_binding
1078 if not binding:
1079 if inspect.isbuiltin(wrapped):
1080 binding = "builtin"
1082 elif inspect.isfunction(wrapped):
1083 binding = "function"
1085 elif inspect.isclass(wrapped):
1086 binding = "class"
1088 elif isinstance(wrapped, classmethod):
1089 binding = "classmethod"
1091 elif isinstance(wrapped, staticmethod):
1092 binding = "staticmethod"
1094 elif hasattr(wrapped, "__self__"):
1095 if inspect.isclass(wrapped.__self__):
1096 binding = "classmethod"
1097 elif inspect.ismethod(wrapped):
1098 binding = "instancemethod"
1099 else:
1100 binding = "callable"
1102 else:
1103 binding = "callable"
1105 # Explicit class in super() is used because the proxy overrides
1106 # __class__ and MRO-related methods to delegate to the wrapped
1107 # object, which can interfere with bare super().
1108 super(FunctionWrapper, self).__init__(wrapped, None, wrapper, enabled, binding)