Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/wrapt/wrappers.py: 33%

508 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:35 +0000

1import os 

2import sys 

3import functools 

4import operator 

5import weakref 

6import inspect 

7 

8PY2 = sys.version_info[0] == 2 

9 

10if PY2: 

11 string_types = basestring, 

12else: 

13 string_types = str, 

14 

15def with_metaclass(meta, *bases): 

16 """Create a base class with a metaclass.""" 

17 return meta("NewBase", bases, {}) 

18 

19class _ObjectProxyMethods(object): 

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 @property 

31 def __module__(self): 

32 return self.__wrapped__.__module__ 

33 

34 @__module__.setter 

35 def __module__(self, value): 

36 self.__wrapped__.__module__ = value 

37 

38 @property 

39 def __doc__(self): 

40 return self.__wrapped__.__doc__ 

41 

42 @__doc__.setter 

43 def __doc__(self, value): 

44 self.__wrapped__.__doc__ = value 

45 

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

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

48 

49 @property 

50 def __dict__(self): 

51 return self.__wrapped__.__dict__ 

52 

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

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

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

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

57 

58 @property 

59 def __weakref__(self): 

60 return self.__wrapped__.__weakref__ 

61 

62class _ObjectProxyMetaType(type): 

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

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

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

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

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

68 

69 dictionary.update(vars(_ObjectProxyMethods)) 

70 

71 return type.__new__(cls, name, bases, dictionary) 

72 

73class ObjectProxy(with_metaclass(_ObjectProxyMetaType)): 

74 

75 __slots__ = '__wrapped__' 

76 

77 def __init__(self, wrapped): 

78 object.__setattr__(self, '__wrapped__', wrapped) 

79 

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

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

82 # be an actual string object instead. 

83 

84 try: 

85 object.__setattr__(self, '__qualname__', wrapped.__qualname__) 

86 except AttributeError: 

87 pass 

88 

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

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

91 

92 try: 

93 object.__setattr__(self, '__annotations__', wrapped.__annotations__) 

94 except AttributeError: 

95 pass 

96 

97 @property 

98 def __name__(self): 

99 return self.__wrapped__.__name__ 

100 

101 @__name__.setter 

102 def __name__(self, value): 

103 self.__wrapped__.__name__ = value 

104 

105 @property 

106 def __class__(self): 

107 return self.__wrapped__.__class__ 

108 

109 @__class__.setter 

110 def __class__(self, value): 

111 self.__wrapped__.__class__ = value 

112 

113 def __dir__(self): 

114 return dir(self.__wrapped__) 

115 

116 def __str__(self): 

117 return str(self.__wrapped__) 

118 

119 if not PY2: 

120 def __bytes__(self): 

121 return bytes(self.__wrapped__) 

122 

123 def __repr__(self): 

124 return '<{} at 0x{:x} for {} at 0x{:x}>'.format( 

125 type(self).__name__, id(self), 

126 type(self.__wrapped__).__name__, 

127 id(self.__wrapped__)) 

128 

129 def __reversed__(self): 

130 return reversed(self.__wrapped__) 

131 

132 if not PY2: 

133 def __round__(self): 

134 return round(self.__wrapped__) 

135 

136 if sys.hexversion >= 0x03070000: 

137 def __mro_entries__(self, bases): 

138 return (self.__wrapped__,) 

139 

140 def __lt__(self, other): 

141 return self.__wrapped__ < other 

142 

143 def __le__(self, other): 

144 return self.__wrapped__ <= other 

145 

146 def __eq__(self, other): 

147 return self.__wrapped__ == other 

148 

149 def __ne__(self, other): 

150 return self.__wrapped__ != other 

151 

152 def __gt__(self, other): 

153 return self.__wrapped__ > other 

154 

155 def __ge__(self, other): 

156 return self.__wrapped__ >= other 

157 

158 def __hash__(self): 

159 return hash(self.__wrapped__) 

160 

161 def __nonzero__(self): 

162 return bool(self.__wrapped__) 

163 

164 def __bool__(self): 

165 return bool(self.__wrapped__) 

166 

167 def __setattr__(self, name, value): 

168 if name.startswith('_self_'): 

169 object.__setattr__(self, name, value) 

170 

171 elif name == '__wrapped__': 

