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

520 statements  

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

2 

3import inspect 

4import operator 

5import sys 

6import types 

7 

8 

9class WrapperNotInitializedError(ValueError): 

10 """ 

11 Exception raised when a wrapper is in an inconsistent state: __init__ was 

12 called but __wrapped__ is not set. Inherits from ValueError only, so it is 

13 not silently swallowed by hasattr/getattr/except AttributeError patterns. 

14 """ 

15 

16 pass 

17 

18 

19class _ObjectProxyMethods: 

20 

21 # We use properties to override the values of __module__ and 

22 # __doc__. If we add these in ObjectProxy, the derived class 

23 # __dict__ will still be setup to have string variants of these 

24 # attributes and the rules of descriptors means that they appear to 

25 # take precedence over the properties in the base class. To avoid 

26 # that, we copy the properties into the derived class type itself 

27 # via a meta class. In that way the properties will always take 

28 # precedence. 

29 # 

30 # Note that because these properties end up in the class __dict__, 

31 # type-level access (e.g. ObjectProxy.__module__) would return the 

32 # property object rather than a string, since CPython's 

33 # type.__module__ getter does a raw dict lookup without invoking the 

34 # descriptor protocol. The metaclass has its own __module__ and 

35 # __doc__ properties to handle type-level access correctly. 

36 

37 @property 

38 def __module__(self): 

39 return self.__wrapped__.__module__ 

40 

41 @__module__.setter 

42 def __module__(self, value): 

43 self.__wrapped__.__module__ = value 

44 

45 @property 

46 def __doc__(self): 

47 return self.__wrapped__.__doc__ 

48 

49 @__doc__.setter 

50 def __doc__(self, value): 

51 self.__wrapped__.__doc__ = value 

52 

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

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

55 

56 @property 

57 def __dict__(self): 

58 return self.__wrapped__.__dict__ 

59 

60 # Need to also propagate the special __weakref__ attribute for case 

61 # where decorating classes which will define this. If do not define 

62 # it and use a function like inspect.getmembers() on a decorator 

63 # class it will fail. This can't be in the derived classes. 

64 

65 @property 

66 def __weakref__(self): 

67 return self.__wrapped__.__weakref__ 

68 

69 

70class _ObjectProxyDictBase: 

71 """Base class whose sole purpose is to provide a ``getset_descriptor`` 

72 for ``__dict__`` that is valid for all ``ObjectProxy`` subclasses. 

73 The metaclass installs this descriptor as ``__self_dict__`` so that 

74 the real instance dictionary of the proxy can always be accessed, 

75 even though ``ObjectProxy`` replaces ``__dict__`` with a property 

76 that delegates to the wrapped object.""" 

77 

78 pass 

79 

80 

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

82 "__dict__" 

83] 

84 

85 

86def _get_self_dict(self): 

87 return _REAL_DICT_DESCRIPTOR.__get__(self) 

88 

89 

90# Wrapping the descriptor in a read-only property ensures that 

91# ``proxy.__self_dict__ = value`` raises AttributeError rather than 

92# replacing the real instance dictionary (which would break the proxy). 

93 

94_SELF_DICT_PROPERTY = property(_get_self_dict) 

95 

96 

97class _ObjectProxyMetaType(type): 

98 # Properties on the metaclass control type-level access to __module__ 

99 # and __doc__ (e.g. ObjectProxy.__module__). Without these, the 

100 # instance-level properties copied from _ObjectProxyMethods into each 

101 # class dict would shadow the string values that type.__new__ sets, 

102 # causing type.__module__ to return a property object instead of a 

103 # string. The metaclass properties read from internal keys where the 

104 # real values are saved. 

105 

106 @property 

107 def __module__(cls): 

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

109 

110 @__module__.setter 

111 def __module__(cls, value): 

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

113 

114 @property 

115 def __doc__(cls): 

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

117 

118 @__doc__.setter 

119 def __doc__(cls, value): 

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

121 

122 def __new__(cls, name, bases, dictionary): 

123 # Copy our special properties into the class so that they 

124 # always take precedence over attributes of the same name added 

125 # during construction of a derived class. This is to save 

126 # duplicating the implementation for them in all derived classes. 

127 # 

128 # Because this overwrites the __module__ and __doc__ strings 

129 # that would normally be in the class dict with property objects, 

130 # we save the original values first and store them under internal 

131 # keys. The metaclass properties above read from these keys to 

132 # ensure type-level access (e.g. MyProxy.__module__) returns a 

133 # string rather than a property object. 

134 

135 real_module = dictionary.get("__module__") 

