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

529 statements  

1"""Core object proxy and function wrapper implementations.""" 

2 

3import inspect 

4import math 

5import operator 

6import sys 

7import types 

8 

9 

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 """ 

16 

17 pass 

18 

19 

20class _ObjectProxyMethods: 

21 

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. 

37 

38 @property 

39 def __module__(self): 

40 return self.__wrapped__.__module__ 

41 

42 @__module__.setter 

43 def __module__(self, value): 

44 self.__wrapped__.__module__ = value 

45 

46 @property 

47 def __doc__(self): 

48 return self.__wrapped__.__doc__ 

49 

50 @__doc__.setter 

51 def __doc__(self, value): 

52 self.__wrapped__.__doc__ = value 

53 

54 # We similar use a property for __dict__. We need __dict__ to be 

55 # explicit to ensure that vars() works as expected. 

56 

57 @property 

58 def __dict__(self): 

59 return self.__wrapped__.__dict__ 

60 

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. 

65 

66 @property 

67 def __weakref__(self): 

68 return self.__wrapped__.__weakref__ 

69 

70 

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.""" 

78 

79 pass 

80 

81 

82_REAL_DICT_DESCRIPTOR = type.__dict__["__dict__"].__get__(_ObjectProxyDictBase)[ 

83 "__dict__" 

84] 

85 

86 

87def _get_self_dict(self): 

88 return _REAL_DICT_DESCRIPTOR.__get__(self) 

89 

90 

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). 

94 

95_SELF_DICT_PROPERTY = property(_get_self_dict) 

96 

97 

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. 

106 

107 @property 

108 def __module__(cls): 

109 return cls.__dict__.get("_cls_real_module", "builtins") 

110 

111 @__module__.setter 

112 def __module__(cls, value): 

113 type.__setattr__(cls, "_cls_real_module", value) 

114 

115 @property 

116 def __doc__(cls): 

117 return cls.__dict__.get("_cls_real_doc") 

118 

119 @__doc__.setter 

120 def __doc__(cls, value): 

121 type.__setattr__(cls, "_cls_real_doc", value) 

122 

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. 

135 

136 real_module = dictionary.get("__module__") 

137 real_doc = dictionary.get("__doc__") 

138 

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. 

144 

145 custom_dict = dictionary.get("__dict__") 

146 

147 dictionary.update(vars(_ObjectProxyMethods)) 

148 

149 if custom_dict is not None: 

150 dictionary["__dict__"] = custom_dict 

151 

152 dictionary.setdefault("__self_dict__", _SELF_DICT_PROPERTY) 

153 

154 klass = type.__new__(cls, name, bases, dictionary) 

155 

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) 

160 

161 return klass 

162 

163 

164class ObjectProxy(_ObjectProxyDictBase, metaclass=_ObjectProxyMetaType): 

165 """A transparent object proxy that delegates attribute access to a 

166 wrapped object.""" 

167 

168 @classmethod 

169 def __class_getitem__(cls, item, /): 

170 return types.GenericAlias(cls, item) 

171 

172 def __init__(self, wrapped): 

173 """Create an object proxy around the given object.""" 

174 

175 if wrapped is None: 

176 try: 

177 callback = object.__getattribute__(self, "__wrapped_factory__") 

178 except AttributeError: 

179 callback = None 

180 

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. 

186 

187 pass 

188 

189 else: 

190 object.__setattr__(self, "__wrapped__", wrapped) 

191 else: 

192 object.__setattr__(self, "__wrapped__", wrapped) 

193 

194 object.__setattr__(self, "__init_called__", True) 

195 

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. 

199 

200 try: 

201 object.__setattr__(self, "__qualname__", wrapped.__qualname__) 

202 except AttributeError: 

203 pass 

204 

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. 

211 

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 

222 

223 @property 

224 def __object_proxy__(self): 

225 return ObjectProxy 

226 

227 def __self_setattr__(self, name, value): 

228 object.__setattr__(self, name, value) 

229 

230 @property 

231 def __name__(self): 

232 return self.__wrapped__.__name__ 

233 

234 @__name__.setter 

235 def __name__(self, value): 

236 self.__wrapped__.__name__ = value 

237 

238 @property 

239 def __class__(self): 

240 return self.__wrapped__.__class__ 

241 

242 @__class__.setter 

243 def __class__(self, value): 

244 self.__wrapped__.__class__ = value 

245 

246 def __dir__(self): 