172 object.__setattr__(self, name, value) 

173 try: 

174 object.__delattr__(self, '__qualname__') 

175 except AttributeError: 

176 pass 

177 try: 

178 object.__setattr__(self, '__qualname__', value.__qualname__) 

179 except AttributeError: 

180 pass 

181 try: 

182 object.__delattr__(self, '__annotations__') 

183 except AttributeError: 

184 pass 

185 try: 

186 object.__setattr__(self, '__annotations__', value.__annotations__) 

187 except AttributeError: 

188 pass 

189 

190 elif name == '__qualname__': 

191 setattr(self.__wrapped__, name, value) 

192 object.__setattr__(self, name, value) 

193 

194 elif name == '__annotations__': 

195 setattr(self.__wrapped__, name, value) 

196 object.__setattr__(self, name, value) 

197 

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

199 object.__setattr__(self, name, value) 

200 

201 else: 

202 setattr(self.__wrapped__, name, value) 

203 

204 def __getattr__(self, name): 

205 # If we are being to lookup '__wrapped__' then the 

206 # '__init__()' method cannot have been called. 

207 

208 if name == '__wrapped__': 

209 raise ValueError('wrapper has not been initialised') 

210 

211 return getattr(self.__wrapped__, name) 

212 

213 def __delattr__(self, name): 

214 if name.startswith('_self_'): 

215 object.__delattr__(self, name) 

216 

217 elif name == '__wrapped__': 

218 raise TypeError('__wrapped__ must be an object') 

219 

220 elif name == '__qualname__': 

221 object.__delattr__(self, name) 

222 delattr(self.__wrapped__, name) 

223 

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

225 object.__delattr__(self, name) 

226 

227 else: 

228 delattr(self.__wrapped__, name) 

229 

230 def __add__(self, other): 

231 return self.__wrapped__ + other 

232 

233 def __sub__(self, other): 

234 return self.__wrapped__ - other 

235 

236 def __mul__(self, other): 

237 return self.__wrapped__ * other 

238 

239 def __div__(self, other): 

240 return operator.div(self.__wrapped__, other) 

241 

242 def __truediv__(self, other): 

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

244 

245 def __floordiv__(self, other): 

246 return self.__wrapped__ // other 

247 

248 def __mod__(self, other): 

249 return self.__wrapped__ % other 

250 

251 def __divmod__(self, other): 

252 return divmod(self.__wrapped__, other) 

253 

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

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

256 

257 def __lshift__(self, other): 

258 return self.__wrapped__ << other 

259 

260 def __rshift__(self, other): 

261 return self.__wrapped__ >> other 

262 

263 def __and__(self, other): 

264 return self.__wrapped__ & other 

265 

266 def __xor__(self, other): 

267 return self.__wrapped__ ^ other 

268 

269 def __or__(self, other): 

270 return self.__wrapped__ | other 

271 

272 def __radd__(self, other): 

273 return other + self.__wrapped__ 

274 

275 def __rsub__(self, other): 

276 return other - self.__wrapped__ 

277 

278 def __rmul__(self, other): 

279 return other * self.__wrapped__ 

280 

281 def __rdiv__(self, other): 

282 return operator.div(other, self.__wrapped__) 

283 

284 def __rtruediv__(self, other): 

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

286 

287 def __rfloordiv__(self, other): 

288 return other // self.__wrapped__ 

289 

290 def __rmod__(self, other): 

291 return other % self.__wrapped__ 

292 

293 def __rdivmod__(self, other): 

294 return divmod(other, self.__wrapped__) 

295 

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

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

298 

299 def __rlshift__(self, other): 

300 return other << self.__wrapped__ 

301 

302 def __rrshift__(self, other): 

303 return other >> self.__wrapped__ 

304 

305 def __rand__(self, other): 

306 return other & self.__wrapped__ 

307 

308 def __rxor__(self, other): 

309 return other ^ self.__wrapped__ 

310 

311 def __ror__(self, other): 

312 return other | self.__wrapped__ 

313 

314 def __iadd__(self, other): 

315 self.__wrapped__ += other 

316 return self 

317 

318 def __isub__(self, other): 

319 self.__wrapped__ -= other 

320 return self 

321 