136 real_doc = dictionary.get("__doc__") 

137 

138 # If the subclass defines its own __dict__ property, preserve it 

139 # rather than overwriting it with the default delegating property 

140 # from _ObjectProxyMethods. When __dict__ is not explicitly 

141 # defined in the class body, it will not be present in the 

142 # dictionary at this point. 

143 

144 custom_dict = dictionary.get("__dict__") 

145 

146 dictionary.update(vars(_ObjectProxyMethods)) 

147 

148 if custom_dict is not None: 

149 dictionary["__dict__"] = custom_dict 

150 

151 dictionary.setdefault("__self_dict__", _SELF_DICT_PROPERTY) 

152 

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

154 

155 if real_module is not None: 

156 type.__setattr__(klass, "_cls_real_module", real_module) 

157 if real_doc is not None: 

158 type.__setattr__(klass, "_cls_real_doc", real_doc) 

159 

160 return klass 

161 

162 

163class ObjectProxy(_ObjectProxyDictBase, metaclass=_ObjectProxyMetaType): 

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

165 wrapped object.""" 

166 

167 __class_getitem__ = classmethod(types.GenericAlias) 

168 

169 def __init__(self, wrapped): 

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

171 

172 if wrapped is None: 

173 try: 

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

175 except AttributeError: 

176 callback = None 

177 

178 if callback is not None: 

179 # If wrapped is none and class has a __wrapped_factory__ 

180 # method, then we don't set __wrapped__ yet and instead will 

181 # defer creation of the wrapped object until it is first 

182 # needed. 

183 

184 pass 

185 

186 else: 

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

188 else: 

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

190 

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

192 

193 # Python 3.2+ has the __qualname__ attribute, but it does not 

194 # allow it to be overridden using a property and it must instead 

195 # be an actual string object instead. 

196 

197 try: 

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

199 except AttributeError: 

200 pass 

201 

202 # Python 3.10 onwards also does not allow itself to be overridden 

203 # using a property and it must instead be set explicitly. Python 

204 # 3.14 onwards uses deferred evaluation of annotations via the 

205 # __annotate__ attribute, so we copy that instead to avoid 

206 # triggering eager evaluation which can fail if names referenced 

207 # in annotations have been shadowed. 

208 

209 if sys.version_info >= (3, 14): 

210 try: 

211 object.__setattr__(self, "__annotate__", wrapped.__annotate__) 

212 except AttributeError: 

213 pass 

214 else: 

215 try: 

216 object.__setattr__(self, "__annotations__", wrapped.__annotations__) 

217 except AttributeError: 

218 pass 

219 

220 @property 

221 def __object_proxy__(self): 

222 return ObjectProxy 

223 

224 def __self_setattr__(self, name, value): 

225 object.__setattr__(self, name, value) 

226 

227 @property 

228 def __name__(self): 

229 return self.__wrapped__.__name__ 

230 

231 @__name__.setter 

232 def __name__(self, value): 

233 self.__wrapped__.__name__ = value 

234 

235 @property 

236 def __class__(self): 

237 return self.__wrapped__.__class__ 

238 

239 @__class__.setter 

240 def __class__(self, value): 

241 self.__wrapped__.__class__ = value 

242 

243 def __dir__(self): 

244 return dir(self.__wrapped__) 

245 

246 def __str__(self): 

247 return str(self.__wrapped__) 

248 

249 def __bytes__(self): 

250 return bytes(self.__wrapped__) 

251 

252 def __repr__(self): 

253 return f"<{type(self).__name__} at 0x{id(self):x} for {type(self.__wrapped__).__name__} at 0x{id(self.__wrapped__):x}>" 

254 

255 def __format__(self, format_spec): 

256 return format(self.__wrapped__, format_spec) 

257 

258 def __reversed__(self): 

259 return reversed(self.__wrapped__) 

260 

261 def __round__(self, ndigits=None): 

262 return round(self.__wrapped__, ndigits) 

263 

264 def __mro_entries__(self, bases): 

265 if not isinstance(self.__wrapped__, type) and hasattr( 

266 self.__wrapped__, "__mro_entries__" 

267 ): 

268 return self.__wrapped__.__mro_entries__(bases) 

269 return (self.__wrapped__,) 

270 

271 def __lt__(self, other): 

272 return self.__wrapped__ < other 

273 

274 def __le__(self, other): 

275 return self.__wrapped__ <= other 

276 

277 def __eq__(self, other): 

278 return self.__wrapped__ == other 

279 

280 def __ne__(self, other): 

281 return self.__wrapped__ != other 

282 

283 def __gt__(self, other): 

284 return self.__wrapped__ > other 

285 

286 def __ge__(self, other): 

287 return self.__wrapped__ >= other 

288 

289 def __hash__(self): 

290 return hash(self.__wrapped__) 

291 

292 def __bool__(self): 

293 return bool(self.__wrapped__) 

294 

295 def __setattr__(self, name, value): 

296 if name.startswith("_self_"): 

297 object.__setattr__(self, name, value) 

298 

299 elif name == "__wrapped__": 

300 object.__setattr__(self, name, value) 

301 

302 try: 

303 object.__delattr__(self, "__qualname__") 

304 except AttributeError: 

305 pass 

306 try: 

307 object.__setattr__(self, "__qualname__", value.__qualname__) 

308 except AttributeError: 

309 pass 

310 if sys.version_info >= (3, 14): 

311 try: 

312 object.__delattr__(self, "__annotate__") 

313 except AttributeError: 

314 pass 

315 try: 

316 object.__setattr__(self, "__annotate__", value.__annotate__) 

317 except AttributeError: 

318 pass 

319 else: 

320 try: 

321 object.__delattr__(self, "__annotations__") 

322 except AttributeError: 

323 pass 

324 try: 

325 object.__setattr__(self, "__annotations__", value.__annotations__) 

326 except AttributeError: 

327 pass 

328 

329 __wrapped_setattr_fixups__ = getattr( 

330 self, "__wrapped_setattr_fixups__", None 

331 ) 

332 

333 if __wrapped_setattr_fixups__ is not None: 

334 __wrapped_setattr_fixups__() 

335 

336 elif name == "__qualname__": 

337 setattr(self.__wrapped__, name, value) 

338 object.__setattr__(self, name, value) 

339 

340 elif name == "__annotations__": 

341 setattr(self.__wrapped__, name, value) 

342 object.__setattr__(self, name, value) 

343 

344 elif name == "__annotate__": 

345 setattr(self.__wrapped__, name, value) 

346 object.__setattr__(self, name, value) 

347 

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

349 object.__setattr__(self, name, value) 

350 

351 else: 

352 setattr(self.__wrapped__, name, value) 

353 

354 def __getattr__(self, name): 

355 # If we need to lookup `__wrapped__` then the `__init__()` method 

356 # cannot have been called, or this is a lazy object proxy which is 

357 # deferring creation of the wrapped object until it is first needed. 

358 

359 if name == "__wrapped__": 

360 # Note that we use existance of `__wrapped_factory__` to gate whether 

361 # we can attempt to initialize the wrapped object lazily, but it is 

362 # `__wrapped_get__` that we actually call to do the initialization. 

363 # This is so that we can handle multithreading correctly by having 

364 # `__wrapped_get__` use a lock to protect against multiple threads 

365 # trying to initialize the wrapped object at the same time. 

366 

367 try: 

368 object.__getattribute__(self, "__wrapped_factory__") 

369 except AttributeError: 

370 pass 

371 else: 

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

373 

374 # If __init__ was called but __wrapped__ is not set, the wrapper 

375 # is in an inconsistent state. Raise WrapperNotInitializedError 

376 # (a ValueError, not AttributeError) so it is not silently 

377 # swallowed by hasattr/getattr patterns. 

378 

379 try: 

380 object.__getattribute__(self, "__init_called__") 

381 except AttributeError: 

382 raise AttributeError( 

383 f"'{type(self).__name__}' object has no attribute " f"'__wrapped__'" 

384 ) 

385 

386 raise WrapperNotInitializedError( 

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

388 ) 

389 

390 return getattr(self.__wrapped__, name) 

391 

392 def __delattr__(self, name): 

393 if name.startswith("_self_"): 

394 object.__delattr__(self, name) 

395 

396 elif name == "__wrapped__": 

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

398 

399 elif name == "__qualname__": 

400 object.__delattr__(self, name) 

401 delattr(self.__wrapped__, name) 

402 

403 elif name == "__annotations__": 

404 try: 

405 object.__delattr__(self, name) 

406 except AttributeError: 

407 pass 

408 delattr(self.__wrapped__, name) 

409 

410 elif name == "__annotate__": 

411 try: 

412 object.__delattr__(self, name) 

413 except AttributeError: 

414 pass 

415 delattr(self.__wrapped__, name) 

416 

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

418 object.__delattr__(self, name) 

419 

420 else: 

421 delattr(self.__wrapped__, name) 

422 

423 def __add__(self, other): 

424 return self.__wrapped__ + other 

425 

426 def __sub__(self, other): 

427 return self.__wrapped__ - other 

428 

429 def __mul__(self, other): 

430 return self.__wrapped__ * other 

431 

432 def __truediv__(self, other): 

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

434 

435 def __floordiv__(self, other): 

436 return self.__wrapped__ // other 

437 

438 def __mod__(self, other): 

439 return self.__wrapped__ % other 

440 

441 def __divmod__(self, other): 

442 return divmod(self.__wrapped__, other) 

443 

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

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

446 

447 def __lshift__(self, other): 

448 return self.__wrapped__ << other 

449 

450 def __rshift__(self, other): 

451 return self.__wrapped__ >> other 

452 

453 def __and__(self, other): 

454 return self.__wrapped__ & other 

455 

456 def __xor__(self, other): 

457 return self.__wrapped__ ^ other 

458 

459 def __or__(self, other): 

460 return self.__wrapped__ | other 

461 

462 def __radd__(self, other): 

463 return other + self.__wrapped__ 

464 

465 def __rsub__(self, other): 

466 return other - self.__wrapped__ 

467 

468 def __rmul__(self, other): 

469 return other * self.__wrapped__ 

470 

471 def __rtruediv__(self, other): 

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

473 

474 def __rfloordiv__(self, other): 

475 return other // self.__wrapped__ 

476 

477 def __rmod__(self, other): 

478 return other % self.__wrapped__ 

479 

480 def __rdivmod__(self, other): 

481 return divmod(other, self.__wrapped__) 

482 

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

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

485 

486 def __rlshift__(self, other): 

487 return other << self.__wrapped__ 

488 

489 def __rrshift__(self, other): 

490 return other >> self.__wrapped__ 

491 

492 def __rand__(self, other): 

493 return other & self.__wrapped__ 

494 

495 def __rxor__(self, other): 

496 return other ^ self.__wrapped__ 

497 

498 def __ror__(self, other): 

499 return other | self.__wrapped__ 

500 

501 def __iadd__(self, other): 

502 if hasattr(self.__wrapped__, "__iadd__"): 

503 self.__wrapped__ += other 

504 return self 

505 else: 

506 return self.__object_proxy__(self.__wrapped__ + other) 

507 

508 def __isub__(self, other): 

509 if hasattr(self.__wrapped__, "__isub__"): 

510 self.__wrapped__ -= other 

511 return self 

512 else: 

513 return self.__object_proxy__(self.__wrapped__ - other) 

514 

515 def __imul__(self, other): 

516 if hasattr(self.__wrapped__, "__imul__"): 

517 self.__wrapped__ *= other 

518 return self 

519 else: 

520 return self.__object_proxy__(self.__wrapped__ * other) 

521 

522 def __itruediv__(self, other): 

523 if hasattr(self.__wrapped__, "__itruediv__"): 

524 self.__wrapped__ /= other 

525 return self 

526 else: 

527 return self.__object_proxy__(self.__wrapped__ / other) 

528 

529 def __ifloordiv__(self, other): 

530 if hasattr(self.__wrapped__, "__ifloordiv__"): 

531 self.__wrapped__ //= other 

532 return self 

533 else: 

534 return self.__object_proxy__(self.__wrapped__ // other) 

535 

536 def __imod__(self, other): 

537 if hasattr(self.__wrapped__, "__imod__"): 

538 self.__wrapped__ %= other 

539 return self 

540 else: 

541 return self.__object_proxy__(self.__wrapped__ % other) 

542 

543 def __ipow__(self, other): # type: ignore[misc] 

544 if hasattr(self.__wrapped__, "__ipow__"): 

545 self.__wrapped__ **= other 

546 return self 

547 else: 

548 return self.__object_proxy__(self.__wrapped__**other) 

549 

550 def __ilshift__(self, other): 

551 if hasattr(self.__wrapped__, "__ilshift__"): 

552 self.__wrapped__ <<= other 

553 return self 

554 else: 

555 return self.__object_proxy__(self.__wrapped__ << other) 

556 

557 def __irshift__(self, other): 

558 if hasattr(self.__wrapped__, "__irshift__"): 

559 self.__wrapped__ >>= other 

560 return self 

561 else: 

562 return self.__object_proxy__(self.__wrapped__ >> other) 

563 

564 def __iand__(self, other): 

565 if hasattr(self.__wrapped__, "__iand__"): 

566 self.__wrapped__ &= other 

567 return self 

568 else: 

569 return self.__object_proxy__(self.__wrapped__ & other) 

570 

571 def __ixor__(self, other): 

572 if hasattr(self.__wrapped__, "__ixor__"): 

573 self.__wrapped__ ^= other 

574 return self 

575 else: 

576 return self.__object_proxy__(self.__wrapped__ ^ other) 

577 

578 def __ior__(self, other): 

579 if hasattr(self.__wrapped__, "__ior__"): 

580 self.__wrapped__ |= other 

581 return self 

582 else: 

583 return self.__object_proxy__(self.__wrapped__ | other) 

584 

585 def __neg__(self): 

586 return -self.__wrapped__ 

587 

588 def __pos__(self): 

589 return +self.__wrapped__ 

590 

591 def __abs__(self): 

592 return abs(self.__wrapped__) 

593 

594 def __invert__(self): 

595 return ~self.__wrapped__ 

596 

597 def __int__(self): 

598 return int(self.__wrapped__) 

599 

600 def __float__(self): 

601 return float(self.__wrapped__) 

602 

603 def __complex__(self): 

604 return complex(self.__wrapped__) 

605 

606 def __index__(self): 

607 return operator.index(self.__wrapped__) 

608 

609 def __matmul__(self, other): 

610 return self.__wrapped__ @ other 

611 

612 def __rmatmul__(self, other): 

613 return other @ self.__wrapped__ 

614 

615 def __imatmul__(self, other): 

616 if hasattr(self.__wrapped__, "__imatmul__"): 

617 self.__wrapped__ @= other 

618 return self 

619 else: 

620 return self.__object_proxy__(self.__wrapped__ @ other) 

621 

622 def __len__(self): 

623 return len(self.__wrapped__) 

624 

625 def __contains__(self, value): 

626 return value in self.__wrapped__ 

627 

628 def __getitem__(self, key): 

629 return self.__wrapped__[key] 

630 

631 def __setitem__(self, key, value): 

632 self.__wrapped__[key] = value 

633 

634 def __delitem__(self, key): 

635 del self.__wrapped__[key] 

636 

637 def __enter__(self): 

638 return self.__wrapped__.__enter__() 

639 

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

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

642 

643 def __aenter__(self): 

644 return self.__wrapped__.__aenter__() 

645 

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

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

648 

649 def __copy__(self): 

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

651 

652 def __deepcopy__(self, memo): 

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

654 

655 def __reduce__(self): 

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

657 

658 def __instancecheck__(self, instance): 

659 return isinstance(instance, self.__wrapped__) 

660 

661 def __subclasscheck__(self, subclass): 

662 if hasattr(subclass, "__wrapped__"): 

663 return issubclass(subclass.__wrapped__, self.__wrapped__) 

664 else: 

665 return issubclass(subclass, self.__wrapped__) 

666 

667 

668class CallableObjectProxy(ObjectProxy): 

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

670 

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

672 def _unpack_self(self, *args): 

673 return self, args 

674 

675 self, args = _unpack_self(*args) 

676 

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

678 

679 

680class PartialCallableObjectProxy(ObjectProxy): 

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

682 and keywords. 

683 """ 