247 return dir(self.__wrapped__) 

248 

249 def __str__(self): 

250 return str(self.__wrapped__) 

251 

252 def __bytes__(self): 

253 return bytes(self.__wrapped__) 

254 

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}>" 

257 

258 def __format__(self, format_spec): 

259 return format(self.__wrapped__, format_spec) 

260 

261 def __reversed__(self): 

262 return reversed(self.__wrapped__) 

263 

264 def __round__(self, ndigits=None): 

265 return round(self.__wrapped__, ndigits) 

266 

267 def __trunc__(self): 

268 return math.trunc(self.__wrapped__) 

269 

270 def __floor__(self): 

271 return math.floor(self.__wrapped__) 

272 

273 def __ceil__(self): 

274 return math.ceil(self.__wrapped__) 

275 

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__,) 

282 

283 def __lt__(self, other): 

284 return self.__wrapped__ < other 

285 

286 def __le__(self, other): 

287 return self.__wrapped__ <= other 

288 

289 def __eq__(self, other): 

290 return self.__wrapped__ == other 

291 

292 def __ne__(self, other): 

293 return self.__wrapped__ != other 

294 

295 def __gt__(self, other): 

296 return self.__wrapped__ > other 

297 

298 def __ge__(self, other): 

299 return self.__wrapped__ >= other 

300 

301 def __hash__(self): 

302 return hash(self.__wrapped__) 

303 

304 def __bool__(self): 

305 return bool(self.__wrapped__) 

306 

307 def __setattr__(self, name, value): 

308 if name.startswith("_self_"): 

309 object.__setattr__(self, name, value) 

310 

311 elif name == "__wrapped__": 

312 object.__setattr__(self, name, value) 

313 

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 

340 

341 __wrapped_setattr_fixups__ = getattr( 

342 self, "__wrapped_setattr_fixups__", None 

343 ) 

344 

345 if __wrapped_setattr_fixups__ is not None: 

346 __wrapped_setattr_fixups__() 

347 

348 elif name == "__qualname__": 

349 setattr(self.__wrapped__, name, value) 

350 object.__setattr__(self, name, value) 

351 

352 elif name == "__annotations__": 

353 setattr(self.__wrapped__, name, value) 

354 object.__setattr__(self, name, value) 

355 

356 elif name == "__annotate__": 

357 setattr(self.__wrapped__, name, value) 

358 object.__setattr__(self, name, value) 

359 

360 elif hasattr(type(self), name): 

361 object.__setattr__(self, name, value) 

362 

363 else: 

364 setattr(self.__wrapped__, name, value) 

365 

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. 

370 

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. 

378 

379 try: 

380 object.__getattribute__(self, "__wrapped_factory__") 

381 except AttributeError: 

382 pass 

383 else: 

384 return object.__getattribute__(self, "__wrapped_get__")() 

385 

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. 

390 

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 ) 

397 

398 raise WrapperNotInitializedError( 

399 "wrapper is in an inconsistent state: __wrapped__ is not set" 

400 ) 

401 

402 return getattr(self.__wrapped__, name) 

403 

404 def __delattr__(self, name): 

405 if name.startswith("_self_"): 

406 object.__delattr__(self, name) 

407 

408 elif name == "__wrapped__": 

409 raise TypeError("can't delete __wrapped__ attribute") 

410 

411 elif name == "__qualname__": 

412 object.__delattr__(self, name) 

413 delattr(self.__wrapped__, name) 

414 

415 elif name == "__annotations__": 

416 try: 

417 object.__delattr__(self, name) 

418 except AttributeError: 

419 pass 

420 delattr(self.__wrapped__, name) 

421 

422 elif name == "__annotate__": 

423 try: 

424 object.__delattr__(self, name) 

425 except AttributeError: 

426 pass 

427 delattr(self.__wrapped__, name) 

428 

429 elif hasattr(type(self), name): 

430 object.__delattr__(self, name) 

431 

432 else: 

433 delattr(self.__wrapped__, name) 

434 

435 def __add__(self, other): 

436 return self.__wrapped__ + other 

437 

438 def __sub__(self, other): 

439 return self.__wrapped__ - other 

440 

441 def __mul__(self, other): 

442 return self.__wrapped__ * other 

443 

444 def __truediv__(self, other): 

445 return operator.truediv(self.__wrapped__, other) 

446 

447 def __floordiv__(self, other): 

448 return self.__wrapped__ // other 