322 def __imul__(self, other): 

323 self.__wrapped__ *= other 

324 return self 

325 

326 def __idiv__(self, other): 

327 self.__wrapped__ = operator.idiv(self.__wrapped__, other) 

328 return self 

329 

330 def __itruediv__(self, other): 

331 self.__wrapped__ = operator.itruediv(self.__wrapped__, other) 

332 return self 

333 

334 def __ifloordiv__(self, other): 

335 self.__wrapped__ //= other 

336 return self 

337 

338 def __imod__(self, other): 

339 self.__wrapped__ %= other 

340 return self 

341 

342 def __ipow__(self, other): 

343 self.__wrapped__ **= other 

344 return self 

345 

346 def __ilshift__(self, other): 

347 self.__wrapped__ <<= other 

348 return self 

349 

350 def __irshift__(self, other): 

351 self.__wrapped__ >>= other 

352 return self 

353 

354 def __iand__(self, other): 

355 self.__wrapped__ &= other 

356 return self 

357 

358 def __ixor__(self, other): 

359 self.__wrapped__ ^= other 

360 return self 

361 

362 def __ior__(self, other): 

363 self.__wrapped__ |= other 

364 return self 

365 

366 def __neg__(self): 

367 return -self.__wrapped__ 

368 

369 def __pos__(self): 

370 return +self.__wrapped__ 

371 

372 def __abs__(self): 

373 return abs(self.__wrapped__) 

374 

375 def __invert__(self): 

376 return ~self.__wrapped__ 

377 

378 def __int__(self): 

379 return int(self.__wrapped__) 

380 

381 def __long__(self): 

382 return long(self.__wrapped__) 

383 

384 def __float__(self): 

385 return float(self.__wrapped__) 

386 

387 def __complex__(self): 

388 return complex(self.__wrapped__) 

389 

390 def __oct__(self): 

391 return oct(self.__wrapped__) 

392 

393 def __hex__(self): 

394 return hex(self.__wrapped__) 

395 

396 def __index__(self): 

397 return operator.index(self.__wrapped__) 

398 

399 def __len__(self): 

400 return len(self.__wrapped__) 

401 

402 def __contains__(self, value): 

403 return value in self.__wrapped__ 

404 

405 def __getitem__(self, key): 

406 return self.__wrapped__[key] 

407 

408 def __setitem__(self, key, value): 

409 self.__wrapped__[key] = value 

410 

411 def __delitem__(self, key): 

412 del self.__wrapped__[key] 

413 

414 def __getslice__(self, i, j): 

415 return self.__wrapped__[i:j] 

416 

417 def __setslice__(self, i, j, value): 

418 self.__wrapped__[i:j] = value 

419 

420 def __delslice__(self, i, j): 

421 del self.__wrapped__[i:j] 

422 

423 def __enter__(self): 

424 return self.__wrapped__.__enter__() 

425 

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

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

428 

429 def __iter__(self): 

430 return iter(self.__wrapped__) 

431 

432 def __copy__(self): 

433 raise NotImplementedError('object proxy must define __copy__()') 

434 

435 def __deepcopy__(self, memo): 

436 raise NotImplementedError('object proxy must define __deepcopy__()') 

437 

438 def __reduce__(self): 

439 raise NotImplementedError( 

440 'object proxy must define __reduce_ex__()') 

441 

442 def __reduce_ex__(self, protocol): 

443 raise NotImplementedError( 

444 'object proxy must define __reduce_ex__()') 

445 

446class CallableObjectProxy(ObjectProxy): 

447 

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

449 def _unpack_self(self, *args): 

450 return self, args 

451 

452 self, args = _unpack_self(*args) 

453 

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

455 

456class PartialCallableObjectProxy(ObjectProxy): 

457 

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

459 def _unpack_self(self, *args): 

460 return self, args 

461 

462 self, args = _unpack_self(*args) 

463 

464 if len(args) < 1: 

465 raise TypeError('partial type takes at least one argument') 

466 

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

468 

469 if not callable(wrapped): 

470 raise TypeError('the first argument must be callable') 

471 

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

473 

474 self._self_args = args 

475 self._self_kwargs = kwargs 

476 

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

478 def _unpack_self(self, *args): 

479 return self, args 

480 