684 

685 def __init__(*args, **kwargs): 

686 """Create a callable object proxy with partial application of the given 

687 arguments and keywords. This behaves the same as `functools.partial`, but 

688 implemented using the `ObjectProxy` class to provide better support for 

689 introspection. 

690 """ 

691 

692 def _unpack_self(self, *args): 

693 return self, args 

694 

695 self, args = _unpack_self(*args) 

696 

697 if len(args) < 1: 

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

699 

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

701 

702 if not callable(wrapped): 

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

704 

705 # Explicit class in super() is used because the proxy overrides 

706 # __class__ and MRO-related methods to delegate to the wrapped 

707 # object, which can interfere with bare super(). 

708 super(PartialCallableObjectProxy, self).__init__(wrapped) 

709 

710 self._self_args = args 

711 self._self_kwargs = kwargs 

712 

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

714 def _unpack_self(self, *args): 

715 return self, args 

716 

717 self, args = _unpack_self(*args) 

718 

719 _args = self._self_args + args 

720 

721 _kwargs = dict(self._self_kwargs) 

722 _kwargs.update(kwargs) 

723 

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

725 

726 

727class _FunctionWrapperBase(ObjectProxy): 

728 

729 def __init__( 

730 self, 

731 wrapped, 

732 instance, 

733 wrapper, 

734 enabled=None, 

735 binding="callable", 

736 parent=None, 

737 owner=None, 

738 ): 

