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 functools
4import inspect
5import math
6import operator
7import sys
8import types
10from .exceptions import WrapperNotInitializedError
13class _ObjectProxyMethods:
15 # We use properties to override the values of __module__ and
16 # __doc__. If we add these in ObjectProxy, the derived class
17 # __dict__ will still be setup to have string variants of these
18 # attributes and the rules of descriptors means that they appear to
19 # take precedence over the properties in the base class. To avoid
20 # that, we copy the properties into the derived class type itself
21 # via a meta class. In that way the properties will always take
22 # precedence.
23 #
24 # Note that because these properties end up in the class __dict__,
25 # type-level access (e.g. ObjectProxy.__module__) would return the
26 # property object rather than a string, since CPython's
27 # type.__module__ getter does a raw dict lookup without invoking the
28 # descriptor protocol. The metaclass has its own __module__ and
29 # __doc__ properties to handle type-level access correctly.
31 @property
32 def __module__(self):
33 return self.__wrapped__.__module__
35 @__module__.setter
36 def __module__(self, value):
37 self.__wrapped__.__module__ = value
39 @__module__.deleter
40 def __module__(self):
41 del self.__wrapped__.__module__
43 @property
44 def __doc__(self):
45 return self.__wrapped__.__doc__
47 @__doc__.setter
48 def __doc__(self, value):
49 self.__wrapped__.__doc__ = value
51 @__doc__.deleter
52 def __doc__(self):
53 del self.__wrapped__.__doc__
55 # We similar use a property for __dict__. We need __dict__ to be
56 # explicit to ensure that vars() works as expected.
58 @property
59 def __dict__(self):
60 return self.__wrapped__.__dict__
62 # Need to also propagate the special __weakref__ attribute for case
63 # where decorating classes which will define this. If do not define
64 # it and use a function like inspect.getmembers() on a decorator
65 # class it will fail. This can't be in the derived classes.
67 @property
68 def __weakref__(self):
69 return self.__wrapped__.__weakref__
72class _ObjectProxyDictBase:
73 """Base class whose sole purpose is to provide a ``getset_descriptor``
74 for ``__dict__`` that is valid for all ``ObjectProxy`` subclasses.
75 The metaclass installs this descriptor as ``__self_dict__`` so that
76 the real instance dictionary of the proxy can always be accessed,
77 even though ``ObjectProxy`` replaces ``__dict__`` with a property
78 that delegates to the wrapped object."""
80 pass
83_REAL_DICT_DESCRIPTOR = type.__dict__["__dict__"].__get__(_ObjectProxyDictBase)[
84 "__dict__"
85]
88def _get_self_dict(self):
89 return _REAL_DICT_DESCRIPTOR.__get__(self)
92# Wrapping the descriptor in a read-only property ensures that
93# ``proxy.__self_dict__ = value`` raises AttributeError rather than
94# replacing the real instance dictionary (which would break the proxy).
96_SELF_DICT_PROPERTY = property(_get_self_dict)
98# The default __doc__ property which delegates to the wrapped object. A
99# derived class may define its own __doc__ descriptor in its class body
100# to take control of what __doc__ reports for its instances, and that is
101# preserved by the metaclass in place of this default.
103_DEFAULT_DOC_PROPERTY = vars(_ObjectProxyMethods)["__doc__"]
106def _is_doc_descriptor(entry):
107 # Every class carries a __doc__ entry in its dict, being the docstring
108 # or None when there is none. Only a descriptor is taken to be a
109 # deliberate override of the instance level __doc__ property.
111 if entry is None or isinstance(entry, str):
112 return False
113 return hasattr(type(entry), "__get__")
116def _inherited_doc_descriptor(bases):
117 # Find a custom __doc__ descriptor inherited from a base class. The
118 # search stops at the first class which holds the default delegating
119 # property, since a derived class of that should delegate as well. The
120 # C extension performs the equivalent walk of the MRO at the time
121 # __doc__ is accessed.
123 for base in bases:
124 for klass in base.__mro__:
125 entry = vars(klass).get("__doc__")
126 if entry is _DEFAULT_DOC_PROPERTY:
127 return None
128 if _is_doc_descriptor(entry):
129 return entry
130 return None
133class _ObjectProxyMetaType(type):
134 # Properties on the metaclass control type-level access to __module__
135 # and __doc__ (e.g. ObjectProxy.__module__). Without these, the
136 # instance-level properties copied from _ObjectProxyMethods into each
137 # class dict would shadow the string values that type.__new__ sets,
138 # causing type.__module__ to return a property object instead of a
139 # string. The metaclass properties read from internal keys where the
140 # real values are saved.
142 @property
143 def __module__(cls):
144 return cls.__dict__.get("_cls_real_module", "builtins")
146 @__module__.setter
147 def __module__(cls, value):
148 type.__setattr__(cls, "_cls_real_module", value)
150 @property
151 def __doc__(cls):
152 return cls.__dict__.get("_cls_real_doc")
154 @__doc__.setter
155 def __doc__(cls, value):
156 type.__setattr__(cls, "_cls_real_doc", value)
158 def __new__(cls, name, bases, dictionary):
159 # Copy our special properties into the class so that they
160 # always take precedence over attributes of the same name added
161 # during construction of a derived class. This is to save
162 # duplicating the implementation for them in all derived classes.
163 #
164 # Because this overwrites the __module__ and __doc__ strings
165 # that would normally be in the class dict with property objects,
166 # we save the original values first and store them under internal
167 # keys. The metaclass properties above read from these keys to
168 # ensure type-level access (e.g. MyProxy.__module__) returns a
169 # string rather than a property object.
171 real_module = dictionary.get("__module__")
172 real_doc = dictionary.get("__doc__")
174 # If the subclass defines its own __dict__ property, preserve it
175 # rather than overwriting it with the default delegating property
176 # from _ObjectProxyMethods. When __dict__ is not explicitly
177 # defined in the class body, it will not be present in the
178 # dictionary at this point.
180 custom_dict = dictionary.get("__dict__")
182 # Similarly, if the subclass defines __doc__ as a descriptor rather
183 # than as a docstring, preserve it so the subclass controls what
184 # __doc__ reports for its instances. Such a descriptor is not the
185 # class docstring, so it is not recorded as one. A descriptor
186 # defined by a base class is inherited, as it would be for any
187 # class not using this metaclass, by copying it into the class
188 # dictionary where it takes precedence over the None or docstring
189 # entry the class body provides.
191 if _is_doc_descriptor(real_doc):
192 custom_doc = real_doc
193 real_doc = None
194 else:
195 custom_doc = _inherited_doc_descriptor(bases)
197 dictionary.update(vars(_ObjectProxyMethods))
199 if custom_dict is not None:
200 dictionary["__dict__"] = custom_dict
202 if custom_doc is not None:
203 dictionary["__doc__"] = custom_doc
205 dictionary.setdefault("__self_dict__", _SELF_DICT_PROPERTY)
207 klass = type.__new__(cls, name, bases, dictionary)
209 if real_module is not None:
210 type.__setattr__(klass, "_cls_real_module", real_module)
211 if real_doc is not None:
212 type.__setattr__(klass, "_cls_real_doc", real_doc)
214 return klass
217def _unwrap_operand(other):
218 # When the other operand of a binary operator is itself a proxy, apply
219 # the operator to the two wrapped objects rather than passing the proxy
220 # through to the wrapped object's own operator method. This mirrors
221 # wrapt_unwrap_operand() in the C extension. Without it, a wrapped
222 # type which raises TypeError for an unrecognised operand, rather
223 # than returning NotImplemented, would never give the proxy on the
224 # right hand side the chance to unwrap itself via the reflected
225 # method, and Python would not see the real types of the operands
226 # when deciding whether the reflected method of a subclass on the
227 # right hand side takes priority. The real type is checked, and not
228 # __class__, which the proxy reports as that of the wrapped object.
230 if issubclass(type(other), ObjectProxy):
231 return other.__wrapped__
232 return other
235class ObjectProxy(_ObjectProxyDictBase, metaclass=_ObjectProxyMetaType):
236 """A transparent object proxy that delegates attribute access to a
237 wrapped object."""
239 @classmethod
240 def __class_getitem__(cls, item, /):
241 return types.GenericAlias(cls, item)
243 def __new__(cls, *args, **kwargs):
244 # Accept and ignore any arguments. A derived class which adds
245 # arguments to __init__() has the same arguments passed to
246 # __new__(), and a derived class which overrides __new__() may
247 # pass through whatever it was given, as it must when deriving
248 # from AutoObjectProxy which needs the wrapped object in __new__().
249 # Without this, once __new__() is overridden anywhere in the class
250 # hierarchy, the call falls through to object.__new__() which
251 # rejects extra arguments. The C extension already ignores the
252 # arguments in its tp_new slot, so this keeps the two consistent.
254 return super().__new__(cls)
256 def __init__(self, wrapped):
257 """Create an object proxy around the given object."""
259 if wrapped is None:
260 try:
261 callback = object.__getattribute__(self, "__wrapped_factory__")
262 except AttributeError:
263 callback = None
265 if callback is not None:
266 # If wrapped is none and class has a __wrapped_factory__
267 # method, then we don't set __wrapped__ yet and instead will
268 # defer creation of the wrapped object until it is first
269 # needed.
271 pass
273 else:
274 object.__setattr__(self, "__wrapped__", wrapped)
275 else:
276 object.__setattr__(self, "__wrapped__", wrapped)
278 object.__setattr__(self, "__init_called__", True)
280 # Python 3.2+ has the __qualname__ attribute, but it does not
281 # allow it to be overridden using a property and it must instead
282 # be an actual string object instead.
284 try:
285 object.__setattr__(self, "__qualname__", wrapped.__qualname__)
286 except AttributeError:
287 pass
289 # Python 3.10 onwards also does not allow itself to be overridden
290 # using a property and it must instead be set explicitly. Python
291 # 3.14 onwards uses deferred evaluation of annotations via the
292 # __annotate__ attribute, so we copy that instead to avoid
293 # triggering eager evaluation which can fail if names referenced
294 # in annotations have been shadowed.
296 if sys.version_info >= (3, 14):
297 try:
298 object.__setattr__(self, "__annotate__", wrapped.__annotate__)
299 except AttributeError:
300 pass
301 else:
302 try:
303 object.__setattr__(self, "__annotations__", wrapped.__annotations__)
304 except AttributeError:
305 pass
307 @property
308 def __object_proxy__(self):
309 return ObjectProxy
311 def __self_setattr__(self, name, value):
312 object.__setattr__(self, name, value)
314 @property
315 def __name__(self):
316 return self.__wrapped__.__name__
318 @__name__.setter
319 def __name__(self, value):
320 self.__wrapped__.__name__ = value
322 @property
323 def __class__(self):
324 return self.__wrapped__.__class__
326 @__class__.setter
327 def __class__(self, value):
328 self.__wrapped__.__class__ = value
330 def __dir__(self):
331 return dir(self.__wrapped__)
333 def __str__(self):
334 return str(self.__wrapped__)
336 def __bytes__(self):
337 return bytes(self.__wrapped__)
339 def __repr__(self):
340 return f"<{type(self).__name__} at 0x{id(self):x} for {type(self.__wrapped__).__name__} at 0x{id(self.__wrapped__):x}>"
342 def __format__(self, format_spec):
343 return format(self.__wrapped__, format_spec)
345 def __reversed__(self):
346 return reversed(self.__wrapped__)
348 def __round__(self, ndigits=None):
349 return round(self.__wrapped__, ndigits)
351 def __trunc__(self):
352 return math.trunc(self.__wrapped__)
354 def __floor__(self):
355 return math.floor(self.__wrapped__)
357 def __ceil__(self):
358 return math.ceil(self.__wrapped__)
360 def __mro_entries__(self, bases):
361 if not isinstance(self.__wrapped__, type) and hasattr(
362 self.__wrapped__, "__mro_entries__"
363 ):
364 return self.__wrapped__.__mro_entries__(bases)
365 return (self.__wrapped__,)
367 def __lt__(self, other):
368 return self.__wrapped__ < other
370 def __le__(self, other):
371 return self.__wrapped__ <= other
373 def __eq__(self, other):
374 return self.__wrapped__ == other
376 def __ne__(self, other):
377 return self.__wrapped__ != other
379 def __gt__(self, other):
380 return self.__wrapped__ > other
382 def __ge__(self, other):
383 return self.__wrapped__ >= other
385 def __hash__(self):
386 return hash(self.__wrapped__)
388 def __bool__(self):
389 return bool(self.__wrapped__)
391 def __setattr__(self, name, value):
392 if name.startswith("_self_"):
393 object.__setattr__(self, name, value)
395 elif name == "__wrapped__":
396 object.__setattr__(self, name, value)
398 try:
399 object.__delattr__(self, "__qualname__")
400 except AttributeError:
401 pass
402 try:
403 object.__setattr__(self, "__qualname__", value.__qualname__)
404 except AttributeError:
405 pass
406 if sys.version_info >= (3, 14):
407 try:
408 object.__delattr__(self, "__annotate__")
409 except AttributeError:
410 pass
411 try:
412 object.__setattr__(self, "__annotate__", value.__annotate__)
413 except AttributeError:
414 pass
415 else:
416 try:
417 object.__delattr__(self, "__annotations__")
418 except AttributeError:
419 pass
420 try:
421 object.__setattr__(self, "__annotations__", value.__annotations__)
422 except AttributeError:
423 pass
425 __wrapped_setattr_fixups__ = getattr(
426 self, "__wrapped_setattr_fixups__", None
427 )
429 if __wrapped_setattr_fixups__ is not None:
430 __wrapped_setattr_fixups__()
432 elif name == "__qualname__":
433 setattr(self.__wrapped__, name, value)
434 object.__setattr__(self, name, value)
436 elif name == "__annotations__":
437 setattr(self.__wrapped__, name, value)
438 object.__setattr__(self, name, value)
440 elif name == "__annotate__":
441 setattr(self.__wrapped__, name, value)
442 object.__setattr__(self, name, value)
444 elif hasattr(type(self), name):
445 object.__setattr__(self, name, value)
447 else:
448 setattr(self.__wrapped__, name, value)
450 def __getattr__(self, name):
451 # If we need to lookup `__wrapped__` then the `__init__()` method
452 # cannot have been called, or this is a lazy object proxy which is
453 # deferring creation of the wrapped object until it is first needed.
455 if name == "__wrapped__":
456 # Note that we use existance of `__wrapped_factory__` to gate whether
457 # we can attempt to initialize the wrapped object lazily, but it is
458 # `__wrapped_get__` that we actually call to do the initialization.
459 # This is so that we can handle multithreading correctly by having
460 # `__wrapped_get__` use a lock to protect against multiple threads
461 # trying to initialize the wrapped object at the same time.
463 try:
464 object.__getattribute__(self, "__wrapped_factory__")
465 except AttributeError:
466 pass
467 else:
468 return object.__getattribute__(self, "__wrapped_get__")()
470 # If __init__ was called but __wrapped__ is not set, the wrapper
471 # is in an inconsistent state. Raise WrapperNotInitializedError
472 # (a ValueError, not AttributeError) so it is not silently
473 # swallowed by hasattr/getattr patterns.
475 try:
476 object.__getattribute__(self, "__init_called__")
477 except AttributeError:
478 raise AttributeError(
479 f"'{type(self).__name__}' object has no attribute " f"'__wrapped__'"
480 )
482 raise WrapperNotInitializedError(
483 "wrapper is in an inconsistent state: __wrapped__ is not set"
484 )
486 return getattr(self.__wrapped__, name)
488 def __delattr__(self, name):
489 if name.startswith("_self_"):
490 object.__delattr__(self, name)
492 elif name == "__wrapped__":
493 raise TypeError("can't delete __wrapped__ attribute")
495 elif name == "__qualname__":
496 object.__delattr__(self, name)
497 delattr(self.__wrapped__, name)
499 elif name == "__annotations__":
500 try:
501 object.__delattr__(self, name)
502 except AttributeError:
503 pass
504 delattr(self.__wrapped__, name)
506 elif name == "__annotate__":
507 try:
508 object.__delattr__(self, name)
509 except AttributeError:
510 pass
511 delattr(self.__wrapped__, name)
513 elif hasattr(type(self), name):
514 object.__delattr__(self, name)
516 else:
517 delattr(self.__wrapped__, name)
519 def __add__(self, other):
520 other = _unwrap_operand(other)
521 return self.__wrapped__ + other
523 def __sub__(self, other):
524 other = _unwrap_operand(other)
525 return self.__wrapped__ - other
527 def __mul__(self, other):
528 other = _unwrap_operand(other)
529 return self.__wrapped__ * other
531 def __truediv__(self, other):
532 other = _unwrap_operand(other)
533 return operator.truediv(self.__wrapped__, other)
535 def __floordiv__(self, other):
536 other = _unwrap_operand(other)
537 return self.__wrapped__ // other
539 def __mod__(self, other):
540 other = _unwrap_operand(other)
541 return self.__wrapped__ % other
543 def __divmod__(self, other):
544 other = _unwrap_operand(other)
545 return divmod(self.__wrapped__, other)
547 def __pow__(self, other, *args):
548 other = _unwrap_operand(other)
549 return pow(self.__wrapped__, other, *args)
551 def __lshift__(self, other):
552 other = _unwrap_operand(other)
553 return self.__wrapped__ << other
555 def __rshift__(self, other):
556 other = _unwrap_operand(other)
557 return self.__wrapped__ >> other
559 def __and__(self, other):
560 other = _unwrap_operand(other)
561 return self.__wrapped__ & other
563 def __xor__(self, other):
564 other = _unwrap_operand(other)
565 return self.__wrapped__ ^ other
567 def __or__(self, other):
568 other = _unwrap_operand(other)
569 return self.__wrapped__ | other
571 def __radd__(self, other):
572 other = _unwrap_operand(other)
573 return other + self.__wrapped__
575 def __rsub__(self, other):
576 other = _unwrap_operand(other)
577 return other - self.__wrapped__
579 def __rmul__(self, other):
580 other = _unwrap_operand(other)
581 return other * self.__wrapped__
583 def __rtruediv__(self, other):
584 other = _unwrap_operand(other)
585 return operator.truediv(other, self.__wrapped__)
587 def __rfloordiv__(self, other):
588 other = _unwrap_operand(other)
589 return other // self.__wrapped__
591 def __rmod__(self, other):
592 other = _unwrap_operand(other)
593 return other % self.__wrapped__
595 def __rdivmod__(self, other):
596 other = _unwrap_operand(other)
597 return divmod(other, self.__wrapped__)
599 def __rpow__(self, other, *args):
600 other = _unwrap_operand(other)
601 return pow(other, self.__wrapped__, *args)
603 def __rlshift__(self, other):
604 other = _unwrap_operand(other)
605 return other << self.__wrapped__
607 def __rrshift__(self, other):
608 other = _unwrap_operand(other)
609 return other >> self.__wrapped__
611 def __rand__(self, other):
612 other = _unwrap_operand(other)
613 return other & self.__wrapped__
615 def __rxor__(self, other):
616 other = _unwrap_operand(other)
617 return other ^ self.__wrapped__
619 def __ror__(self, other):
620 other = _unwrap_operand(other)
621 return other | self.__wrapped__
623 def __iadd__(self, other):
624 other = _unwrap_operand(other)
625 if hasattr(self.__wrapped__, "__iadd__"):
626 self.__wrapped__ += other
627 return self
628 else:
629 return self.__object_proxy__(self.__wrapped__ + other)
631 def __isub__(self, other):
632 other = _unwrap_operand(other)
633 if hasattr(self.__wrapped__, "__isub__"):
634 self.__wrapped__ -= other
635 return self
636 else:
637 return self.__object_proxy__(self.__wrapped__ - other)
639 def __imul__(self, other):
640 other = _unwrap_operand(other)
641 if hasattr(self.__wrapped__, "__imul__"):
642 self.__wrapped__ *= other
643 return self
644 else:
645 return self.__object_proxy__(self.__wrapped__ * other)
647 def __itruediv__(self, other):
648 other = _unwrap_operand(other)
649 if hasattr(self.__wrapped__, "__itruediv__"):
650 self.__wrapped__ /= other
651 return self
652 else:
653 return self.__object_proxy__(self.__wrapped__ / other)
655 def __ifloordiv__(self, other):
656 other = _unwrap_operand(other)
657 if hasattr(self.__wrapped__, "__ifloordiv__"):
658 self.__wrapped__ //= other
659 return self
660 else:
661 return self.__object_proxy__(self.__wrapped__ // other)
663 def __imod__(self, other):
664 other = _unwrap_operand(other)
665 if hasattr(self.__wrapped__, "__imod__"):
666 self.__wrapped__ %= other
667 return self
668 else:
669 return self.__object_proxy__(self.__wrapped__ % other)
671 def __ipow__(self, other): # type: ignore[misc]
672 other = _unwrap_operand(other)
673 if hasattr(self.__wrapped__, "__ipow__"):
674 self.__wrapped__ **= other
675 return self
676 else:
677 return self.__object_proxy__(self.__wrapped__**other)
679 def __ilshift__(self, other):
680 other = _unwrap_operand(other)
681 if hasattr(self.__wrapped__, "__ilshift__"):
682 self.__wrapped__ <<= other
683 return self
684 else:
685 return self.__object_proxy__(self.__wrapped__ << other)
687 def __irshift__(self, other):
688 other = _unwrap_operand(other)
689 if hasattr(self.__wrapped__, "__irshift__"):
690 self.__wrapped__ >>= other
691 return self
692 else:
693 return self.__object_proxy__(self.__wrapped__ >> other)
695 def __iand__(self, other):
696 other = _unwrap_operand(other)
697 if hasattr(self.__wrapped__, "__iand__"):
698 self.__wrapped__ &= other
699 return self
700 else:
701 return self.__object_proxy__(self.__wrapped__ & other)
703 def __ixor__(self, other):
704 other = _unwrap_operand(other)
705 if hasattr(self.__wrapped__, "__ixor__"):
706 self.__wrapped__ ^= other
707 return self
708 else:
709 return self.__object_proxy__(self.__wrapped__ ^ other)
711 def __ior__(self, other):
712 other = _unwrap_operand(other)
713 if hasattr(self.__wrapped__, "__ior__"):
714 self.__wrapped__ |= other
715 return self
716 else:
717 return self.__object_proxy__(self.__wrapped__ | other)
719 def __neg__(self):
720 return -self.__wrapped__
722 def __pos__(self):
723 return +self.__wrapped__
725 def __abs__(self):
726 return abs(self.__wrapped__)
728 def __invert__(self):
729 return ~self.__wrapped__
731 def __int__(self):
732 return int(self.__wrapped__)
734 def __float__(self):
735 return float(self.__wrapped__)
737 def __complex__(self):
738 return complex(self.__wrapped__)
740 def __index__(self):
741 return operator.index(self.__wrapped__)
743 def __matmul__(self, other):
744 other = _unwrap_operand(other)
745 return self.__wrapped__ @ other
747 def __rmatmul__(self, other):
748 other = _unwrap_operand(other)
749 return other @ self.__wrapped__
751 def __imatmul__(self, other):
752 other = _unwrap_operand(other)
753 if hasattr(self.__wrapped__, "__imatmul__"):
754 self.__wrapped__ @= other
755 return self
756 else:
757 return self.__object_proxy__(self.__wrapped__ @ other)
759 def __len__(self):
760 return len(self.__wrapped__)
762 def __contains__(self, value):
763 return value in self.__wrapped__
765 def __getitem__(self, key):
766 return self.__wrapped__[key]
768 def __setitem__(self, key, value):
769 self.__wrapped__[key] = value
771 def __delitem__(self, key):
772 del self.__wrapped__[key]
774 def __enter__(self):
775 return self.__wrapped__.__enter__()
777 def __exit__(self, *args, **kwargs):
778 return self.__wrapped__.__exit__(*args, **kwargs)
780 def __aenter__(self):
781 return self.__wrapped__.__aenter__()
783 def __aexit__(self, *args, **kwargs):
784 return self.__wrapped__.__aexit__(*args, **kwargs)
786 def __copy__(self):
787 raise NotImplementedError("object proxy must define __copy__()")
789 def __deepcopy__(self, memo):
790 raise NotImplementedError("object proxy must define __deepcopy__()")
792 def __reduce__(self):
793 raise NotImplementedError("object proxy must define __reduce__()")
795 def __instancecheck__(self, instance):
796 return isinstance(instance, self.__wrapped__)
798 def __subclasscheck__(self, subclass):
799 if hasattr(subclass, "__wrapped__"):
800 return issubclass(subclass.__wrapped__, self.__wrapped__)
801 else:
802 return issubclass(subclass, self.__wrapped__)
805class CallableObjectProxy(ObjectProxy):
806 """An object proxy for callable objects that also forwards calls."""
808 def __call__(*args, **kwargs):
809 def _unpack_self(self, *args):
810 return self, args
812 self, args = _unpack_self(*args)
814 return self.__wrapped__(*args, **kwargs)
817class _PartialSignatureDescriptor:
818 """Descriptor providing the ``__signature__`` attribute of instances of
819 ``PartialCallableObjectProxy``.
821 The signature reported is that of the wrapped callable with the bound
822 positional and keyword arguments removed, matching what ``inspect``
823 reports for ``functools.partial``. It must be defined on the proxy type
824 itself, since attribute lookup on the proxy would otherwise be forwarded
825 to the wrapped callable, and ``inspect.signature()`` stops following
826 ``__wrapped__`` at the first object which has a ``__signature__``
827 attribute.
829 A plain property cannot be used because it would also be visible when
830 accessed on the class, and ``inspect.signature()`` applied to the class
831 itself would then fail on finding a property object rather than a
832 ``Signature``. Raising ``AttributeError`` on class access leaves the
833 signature of the class unchanged.
834 """
836 def __get__(self, instance, owner=None):
837 if instance is None:
838 raise AttributeError("__signature__")
840 partial = functools.partial(
841 instance.__wrapped__, *instance._self_args, **instance._self_kwargs
842 )
844 return inspect.signature(partial)
847class PartialCallableObjectProxy(ObjectProxy):
848 """A callable object proxy that supports partial application of arguments
849 and keywords.
850 """
852 __signature__ = _PartialSignatureDescriptor()
854 def __init__(*args, **kwargs):
855 """Create a callable object proxy with partial application of the given
856 arguments and keywords. This behaves the same as `functools.partial`, but
857 implemented using the `ObjectProxy` class to provide better support for
858 introspection.
859 """
861 def _unpack_self(self, *args):
862 return self, args
864 self, args = _unpack_self(*args)
866 if len(args) < 1:
867 raise TypeError("partial type takes at least one argument")
869 wrapped, args = args[0], args[1:]
871 if not callable(wrapped):
872 raise TypeError("the first argument must be callable")
874 # Explicit class in super() is used because the proxy overrides
875 # __class__ and MRO-related methods to delegate to the wrapped
876 # object, which can interfere with bare super().
877 super(PartialCallableObjectProxy, self).__init__(wrapped)
879 self._self_args = args
880 self._self_kwargs = kwargs
882 def __call__(*args, **kwargs):
883 def _unpack_self(self, *args):
884 return self, args
886 self, args = _unpack_self(*args)
888 _args = self._self_args + args
890 _kwargs = dict(self._self_kwargs)
891 _kwargs.update(kwargs)
893 return self.__wrapped__(*_args, **_kwargs)
896class _FunctionWrapperBase(ObjectProxy):
898 def __init__(
899 self,
900 wrapped,
901 instance,
902 wrapper,
903 enabled=None,
904 binding="callable",
905 parent=None,
906 owner=None,
907 ):
909 # Explicit class in super() is used because the proxy overrides
910 # __class__ and MRO-related methods to delegate to the wrapped
911 # object, which can interfere with bare super().
912 super(_FunctionWrapperBase, self).__init__(wrapped)
914 object.__setattr__(self, "_self_instance", instance)
915 object.__setattr__(self, "_self_wrapper", wrapper)
916 object.__setattr__(self, "_self_enabled", enabled)
917 object.__setattr__(self, "_self_binding", binding)
918 object.__setattr__(self, "_self_parent", parent)
919 object.__setattr__(self, "_self_owner", owner)
921 def __get__(self, instance, owner=None):
922 # This method handles both unbound and bound derived wrapper classes.
923 # It is kept in the base class as the amount of common code makes it
924 # impractical to split into the derived classes.
925 #
926 # The distinguishing attribute which determines whether we are being
927 # called in an unbound or bound wrapper is the parent attribute. If
928 # binding has never occurred, then the parent will be None.
929 #
930 # First therefore, is if we are called in an unbound wrapper. In this
931 # case we perform the binding.
932 #
933 # We have two special cases to worry about here. These are where we are
934 # decorating a class or builtin function as neither provide a __get__()
935 # method to call. In this case we simply return self.
936 #
937 # Note that we otherwise still do binding even if instance is None and
938 # accessing an unbound instance method from a class. This is because we
939 # need to be able to later detect that specific case as we will need to
940 # extract the instance from the first argument of those passed in.
942 if self._self_parent is None:
943 # Technically can probably just check for existence of __get__ on
944 # the wrapped object, but this is more explicit.
946 if self._self_binding == "builtin":
947 return self
949 if self._self_binding == "class":
950 return self
952 binder = getattr(self.__wrapped__, "__get__", None)
954 if binder is None:
955 return self
957 descriptor = binder(instance, owner)
959 return self.__bound_function_wrapper__(
960 descriptor,
961 instance,
962 self._self_wrapper,
963 self._self_enabled,
964 self._self_binding,
965 self,
966 owner,
967 )
969 # Now we have the case of binding occurring a second time on what was
970 # already a bound function. In this case we would usually return
971 # ourselves again. This mirrors what Python does.
972 #
973 # The special case this time is where we were originally bound with an
974 # instance of None and we were likely an instance method. In that case
975 # we rebind against the original wrapped function from the parent again.
977 if self._self_instance is None and self._self_binding in (
978 "function",
979 "instancemethod",
980 "callable",
981 ):
982 descriptor = self._self_parent.__wrapped__.__get__(instance, owner)
984 return self._self_parent.__bound_function_wrapper__(
985 descriptor,
986 instance,
987 self._self_wrapper,
988 self._self_enabled,
989 self._self_binding,
990 self._self_parent,
991 owner,
992 )
994 return self
996 def __call__(*args, **kwargs):
997 def _unpack_self(self, *args):
998 return self, args
1000 self, args = _unpack_self(*args)
1002 # If enabled has been specified, then evaluate it at this point
1003 # and if the wrapper is not to be executed, then simply return
1004 # the bound function rather than a bound wrapper for the bound
1005 # function. When evaluating enabled, if it is callable we call
1006 # it, otherwise we evaluate it as a boolean.
1008 if self._self_enabled is not None:
1009 if callable(self._self_enabled):
1010 if not self._self_enabled():
1011 return self.__wrapped__(*args, **kwargs)
1012 elif not self._self_enabled:
1013 return self.__wrapped__(*args, **kwargs)
1015 # This can occur where initial function wrapper was applied to
1016 # a function that was already bound to an instance. In that case
1017 # we want to extract the instance from the function and use it.
1019 if self._self_binding in (
1020 "function",
1021 "instancemethod",
1022 "classmethod",
1023 "callable",
1024 ):
1025 if self._self_instance is None:
1026 instance = getattr(self.__wrapped__, "__self__", None)
1027 if instance is not None:
1028 return self._self_wrapper(self.__wrapped__, instance, args, kwargs)
1030 # This is generally invoked when the wrapped function is being
1031 # called as a normal function and is not bound to a class as an
1032 # instance method. This is also invoked in the case where the
1033 # wrapped function was a method, but this wrapper was in turn
1034 # wrapped using the staticmethod decorator.
1036 return self._self_wrapper(self.__wrapped__, self._self_instance, args, kwargs)
1038 def __set_name__(self, owner, name):
1039 # This is a special method use to supply information to
1040 # descriptors about what the name of variable in a class
1041 # definition is. Not wanting to add this to ObjectProxy as not
1042 # sure of broader implications of doing that. Thus restrict to
1043 # FunctionWrapper used by decorators.
1045 if hasattr(self.__wrapped__, "__set_name__"):
1046 self.__wrapped__.__set_name__(owner, name)
1049_FUNCTION_WRAPPER_SLOTS = frozenset(
1050 (
1051 "_self_instance",
1052 "_self_wrapper",
1053 "_self_enabled",
1054 "_self_binding",
1055 "_self_parent",
1056 "_self_owner",
1057 )
1058)
1061class BoundFunctionWrapper(_FunctionWrapperBase):
1062 """A wrapper for bound methods, classmethods, and staticmethods."""
1064 def __setattr__(self, name, value):
1065 if name.startswith("_self_") and name not in _FUNCTION_WRAPPER_SLOTS:
1066 if self._self_parent is not None:
1067 object.__setattr__(self._self_parent, name, value)
1068 return
1069 super().__setattr__(name, value)
1071 def __getattr__(self, name):
1072 # This is only reached for _self_parent when that attribute was
1073 # never set, which means __init__() was not called. It has to fail
1074 # here, as the lookup of it below would otherwise come straight
1075 # back in and recurse without end.
1077 if name == "_self_parent":
1078 raise AttributeError(
1079 f"'{type(self).__name__}' object has no attribute '{name}'"
1080 )
1082 if self._self_parent is not None:
1083 try:
1084 return getattr(self._self_parent, name)
1085 except AttributeError:
1086 pass
1087 return super().__getattr__(name)
1089 def __call__(*args, **kwargs):
1090 def _unpack_self(self, *args):
1091 return self, args
1093 self, args = _unpack_self(*args)
1095 # If enabled has been specified, then evaluate it at this point and if
1096 # the wrapper is not to be executed, then simply return the bound
1097 # function rather than a bound wrapper for the bound function. When
1098 # evaluating enabled, if it is callable we call it, otherwise we
1099 # evaluate it as a boolean.
1101 if self._self_enabled is not None:
1102 if callable(self._self_enabled):
1103 if not self._self_enabled():
1104 return self.__wrapped__(*args, **kwargs)
1105 elif not self._self_enabled:
1106 return self.__wrapped__(*args, **kwargs)
1108 # We need to do things different depending on whether we are likely
1109 # wrapping an instance method vs a static method or class method.
1111 if self._self_binding == "function":
1112 if self._self_instance is None and args:
1113 instance, newargs = args[0], args[1:]
1114 if isinstance(instance, self._self_owner):
1115 wrapped = PartialCallableObjectProxy(self.__wrapped__, instance)
1116 return self._self_wrapper(wrapped, instance, newargs, kwargs)
1118 return self._self_wrapper(
1119 self.__wrapped__, self._self_instance, args, kwargs
1120 )
1122 elif self._self_binding == "callable":
1123 if self._self_instance is None and args:
1124 # This situation can occur where someone is calling the
1125 # instancemethod via the class type and passing the instance as
1126 # the first argument. We need to shift the args before making
1127 # the call to the wrapper and effectively bind the instance to
1128 # the wrapped function using a partial so the wrapper doesn't
1129 # see anything as being different.
1131 instance, newargs = args[0], args[1:]
1132 if isinstance(instance, self._self_owner):
1133 wrapped = PartialCallableObjectProxy(self.__wrapped__, instance)
1134 return self._self_wrapper(wrapped, instance, newargs, kwargs)
1136 return self._self_wrapper(
1137 self.__wrapped__, self._self_instance, args, kwargs
1138 )
1140 else:
1141 # As in this case we would be dealing with a classmethod or
1142 # staticmethod, then _self_instance will only tell us whether
1143 # when calling the classmethod or staticmethod they did it via an
1144 # instance of the class it is bound to and not the case where
1145 # done by the class type itself. We thus ignore _self_instance
1146 # and use the __self__ attribute of the bound function instead.
1147 # For a classmethod, this means instance will be the class type
1148 # and for a staticmethod it will be None. This is probably the
1149 # more useful thing we can pass through even though we loose
1150 # knowledge of whether they were called on the instance vs the
1151 # class type, as it reflects what they have available in the
1152 # decoratored function.
1154 instance = getattr(self.__wrapped__, "__self__", None)
1156 return self._self_wrapper(self.__wrapped__, instance, args, kwargs)
1159class FunctionWrapper(_FunctionWrapperBase):
1160 """
1161 A wrapper for callable objects that can be used to apply decorators to
1162 functions, methods, classmethods, and staticmethods, or any other callable.
1163 It handles binding and unbinding of methods, and allows for the wrapper to
1164 be enabled or disabled.
1165 """
1167 __bound_function_wrapper__ = BoundFunctionWrapper
1169 def __init__(self, wrapped, wrapper, enabled=None):
1170 """
1171 Initialize the `FunctionWrapper` with the `wrapped` callable, the
1172 `wrapper` function, and an optional `enabled` argument. The `enabled`
1173 argument can be a boolean or a callable that returns a boolean. When a
1174 callable is provided, it will be called each time the wrapper is
1175 invoked to determine if the wrapper function should be executed or
1176 whether the wrapped function should be called directly. If `enabled`
1177 is not provided, the wrapper is enabled by default.
1178 """
1180 # What it is we are wrapping here could be anything. We need to
1181 # try and detect specific cases though. In particular, we need
1182 # to detect when we are given something that is a method of a
1183 # class. Further, we need to know when it is likely an instance
1184 # method, as opposed to a class or static method. This can
1185 # become problematic though as there isn't strictly a fool proof
1186 # method of knowing.
1187 #
1188 # The situations we could encounter when wrapping a method are:
1189 #
1190 # 1. The wrapper is being applied as part of a decorator which
1191 # is a part of the class definition. In this case what we are
1192 # given is the raw unbound function, classmethod or staticmethod
1193 # wrapper objects.
1194 #
1195 # The problem here is that we will not know we are being applied
1196 # in the context of the class being set up. This becomes
1197 # important later for the case of an instance method, because in
1198 # that case we just see it as a raw function and can't
1199 # distinguish it from wrapping a normal function outside of
1200 # a class context.
1201 #
1202 # 2. The wrapper is being applied when performing monkey
1203 # patching of the class type afterwards and the method to be
1204 # wrapped was retrieved direct from the __dict__ of the class
1205 # type. This is effectively the same as (1) above.
1206 #
1207 # 3. The wrapper is being applied when performing monkey
1208 # patching of the class type afterwards and the method to be
1209 # wrapped was retrieved from the class type. In this case
1210 # binding will have been performed where the instance against
1211 # which the method is bound will be None at that point.
1212 #
1213 # This case is a problem because we can no longer tell if the
1214 # method was a static method, plus if using Python3, we cannot
1215 # tell if it was an instance method as the concept of an
1216 # unnbound method no longer exists.
1217 #
1218 # 4. The wrapper is being applied when performing monkey
1219 # patching of an instance of a class. In this case binding will
1220 # have been performed where the instance was not None.
1221 #
1222 # This case is a problem because we can no longer tell if the
1223 # method was a static method.
1224 #
1225 # Overall, the best we can do is look at the original type of the
1226 # object which was wrapped prior to any binding being done and
1227 # see if it is an instance of classmethod or staticmethod. In
1228 # the case where other decorators are between us and them, if
1229 # they do not propagate the __class__ attribute so that the
1230 # isinstance() checks works, then likely this will do the wrong
1231 # thing where classmethod and staticmethod are used.
1232 #
1233 # Since it is likely to be very rare that anyone even puts
1234 # decorators around classmethod and staticmethod, likelihood of
1235 # that being an issue is very small, so we accept it and suggest
1236 # that those other decorators be fixed. It is also only an issue
1237 # if a decorator wants to actually do things with the arguments.
1238 #
1239 # As to not being able to identify static methods properly, we
1240 # just hope that that isn't something people are going to want
1241 # to wrap, or if they do suggest they do it the correct way by
1242 # ensuring that it is decorated in the class definition itself,
1243 # or patch it in the __dict__ of the class type.
1244 #
1245 # So to get the best outcome we can, whenever we aren't sure what
1246 # it is, we label it as a 'callable'. If it was already bound and
1247 # that is rebound later, we assume that it will be an instance
1248 # method and try and cope with the possibility that the 'self'
1249 # argument it being passed as an explicit argument and shuffle
1250 # the arguments around to extract 'self' for use as the instance.
1252 binding = None
1254 if isinstance(wrapped, _FunctionWrapperBase):
1255 binding = wrapped._self_binding
1257 if not binding:
1258 if inspect.isbuiltin(wrapped):
1259 binding = "builtin"
1261 elif inspect.isfunction(wrapped):
1262 binding = "function"
1264 elif inspect.isclass(wrapped):
1265 binding = "class"
1267 elif isinstance(wrapped, classmethod):
1268 binding = "classmethod"
1270 elif isinstance(wrapped, staticmethod):
1271 binding = "staticmethod"
1273 elif hasattr(wrapped, "__self__"):
1274 if inspect.isclass(wrapped.__self__):
1275 binding = "classmethod"
1276 elif inspect.ismethod(wrapped):
1277 binding = "instancemethod"
1278 else:
1279 binding = "callable"
1281 else:
1282 binding = "callable"
1284 # Explicit class in super() is used because the proxy overrides
1285 # __class__ and MRO-related methods to delegate to the wrapped
1286 # object, which can interfere with bare super().
1287 super(FunctionWrapper, self).__init__(wrapped, None, wrapper, enabled, binding)