481 self, args = _unpack_self(*args) 

482 

483 _args = self._self_args + args 

484 

485 _kwargs = dict(self._self_kwargs) 

486 _kwargs.update(kwargs) 

487 

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

489 

490class _FunctionWrapperBase(ObjectProxy): 

491 

492 __slots__ = ('_self_instance', '_self_wrapper', '_self_enabled', 

493 '_self_binding', '_self_parent') 

494 

495 def __init__(self, wrapped, instance, wrapper, enabled=None, 

496 binding='function', parent=None): 

497 

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

499 

500 object.__setattr__(self, '_self_instance', instance) 

501 object.__setattr__(self, '_self_wrapper', wrapper) 

502 object.__setattr__(self, '_self_enabled', enabled) 

503 object.__setattr__(self, '_self_binding', binding) 

504 object.__setattr__(self, '_self_parent', parent) 

505 

506 def __get__(self, instance, owner): 

507 # This method is actually doing double duty for both unbound and 

508 # bound derived wrapper classes. It should possibly be broken up 

509 # and the distinct functionality moved into the derived classes. 

510 # Can't do that straight away due to some legacy code which is 

511 # relying on it being here in this base class. 

512 # 

513 # The distinguishing attribute which determines whether we are 

514 # being called in an unbound or bound wrapper is the parent 

515 # attribute. If binding has never occurred, then the parent will 

516 # be None. 

517 # 

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

519 # this case we perform the binding. 

520 # 

521 # We have one special case to worry about here. This is where we 

522 # are decorating a nested class. In this case the wrapped class 

523 # would not have a __get__() method to call. In that case we 

524 # simply return self. 

525 # 

526 # Note that we otherwise still do binding even if instance is 

527 # None and accessing an unbound instance method from a class. 

528 # This is because we need to be able to later detect that 

529 # specific case as we will need to extract the instance from the 

530 # first argument of those passed in. 

531 

532 if self._self_parent is None: 

533 if not inspect.isclass(self.__wrapped__): 

534 descriptor = self.__wrapped__.__get__(instance, owner) 

535 

536 return self.__bound_function_wrapper__(descriptor, instance, 

537 self._self_wrapper, self._self_enabled, 

538 self._self_binding, self) 

539 

540 return self 

541 

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

543 # was already a bound function. In this case we would usually 

544 # return ourselves again. This mirrors what Python does. 

545 # 

546 # The special case this time is where we were originally bound 

547 # with an instance of None and we were likely an instance 

548 # method. In that case we rebind against the original wrapped 

549 # function from the parent again. 

550 

551 if self._self_instance is None and self._self_binding == 'function': 

552 descriptor = self._self_parent.__wrapped__.__get__( 

553 instance, owner) 

554 

555 return self._self_parent.__bound_function_wrapper__( 

556 descriptor, instance, self._self_wrapper, 

557 self._self_enabled, self._self_binding, 

558 self._self_parent) 

559 

560 return self 

561 

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

563 def _unpack_self(self, *args): 

564 return self, args 

565 

566 self, args = _unpack_self(*args) 

567 

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

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

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

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

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

573 

574 if self._self_enabled is not None: 

575 if callable(self._self_enabled): 

576 if not self._self_enabled(): 

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

578 elif not self._self_enabled: 

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

580 

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

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

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

584 

585 if self._self_binding in ('function', 'classmethod'): 

586 if self._self_instance is None: 

587 instance = getattr(self.__wrapped__, '__self__', None) 

588 if instance is not None: 

589 return self._self_wrapper(self.__wrapped__, instance, 

590 args, kwargs) 

591 

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

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

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

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

596 # wrapped using the staticmethod decorator. 

597 

598 return self._self_wrapper(self.__wrapped__, self._self_instance, 

599 args, kwargs) 

600 

601 def __set_name__(self, owner, name): 

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

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

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

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

606 # FunctionWrapper used by decorators. 

607 

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

609 self.__wrapped__.__set_name__(owner, name) 

610 

611 def __instancecheck__(self, instance): 

612 # This is a special method used by isinstance() to make checks 

613 # instance of the `__wrapped__`. 

614 return isinstance(instance, self.__wrapped__) 

615 

616 def __subclasscheck__(self, subclass): 