739 

740 # Explicit class in super() is used because the proxy overrides 

741 # __class__ and MRO-related methods to delegate to the wrapped 

742 # object, which can interfere with bare super(). 

743 super(_FunctionWrapperBase, self).__init__(wrapped) 

744 

745 object.__setattr__(self, "_self_instance", instance) 

746 object.__setattr__(self, "_self_wrapper", wrapper) 

747 object.__setattr__(self, "_self_enabled", enabled) 

748 object.__setattr__(self, "_self_binding", binding) 

749 object.__setattr__(self, "_self_parent", parent) 

750 object.__setattr__(self, "_self_owner", owner) 

751 

752 def __get__(self, instance, owner): 

753 # This method handles both unbound and bound derived wrapper classes. 

754 # It is kept in the base class as the amount of common code makes it 

755 # impractical to split into the derived classes. 

756 # 

757 # The distinguishing attribute which determines whether we are being 

758 # called in an unbound or bound wrapper is the parent attribute. If 

759 # binding has never occurred, then the parent will be None. 

760 # 

761 # First therefore, is if we are called in an unbound wrapper. In this 

762 # case we perform the binding. 

763 # 

764 # We have two special cases to worry about here. These are where we are 

765 # decorating a class or builtin function as neither provide a __get__() 

766 # method to call. In this case we simply return self. 

