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

390 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-03 07:57 +0000

1import sys 

2import operator 

3import inspect 

4 

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

6 

7if PY2: 

8 string_types = basestring, 

9else: 

10 string_types = str, 

11 

12def with_metaclass(meta, *bases): 

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

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

15 

16class _ObjectProxyMethods(object): 

17 

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

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

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

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

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

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

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

25 # precedence. 

26 

27 @property 

28 def __module__(self): 

29 return self.__wrapped__.__module__ 

30 

31 @__module__.setter 

32 def __module__(self, value): 

33 self.__wrapped__.__module__ = value 

34 

35 @property 

36 def __doc__(self): 

37 return self.__wrapped__.__doc__ 

38 

39 @__doc__.setter 

40 def __doc__(self, value): 

41 self.__wrapped__.__doc__ = value 

42 

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

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

45 

46 @property 

47 def __dict__(self): 

48 return self.__wrapped__.__dict__ 

49 

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

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

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

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

54 

55 @property 

56 def __weakref__(self): 

57 return self.__wrapped__.__weakref__ 

58 

59class _ObjectProxyMetaType(type): 

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

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

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

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

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

65 

66 dictionary.update(vars(_ObjectProxyMethods)) 

67 

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

69 

70class ObjectProxy(with_metaclass(_ObjectProxyMetaType)): 

71 

72 __slots__ = '__wrapped__' 

73 

74 def __init__(self, wrapped): 

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

76 

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

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

79 # be an actual string object instead. 

80 

81 try: 

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

83 except AttributeError: 

84 pass 

85 

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

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

88 

89 try: 

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

91 except AttributeError: 

92 pass 

93 

94 def __self_setattr__(self, name, value): 

95 object.__setattr__(self, name, value) 

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)