617 # This is a special method used by issubclass() to make checks 

618 # about inheritance of classes. We need to upwrap any object 

619 # proxy. Not wanting to add this to ObjectProxy as not sure of 

620 # broader implications of doing that. Thus restrict to 

621 # FunctionWrapper used by decorators. 

622 

623 if hasattr(subclass, "__wrapped__"): 

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

625 else: 

626 return issubclass(subclass, self.__wrapped__) 

627 

628class BoundFunctionWrapper(_FunctionWrapperBase): 

629 

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

631 def _unpack_self(self, *args): 

632 return self, args 

633 

634 self, args = _unpack_self(*args) 

635 

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

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

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

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

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

641 

642 if self._self_enabled is not None: 

643 if callable(self._self_enabled): 

644 if not self._self_enabled(): 

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

646 elif not self._self_enabled: 

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

648 

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

650 # likely wrapping an instance method vs a static method or class 

651 # method. 

652 

653 if self._self_binding == 'function': 

654 if self._self_instance is None: 

655 # This situation can occur where someone is calling the 

656 # instancemethod via the class type and passing the instance 

657 # as the first argument. We need to shift the args before 

658 # making the call to the wrapper and effectively bind the 

659 # instance to the wrapped function using a partial so the 

660 # wrapper doesn't see anything as being different. 

661 

662 if not args: 

663 raise TypeError('missing 1 required positional argument') 

664 

665 instance, args = args[0], args[1:] 

666 wrapped = PartialCallableObjectProxy(self.__wrapped__, instance) 

667 return self._self_wrapper(wrapped, instance, args, kwargs) 

668 

669 return self._self_wrapper(self.__wrapped__, self._self_instance, 

670 args, kwargs) 

671 

672 else: 

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

674 # staticmethod, then _self_instance will only tell us whether 

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

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

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

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

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

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

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

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

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

684 # decoratored function. 

685 

686 instance = getattr(self.__wrapped__, '__self__', None) 

687 

688 return self._self_wrapper(self.__wrapped__, instance, args, 

689 kwargs) 

690 

691class FunctionWrapper(_FunctionWrapperBase): 

692 

693 __bound_function_wrapper__ = BoundFunctionWrapper 

694 

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

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

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

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

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

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

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

702 # method of knowing. 

703 # 

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

705 # 

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

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

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

709 # wrapper objects. 

710 # 

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

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

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

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

715 # distinguish it from wrapping a normal function outside of 

716 # a class context. 

717 # 

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

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

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

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

722 # 

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

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

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

726 # binding will have been performed where the instance against 

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

728 # 

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

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

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

732 # unnbound method no longer exists. 

733 # 

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

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

736 # have been perfomed where the instance was not None. 

737 # 

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

739 # method was a static method. 

740 # 

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

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

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

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

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

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

747 # thing where classmethod and staticmethod are used. 

748 # 

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

750 # decorators around classmethod and staticmethod, likelihood of 

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

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

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

754 # 

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

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

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

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

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

760 # 

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

762 # it is, we label it as a 'function'. If it was already bound and 

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

764 # method and try an cope with the possibility that the 'self' 

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

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

767 

768 if isinstance(wrapped, classmethod): 

769 binding = 'classmethod' 

770 

771 elif isinstance(wrapped, staticmethod): 

772 binding = 'staticmethod' 

773 

774 elif hasattr(wrapped, '__self__'): 

775 if inspect.isclass(wrapped.__self__): 

776 binding = 'classmethod' 

777 else: 

778 binding = 'function' 

779 

780 else: 

781 binding = 'function' 

782 

783 super(FunctionWrapper, self).__init__(wrapped, None, wrapper, 

784 enabled, binding) 

785 

786try: 

787 if not os.environ.get('WRAPT_DISABLE_EXTENSIONS'): 

788 from ._wrappers import (ObjectProxy, CallableObjectProxy, 

789 PartialCallableObjectProxy, FunctionWrapper, 

790 BoundFunctionWrapper, _FunctionWrapperBase) 

791except ImportError: 

792 pass 

793 

794# Helper functions for applying wrappers to existing functions. 

795 

796def resolve_path(module, name): 

797 if isinstance(module, string_types): 

798 __import__(module) 