449 

450 def __mod__(self, other): 

451 return self.__wrapped__ % other 

452 

453 def __divmod__(self, other): 

454 return divmod(self.__wrapped__, other) 

455 

456 def __pow__(self, other, *args): 

457 return pow(self.__wrapped__, other, *args) 

458 

459 def __lshift__(self, other): 

460 return self.__wrapped__ << other 

461 

462 def __rshift__(self, other): 

463 return self.__wrapped__ >> other 

464 

465 def __and__(self, other): 

466 return self.__wrapped__ & other 

467 

468 def __xor__(self, other): 

469 return self.__wrapped__ ^ other 

470 

471 def __or__(self, other): 

472 return self.__wrapped__ | other 

473 

474 def __radd__(self, other): 

475 return other + self.__wrapped__ 

476 

477 def __rsub__(self, other): 

478 return other - self.__wrapped__ 

479 

480 def __rmul__(self, other): 

481 return other * self.__wrapped__ 

482 

483 def __rtruediv__(self, other): 

484 return operator.truediv(other, self.__wrapped__) 

485 

486 def __rfloordiv__(self, other): 

487 return other // self.__wrapped__ 

488 

489 def __rmod__(self, other): 

490 return other % self.__wrapped__ 

491 

492 def __rdivmod__(self, other): 

493 return divmod(other, self.__wrapped__) 

494 

495 def __rpow__(self, other, *args): 

496 return pow(other, self.__wrapped__, *args) 

497 

498 def __rlshift__(self, other): 

499 return other << self.__wrapped__ 

500 

501 def __rrshift__(self, other): 

502 return other >> self.__wrapped__ 

503 

504 def __rand__(self, other): 

505 return other & self.__wrapped__ 

506 

507 def __rxor__(self, other): 

508 return other ^ self.__wrapped__ 

509 

510 def __ror__(self, other): 

511 return other | self.__wrapped__ 

512 

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) 

519 

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) 

526 

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) 

533 

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) 

540 

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) 

547 

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) 

554 

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) 

561 

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) 

568 

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) 

575 

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) 

582 

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) 

589 

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) 

596 

597 def __neg__(self): 

598 return -self.__wrapped__ 

599 

600 def __pos__(self): 

601 return +self.__wrapped__ 

602 

603 def __abs__(self): 

604 return abs(self.__wrapped__) 

605 

606 def __invert__(self): 

607 return ~self.__wrapped__ 

608 

609 def __int__(self): 

610 return int(self.__wrapped__) 

611 

612 def __float__(self): 

613 return float(self.__wrapped__) 

614 

615 def __complex__(self): 

616 return complex(self.__wrapped__) 

617 

618 def __index__(self): 

619 return operator.index(self.__wrapped__) 

620 

621 def __matmul__(self, other): 

622 return self.__wrapped__ @ other 

623 

624 def __rmatmul__(self, other): 

625 return other @ self.__wrapped__ 

626 

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) 

633 

634 def __len__(self): 

635 return len(self.__wrapped__) 

636 

637 def __contains__(self, value): 

638 return value in self.__wrapped__ 

639 

640 def __getitem__(self, key): 

641 return self.__wrapped__[key] 

642 

643 def __setitem__(self, key, value): 

644 self.__wrapped__[key] = value 

645 

646 def __delitem__(self, key): 

647 del self.__wrapped__[key] 

648 

649 def __enter__(self): 

650 return self.__wrapped__.__enter__() 

651 

652 def __exit__(self, *args, **kwargs): 

653 return self.__wrapped__.__exit__(*args, **kwargs) 

654 

655 def __aenter__(self): 

656 return self.__wrapped__.__aenter__() 

657 

658 def __aexit__(self, *args, **kwargs): 

659 return self.__wrapped__.__aexit__(*args, **kwargs) 

660 

661 def __copy__(self): 

662 raise NotImplementedError("object proxy must define __copy__()") 

663 

664 def __deepcopy__(self, memo): 

665 raise NotImplementedError("object proxy must define __deepcopy__()") 

666 

667 def __reduce__(self): 

668 raise NotImplementedError("object proxy must define __reduce__()") 

669 

670 def __instancecheck__(self, instance): 

671 return isinstance(instance, self.__wrapped__) 

672 

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__) 

678 

679 

680class CallableObjectProxy(ObjectProxy): 

681 """An object proxy for callable objects that also forwards calls.""" 