767 # 

768 # Note that we otherwise still do binding even if instance is None and 

769 # accessing an unbound instance method from a class. This is because we 

770 # need to be able to later detect that specific case as we will need to 

771 # extract the instance from the first argument of those passed in. 

772 

773 if self._self_parent is None: 

774 # Technically can probably just check for existence of __get__ on 

775 # the wrapped object, but this is more explicit. 

776 

777 if self._self_binding == "builtin": 

778 return self 

779 

780 if self._self_binding == "class": 

781 return self 

782 

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

784 

785 if binder is None: 

786 return self 

787 

788 descriptor = binder(instance, owner) 

789 

790 return self.__bound_function_wrapper__( 

791 descriptor, 

792 instance, 

793 self._self_wrapper, 

794 self._self_enabled, 

795 self._self_binding, 

796 self, 

797 owner, 

798 ) 

799 

800 # Now we have the case of binding occurring a second time on what was 

801 # already a bound function. In this case we would usually return 

802 # ourselves again. This mirrors what Python does. 

803 # 

804 # The special case this time is where we were originally bound with an 

805 # instance of None and we were likely an instance method. In that case 

806 # we rebind against the original wrapped function from the parent again. 

807 

808 if self._self_instance is None and self._self_binding in ( 

809 "function", 

810 "instancemethod", 

811 "callable", 

812 ): 