799 module = sys.modules[module] 

800 

801 parent = module 

802 

803 path = name.split('.') 

804 attribute = path[0] 

805 

806 # We can't just always use getattr() because in doing 

807 # that on a class it will cause binding to occur which 

808 # will complicate things later and cause some things not 

809 # to work. For the case of a class we therefore access 

810 # the __dict__ directly. To cope though with the wrong 

811 # class being given to us, or a method being moved into 

812 # a base class, we need to walk the class hierarchy to 

813 # work out exactly which __dict__ the method was defined 

814 # in, as accessing it from __dict__ will fail if it was 

815 # not actually on the class given. Fallback to using 

816 # getattr() if we can't find it. If it truly doesn't 

817 # exist, then that will fail. 

818 

819 def lookup_attribute(parent, attribute): 

820 if inspect.isclass(parent): 

821 for cls in inspect.getmro(parent): 

822 if attribute in vars(cls): 

823 return vars(cls)[attribute] 

824 else: 

825 return getattr(parent, attribute) 

826 else: 

827 return getattr(parent, attribute) 

828 

829 original = lookup_attribute(parent, attribute) 

830 

831 for attribute in path[1:]: 

832 parent = original 

833 original = lookup_attribute(parent, attribute) 

834 

835 return (parent, attribute, original) 

836 

837def apply_patch(parent, attribute, replacement): 

838 setattr(parent, attribute, replacement) 

839 

840def wrap_object(module, name, factory, args=(), kwargs={}): 

841 (parent, attribute, original) = resolve_path(module, name) 

842 wrapper = factory(original, *args, **kwargs) 

843 apply_patch(parent, attribute, wrapper) 

844 return wrapper 

845 

846# Function for applying a proxy object to an attribute of a class 

847# instance. The wrapper works by defining an attribute of the same name 

848# on the class which is a descriptor and which intercepts access to the 

849# instance attribute. Note that this cannot be used on attributes which 

850# are themselves defined by a property object. 

851 

852class AttributeWrapper(object): 

853 

854 def __init__(self, attribute, factory, args, kwargs): 

855 self.attribute = attribute 

856 self.factory = factory 

857 self.args = args 

858 self.kwargs = kwargs 

859 

860 def __get__(self, instance, owner): 

861 value = instance.__dict__[self.attribute] 

862 return self.factory(value, *self.args, **self.kwargs) 

863 

864 def __set__(self, instance, value): 

865 instance.__dict__[self.attribute] = value 

866 

867 def __delete__(self, instance): 

868 del instance.__dict__[self.attribute] 

869 

870def wrap_object_attribute(module, name, factory, args=(), kwargs={}): 

871 path, attribute = name.rsplit('.', 1) 

872 parent = resolve_path(module, path)[2] 

873 wrapper = AttributeWrapper(attribute, factory, args, kwargs) 

874 apply_patch(parent, attribute, wrapper) 

875 return wrapper 

876 

877# Functions for creating a simple decorator using a FunctionWrapper, 

878# plus short cut functions for applying wrappers to functions. These are 

879# for use when doing monkey patching. For a more featured way of 

880# creating decorators see the decorator decorator instead. 

881 

882def function_wrapper(wrapper): 

883 def _wrapper(wrapped, instance, args, kwargs): 

884 target_wrapped = args[0] 

885 if instance is None: 

886 target_wrapper = wrapper 

887 elif inspect.isclass(instance): 

888 target_wrapper = wrapper.__get__(None, instance) 

889 else: 

890 target_wrapper = wrapper.__get__(instance, type(instance)) 

891 return FunctionWrapper(target_wrapped, target_wrapper) 

892 return FunctionWrapper(wrapper, _wrapper) 

893 

894def wrap_function_wrapper(module, name, wrapper): 

895 return wrap_object(module, name, FunctionWrapper, (wrapper,)) 

896 

897def patch_function_wrapper(module, name): 

898 def _wrapper(wrapper): 

899 return wrap_object(module, name, FunctionWrapper, (wrapper,)) 

900 return _wrapper 

901 

902def transient_function_wrapper(module, name): 

903 def _decorator(wrapper): 

904 def _wrapper(wrapped, instance, args, kwargs): 

905 target_wrapped = args[0] 

