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