813 descriptor = self._self_parent.__wrapped__.__get__(instance, owner) 

814 

815 return self._self_parent.__bound_function_wrapper__( 

816 descriptor, 

817 instance, 

818 self._self_wrapper, 

819 self._self_enabled, 

820 self._self_binding, 

821 self._self_parent, 

822 owner, 

823 ) 

824 

825 return self 

826 

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

828 def _unpack_self(self, *args): 

829 return self, args 

830 

831 self, args = _unpack_self(*args) 

832 

833 # If enabled has been specified, then evaluate it at this point 

834 # and if the wrapper is not to be executed, then simply return 

835 # the bound function rather than a bound wrapper for the bound 

836 # function. When evaluating enabled, if it is callable we call 

837 # it, otherwise we evaluate it as a boolean. 

838 

839 if self._self_enabled is not None: 

840 if callable(self._self_enabled): 

841 if not self._self_enabled(): 

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

843 elif not self._self_enabled: 

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

845 

846 # This can occur where initial function wrapper was applied to 

847 # a function that was already bound to an instance. In that case 

848 # we want to extract the instance from the function and use it. 

849 

850 if self._self_binding in ( 

851 "function", 

852 "instancemethod", 

853 "classmethod", 

854 "callable", 

855 ): 

856 if self._self_instance is None: 

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

858 if instance is not None: 

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

860 

861 # This is generally invoked when the wrapped function is being 

862 # called as a normal function and is not bound to a class as an 

863 # instance method. This is also invoked in the case where the 

864 # wrapped function was a method, but this wrapper was in turn 

865 # wrapped using the staticmethod decorator. 

866 

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

868 

869 def __set_name__(self, owner, name): 

870 # This is a special method use to supply information to 

871 # descriptors about what the name of variable in a class 

872 # definition is. Not wanting to add this to ObjectProxy as not 

873 # sure of broader implications of doing that. Thus restrict to 

874 # FunctionWrapper used by decorators. 

875 

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

877 self.__wrapped__.__set_name__(owner, name) 

878 

879 