906 if instance is None: 

907 target_wrapper = wrapper 

908 elif inspect.isclass(instance): 

909 target_wrapper = wrapper.__get__(None, instance) 

910 else: 

911 target_wrapper = wrapper.__get__(instance, type(instance)) 

912 def _execute(wrapped, instance, args, kwargs): 

913 (parent, attribute, original) = resolve_path(module, name) 

914 replacement = FunctionWrapper(original, target_wrapper) 

915 setattr(parent, attribute, replacement) 

916 try: 

917 return wrapped(*args, **kwargs) 

918 finally: 

919 setattr(parent, attribute, original) 

920 return FunctionWrapper(target_wrapped, _execute) 

921 return FunctionWrapper(wrapper, _wrapper) 

922 return _decorator 

923 

924# A weak function proxy. This will work on instance methods, class 

925# methods, static methods and regular functions. Special treatment is 

926# needed for the method types because the bound method is effectively a 

927# transient object and applying a weak reference to one will immediately 

928# result in it being destroyed and the weakref callback called. The weak 

929# reference is therefore applied to the instance the method is bound to 

930# and the original function. The function is then rebound at the point 

931# of a call via the weak function proxy. 

932 

933def _weak_function_proxy_callback(ref, proxy, callback): 

934 if proxy._self_expired: 

935 return 

936 

937 proxy._self_expired = True 

938 

939 # This could raise an exception. We let it propagate back and let 

940 # the weakref.proxy() deal with it, at which point it generally 

941 # prints out a short error message direct to stderr and keeps going. 

942 

943 if callback is not None: 

944 callback(proxy) 

945 

946class WeakFunctionProxy(ObjectProxy): 

947 

948 __slots__ = ('_self_expired', '_self_instance') 

949 

950 def __init__(self, wrapped, callback=None): 

951 # We need to determine if the wrapped function is actually a 

952 # bound method. In the case of a bound method, we need to keep a 

953 # reference to the original unbound function and the instance. 

954 # This is necessary because if we hold a reference to the bound 

955 # function, it will be the only reference and given it is a 

956 # temporary object, it will almost immediately expire and 

957 # the weakref callback triggered. So what is done is that we 

958 # hold a reference to the instance and unbound function and 

959 # when called bind the function to the instance once again and 

960 # then call it. Note that we avoid using a nested function for 

961 # the callback here so as not to cause any odd reference cycles. 

962 

963 _callback = callback and functools.partial( 

964 _weak_function_proxy_callback, proxy=self, 

965 callback=callback) 

966 

967 self._self_expired = False 

968 

969 if isinstance(wrapped, _FunctionWrapperBase): 

970 self._self_instance = weakref.ref(wrapped._self_instance, 

971 _callback) 

972 

973 if wrapped._self_parent is not None: 

974 super(WeakFunctionProxy, self).__init__( 

975 weakref.proxy(wrapped._self_parent, _callback)) 

976 

977 else: 

978 super(WeakFunctionProxy, self).__init__( 

979 weakref.proxy(wrapped, _callback)) 

980 

981 return 

982 

983 try: 

984 self._self_instance = weakref.ref(wrapped.__self__, _callback) 

985 

986 super(WeakFunctionProxy, self).__init__( 

987 weakref.proxy(wrapped.__func__, _callback)) 

988 

989 except AttributeError: 

990 self._self_instance = None 

991 

992 super(WeakFunctionProxy, self).__init__( 

993 weakref.proxy(wrapped, _callback)) 

994 

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

996 def _unpack_self(self, *args): 

997 return self, args 

998 

999 self, args = _unpack_self(*args) 

1000 

1001 # We perform a boolean check here on the instance and wrapped 

1002 # function as that will trigger the reference error prior to 

1003 # calling if the reference had expired. 

1004 

1005 instance = self._self_instance and self._self_instance() 

1006 function = self.__wrapped__ and self.__wrapped__ 

1007 

1008 # If the wrapped function was originally a bound function, for 

1009 # which we retained a reference to the instance and the unbound 

1010 # function we need to rebind the function and then call it. If 

1011 # not just called the wrapped function. 

1012 

1013 if instance is None: 

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

1015 

1016 return function.__get__(instance, type(instance))(*args, **kwargs)