682 

683 def __call__(*args, **kwargs): 

684 def _unpack_self(self, *args): 

685 return self, args 

686 

687 self, args = _unpack_self(*args) 

688 

689 return self.__wrapped__(*args, **kwargs) 

690 

691 

692class PartialCallableObjectProxy(ObjectProxy): 

693 """A callable object proxy that supports partial application of arguments 

694 and keywords. 

695 """ 

696 

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 """ 

703 

704 def _unpack_self(self, *args): 

705 return self, args 

706 

707 self, args = _unpack_self(*args) 

708 

709 if len(args) < 1: 

710 raise TypeError("partial type takes at least one argument") 

711 

712 wrapped, args = args[0], args[1:] 

713 

714 if not callable(wrapped): 

715 raise TypeError("the first argument must be callable") 

716 

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) 

721 

722 self._self_args = args 

723 self._self_kwargs = kwargs 

724 

725 def __call__(*args, **kwargs): 

726 def _unpack_self(self, *args): 

727 return self, args 

728 

729 self, args = _unpack_self(*args) 

730 

731 _args = self._self_args + args 

732 

733 _kwargs = dict(self._self_kwargs) 

734 _kwargs.update(kwargs) 

735 

736 return self.__wrapped__(*_args, **_kwargs) 

737 

738 

739class _FunctionWrapperBase(ObjectProxy): 

740 

741 def __init__( 

742 self, 

743 wrapped, 

744 instance, 

745 wrapper, 

746 enabled=None, 

747 binding="callable", 

748 parent=None, 

749 owner=None, 

750 ): 

751 

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) 

756 

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) 

763 

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. 

784 

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. 

788 

789 if self._self_binding == "builtin": 

790 return self 

791 

792 if self._self_binding == "class": 

793 return self 

794 

795 binder = getattr(self.__wrapped__, "__get__", None) 

796 

797 if binder is None: 

798 return self 

799 

800 descriptor = binder(instance, owner) 

801 

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 ) 

811 

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. 

819 

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) 

826 

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 ) 

836 

837 return self 

838 

839 def __call__(*args, **kwargs): 

840 def _unpack_self(self, *args): 

841 return self, args 

842 

843 self, args = _unpack_self(*args) 

844 

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. 

850 

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) 

857 

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. 

861 

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) 

872 

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. 

878 

879 return self._self_wrapper(self.__wrapped__, self._self_instance, args, kwargs) 

880 

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. 

887 

888 if hasattr(self.__wrapped__, "__set_name__"): 

889 self.__wrapped__.__set_name__(owner, name) 

890 

891 

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) 

902 

903 

904class BoundFunctionWrapper(_FunctionWrapperBase): 

905 """A wrapper for bound methods, classmethods, and staticmethods.""" 

906 

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) 

913 

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) 

921 

922 def __call__(*args, **kwargs): 

923 def _unpack_self(self, *args): 

924 return self, args 

925 

926 self, args = _unpack_self(*args) 

927 

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. 

933 

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) 

940 

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. 

943 

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) 

950 

951 return self._self_wrapper( 

952 self.__wrapped__, self._self_instance, args, kwargs 

953 ) 

954 

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. 

963 

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) 

968 

969 return self._self_wrapper( 

970 self.__wrapped__, self._self_instance, args, kwargs 

971 ) 

972 

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. 

986 

987 instance = getattr(self.__wrapped__, "__self__", None) 

988 

989 return self._self_wrapper(self.__wrapped__, instance, args, kwargs) 

990 

991 

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 """ 

999 

1000 __bound_function_wrapper__ = BoundFunctionWrapper 

1001 

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 """ 

1012 

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. 

1084 

1085 binding = None 

1086 

1087 if isinstance(wrapped, _FunctionWrapperBase): 

1088 binding = wrapped._self_binding 

1089 

1090 if not binding: 

1091 if inspect.isbuiltin(wrapped): 

1092 binding = "builtin" 

1093 

1094 elif inspect.isfunction(wrapped): 

1095 binding = "function" 

1096 

1097 elif inspect.isclass(wrapped): 

1098 binding = "class" 

1099 

1100 elif isinstance(wrapped, classmethod): 

1101 binding = "classmethod" 

1102 

1103 elif isinstance(wrapped, staticmethod): 

1104 binding = "staticmethod" 

1105 

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" 

1113 

1114 else: 

1115 binding = "callable" 

1116 

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)