880_FUNCTION_WRAPPER_SLOTS = frozenset( 

881 ( 

882 "_self_instance", 

883 "_self_wrapper", 

884 "_self_enabled", 

885 "_self_binding", 

886 "_self_parent", 

887 "_self_owner", 

888 ) 

889) 

890 

891 

892class BoundFunctionWrapper(_FunctionWrapperBase): 

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

894 

895 def __setattr__(self, name, value): 

896 if name.startswith("_self_") and name not in _FUNCTION_WRAPPER_SLOTS: 

897 if self._self_parent is not None: 

898 object.__setattr__(self._self_parent, name, value) 

899 return 

900 super().__setattr__(name, value) 

901 

902 def __getattr__(self, name): 

903 if self._self_parent is not None: 

904 try: 

905 return getattr(self._self_parent, name) 

906 except AttributeError: 

907 pass 

908 return super().__getattr__(name) 

909 

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

911 def _unpack_self(self, *args): 

912 return self, args 

913 

914 self, args = _unpack_self(*args) 

915 

916 # If enabled has been specified, then evaluate it at this point and if 

917 # the wrapper is not to be executed, then simply return the bound 

918 # function rather than a bound wrapper for the bound function. When 

919 # evaluating enabled, if it is callable we call it, otherwise we 

920 # evaluate it as a boolean. 

921 

922 if self._self_enabled is not None: 

923 if callable(self._self_enabled): 

924 if not self._self_enabled(): 

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

926 elif not self._self_enabled: 

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

928 

929 # We need to do things different depending on whether we are likely 

930 # wrapping an instance method vs a static method or class method. 

931 

932 if self._self_binding == "function": 

933 if self._self_instance is None and args: 

934 instance, newargs = args[0], args[1:] 

935 if isinstance(instance, self._self_owner): 

936 wrapped = PartialCallableObjectProxy(self.__wrapped__, instance) 

937 return self._self_wrapper(wrapped, instance, newargs, kwargs) 

938 

939 return self._self_wrapper( 

940 self.__wrapped__, self._self_instance, args, kwargs 

941 ) 

942 

943 elif self._self_binding == "callable": 

944 if self._self_instance is None and args: 

945 # This situation can occur where someone is calling the 

946 # instancemethod via the class type and passing the instance as 

947 # the first argument. We need to shift the args before making 

948 # the call to the wrapper and effectively bind the instance to 

949 # the wrapped function using a partial so the wrapper doesn't 

950 # see anything as being different. 

951 

952 instance, newargs = args[0], args[1:] 

953 if isinstance(instance, self._self_owner): 

954 wrapped = PartialCallableObjectProxy(self.__wrapped__, instance) 

955 return self._self_wrapper(wrapped, instance, newargs, kwargs) 

956 

957 return self._self_wrapper( 

958 self.__wrapped__, self._self_instance, args, kwargs 

959 ) 

960 

961 else: 

962 # As in this case we would be dealing with a classmethod or 

963 # staticmethod, then _self_instance will only tell us whether 

964 # when calling the classmethod or staticmethod they did it via an 

965 # instance of the class it is bound to and not the case where 

966 # done by the class type itself. We thus ignore _self_instance 

967 # and use the __self__ attribute of the bound function instead. 

968 # For a classmethod, this means instance will be the class type 

969 # and for a staticmethod it will be None. This is probably the 

970 # more useful thing we can pass through even though we loose 

971 # knowledge of whether they were called on the instance vs the 

972 # class type, as it reflects what they have available in the 

973 # decoratored function. 

974 

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

976 

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

978 

979 

980class FunctionWrapper(_FunctionWrapperBase): 

981 """ 

982 A wrapper for callable objects that can be used to apply decorators to 

983 functions, methods, classmethods, and staticmethods, or any other callable. 

984 It handles binding and unbinding of methods, and allows for the wrapper to 

985 be enabled or disabled. 

986 """ 

987 

988 __bound_function_wrapper__ = BoundFunctionWrapper 

989 

990 def __init__(self, wrapped, wrapper, enabled=None): 

991 """ 

992 Initialize the `FunctionWrapper` with the `wrapped` callable, the 

993 `wrapper` function, and an optional `enabled` argument. The `enabled` 

994 argument can be a boolean or a callable that returns a boolean. When a 

995 callable is provided, it will be called each time the wrapper is 

996 invoked to determine if the wrapper function should be executed or 

997 whether the wrapped function should be called directly. If `enabled` 

998 is not provided, the wrapper is enabled by default. 

999 """ 

1000 

1001 # What it is we are wrapping here could be anything. We need to 

1002 # try and detect specific cases though. In particular, we need 

1003 # to detect when we are given something that is a method of a 

1004 # class. Further, we need to know when it is likely an instance 

1005 # method, as opposed to a class or static method. This can 

1006 # become problematic though as there isn't strictly a fool proof 

1007 # method of knowing. 

1008 # 

1009 # The situations we could encounter when wrapping a method are: 

1010 # 

1011 # 1. The wrapper is being applied as part of a decorator which 

1012 # is a part of the class definition. In this case what we are 

1013 # given is the raw unbound function, classmethod or staticmethod 

1014 # wrapper objects. 

1015 # 

1016 # The problem here is that we will not know we are being applied 

1017 # in the context of the class being set up. This becomes 

1018 # important later for the case of an instance method, because in 

1019 # that case we just see it as a raw function and can't 

1020 # distinguish it from wrapping a normal function outside of 

1021 # a class context. 

1022 # 

1023 # 2. The wrapper is being applied when performing monkey 

1024 # patching of the class type afterwards and the method to be 

1025 # wrapped was retrieved direct from the __dict__ of the class 

1026 # type. This is effectively the same as (1) above. 

1027 # 

1028 # 3. The wrapper is being applied when performing monkey 

1029 # patching of the class type afterwards and the method to be 

1030 # wrapped was retrieved from the class type. In this case 

1031 # binding will have been performed where the instance against 

1032 # which the method is bound will be None at that point. 

1033 # 

1034 # This case is a problem because we can no longer tell if the 

1035 # method was a static method, plus if using Python3, we cannot 

1036 # tell if it was an instance method as the concept of an 

1037 # unnbound method no longer exists. 

1038 # 

1039 # 4. The wrapper is being applied when performing monkey 

1040 # patching of an instance of a class. In this case binding will 

1041 # have been performed where the instance was not None. 

1042 # 

1043 # This case is a problem because we can no longer tell if the 

1044 # method was a static method. 

1045 # 

1046 # Overall, the best we can do is look at the original type of the 

1047 # object which was wrapped prior to any binding being done and 

1048 # see if it is an instance of classmethod or staticmethod. In 

1049 # the case where other decorators are between us and them, if 

1050 # they do not propagate the __class__ attribute so that the 

1051 # isinstance() checks works, then likely this will do the wrong 

1052 # thing where classmethod and staticmethod are used. 

1053 # 

1054 # Since it is likely to be very rare that anyone even puts 

1055 # decorators around classmethod and staticmethod, likelihood of 

1056 # that being an issue is very small, so we accept it and suggest 

1057 # that those other decorators be fixed. It is also only an issue 

1058 # if a decorator wants to actually do things with the arguments. 

1059 # 

1060 # As to not being able to identify static methods properly, we 

1061 # just hope that that isn't something people are going to want 

1062 # to wrap, or if they do suggest they do it the correct way by 

1063 # ensuring that it is decorated in the class definition itself, 

1064 # or patch it in the __dict__ of the class type. 

1065 # 

1066 # So to get the best outcome we can, whenever we aren't sure what 

1067 # it is, we label it as a 'callable'. If it was already bound and 

1068 # that is rebound later, we assume that it will be an instance 

1069 # method and try and cope with the possibility that the 'self' 

1070 # argument it being passed as an explicit argument and shuffle 

1071 # the arguments around to extract 'self' for use as the instance. 

1072 

1073 binding = None 

1074 

1075 if isinstance(wrapped, _FunctionWrapperBase): 

1076 binding = wrapped._self_binding 

1077 

1078 if not binding: 

1079 if inspect.isbuiltin(wrapped): 

1080 binding = "builtin" 

1081 

1082 elif inspect.isfunction(wrapped): 

1083 binding = "function" 

1084 

1085 elif inspect.isclass(wrapped): 

1086 binding = "class" 

1087 

1088 elif isinstance(wrapped, classmethod): 

1089 binding = "classmethod" 

1090 

1091 elif isinstance(wrapped, staticmethod): 

1092 binding = "staticmethod" 

1093 

1094 elif hasattr(wrapped, "__self__"): 

1095 if inspect.isclass(wrapped.__self__): 

1096 binding = "classmethod" 

1097 elif inspect.ismethod(wrapped): 

1098 binding = "instancemethod" 

1099 else: 

1100 binding = "callable" 

1101 

1102 else: 

1103 binding = "callable" 

1104 

1105 # Explicit class in super() is used because the proxy overrides 

1106 # __class__ and MRO-related methods to delegate to the wrapped 

1107 # object, which can interfere with bare super(). 

1108 super(FunctionWrapper, self).__init__(wrapped, None, wrapper, enabled, binding)