simple.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. import operator
  2. from .compat import string_types
  3. from .compat import with_metaclass
  4. from .utils import await_
  5. from .utils import cached_property
  6. from .utils import identity
  7. def make_proxy_method(code):
  8. def proxy_wrapper(self, *args):
  9. return code(self.__wrapped__, *args)
  10. return proxy_wrapper
  11. class _ProxyMethods:
  12. # We use properties to override the values of __module__ and
  13. # __doc__. If we add these in ObjectProxy, the derived class
  14. # __dict__ will still be setup to have string variants of these
  15. # attributes and the rules of descriptors means that they appear to
  16. # take precedence over the properties in the base class. To avoid
  17. # that, we copy the properties into the derived class type itself
  18. # via a meta class. In that way the properties will always take
  19. # precedence.
  20. @property
  21. def __module__(self):
  22. return self.__wrapped__.__module__
  23. @__module__.setter
  24. def __module__(self, value):
  25. self.__wrapped__.__module__ = value
  26. @property
  27. def __doc__(self):
  28. return self.__wrapped__.__doc__
  29. @__doc__.setter
  30. def __doc__(self, value):
  31. self.__wrapped__.__doc__ = value
  32. # Need to also propagate the special __weakref__ attribute for case
  33. # where decorating classes which will define this. If do not define
  34. # it and use a function like inspect.getmembers() on a decorator
  35. # class it will fail. This can't be in the derived classes.
  36. @property
  37. def __weakref__(self):
  38. return self.__wrapped__.__weakref__
  39. class _ProxyMetaType(type):
  40. def __new__(cls, name, bases, dictionary):
  41. # Copy our special properties into the class so that they
  42. # always take precedence over attributes of the same name added
  43. # during construction of a derived class. This is to save
  44. # duplicating the implementation for them in all derived classes.
  45. dictionary.update(vars(_ProxyMethods))
  46. dictionary.pop('__dict__')
  47. return type.__new__(cls, name, bases, dictionary)
  48. class Proxy(with_metaclass(_ProxyMetaType)):
  49. __factory__ = None
  50. def __init__(self, factory):
  51. self.__dict__['__factory__'] = factory
  52. @property
  53. def __resolved__(self):
  54. return '__wrapped__' in self.__dict__
  55. @cached_property
  56. def __wrapped__(self):
  57. self = self.__dict__
  58. if '__factory__' in self:
  59. factory = self['__factory__']
  60. return factory()
  61. else:
  62. raise ValueError("Proxy hasn't been initiated: __factory__ is missing.")
  63. __name__ = property(make_proxy_method(operator.attrgetter('__name__')))
  64. __class__ = property(make_proxy_method(operator.attrgetter('__class__')))
  65. __annotations__ = property(make_proxy_method(operator.attrgetter('__anotations__')))
  66. __dir__ = make_proxy_method(dir)
  67. __str__ = make_proxy_method(str)
  68. __bytes__ = make_proxy_method(bytes)
  69. def __repr__(self, __getattr__=object.__getattribute__):
  70. if '__wrapped__' in self.__dict__:
  71. return '<{} at 0x{:x} wrapping {!r} at 0x{:x} with factory {!r}>'.format(
  72. type(self).__name__, id(self), self.__wrapped__, id(self.__wrapped__), self.__factory__
  73. )
  74. else:
  75. return f'<{type(self).__name__} at 0x{id(self):x} with factory {self.__factory__!r}>'
  76. def __fspath__(self):
  77. wrapped = self.__wrapped__
  78. if isinstance(wrapped, string_types):
  79. return wrapped
  80. else:
  81. fspath = getattr(wrapped, '__fspath__', None)
  82. if fspath is None:
  83. return wrapped
  84. else:
  85. return fspath()
  86. __reversed__ = make_proxy_method(reversed)
  87. __round__ = make_proxy_method(round)
  88. __lt__ = make_proxy_method(operator.lt)
  89. __le__ = make_proxy_method(operator.le)
  90. __eq__ = make_proxy_method(operator.eq)
  91. __ne__ = make_proxy_method(operator.ne)
  92. __gt__ = make_proxy_method(operator.gt)
  93. __ge__ = make_proxy_method(operator.ge)
  94. __hash__ = make_proxy_method(hash)
  95. __nonzero__ = make_proxy_method(bool)
  96. __bool__ = make_proxy_method(bool)
  97. def __setattr__(self, name, value):
  98. if hasattr(type(self), name):
  99. self.__dict__[name] = value
  100. else:
  101. setattr(self.__wrapped__, name, value)
  102. def __getattr__(self, name):
  103. if name in ('__wrapped__', '__factory__'):
  104. raise AttributeError(name)
  105. else:
  106. return getattr(self.__wrapped__, name)
  107. def __delattr__(self, name):
  108. if hasattr(type(self), name):
  109. del self.__dict__[name]
  110. else:
  111. delattr(self.__wrapped__, name)
  112. __add__ = make_proxy_method(operator.add)
  113. __sub__ = make_proxy_method(operator.sub)
  114. __mul__ = make_proxy_method(operator.mul)
  115. __matmul__ = make_proxy_method(operator.matmul)
  116. __truediv__ = make_proxy_method(operator.truediv)
  117. __floordiv__ = make_proxy_method(operator.floordiv)
  118. __mod__ = make_proxy_method(operator.mod)
  119. __divmod__ = make_proxy_method(divmod)
  120. __pow__ = make_proxy_method(pow)
  121. __lshift__ = make_proxy_method(operator.lshift)
  122. __rshift__ = make_proxy_method(operator.rshift)
  123. __and__ = make_proxy_method(operator.and_)
  124. __xor__ = make_proxy_method(operator.xor)
  125. __or__ = make_proxy_method(operator.or_)
  126. def __radd__(self, other):
  127. return other + self.__wrapped__
  128. def __rsub__(self, other):
  129. return other - self.__wrapped__
  130. def __rmul__(self, other):
  131. return other * self.__wrapped__
  132. def __rmatmul__(self, other):
  133. return other @ self.__wrapped__
  134. def __rdiv__(self, other):
  135. return operator.div(other, self.__wrapped__)
  136. def __rtruediv__(self, other):
  137. return operator.truediv(other, self.__wrapped__)
  138. def __rfloordiv__(self, other):
  139. return other // self.__wrapped__
  140. def __rmod__(self, other):
  141. return other % self.__wrapped__
  142. def __rdivmod__(self, other):
  143. return divmod(other, self.__wrapped__)
  144. def __rpow__(self, other, *args):
  145. return pow(other, self.__wrapped__, *args)
  146. def __rlshift__(self, other):
  147. return other << self.__wrapped__
  148. def __rrshift__(self, other):
  149. return other >> self.__wrapped__
  150. def __rand__(self, other):
  151. return other & self.__wrapped__
  152. def __rxor__(self, other):
  153. return other ^ self.__wrapped__
  154. def __ror__(self, other):
  155. return other | self.__wrapped__
  156. __iadd__ = make_proxy_method(operator.iadd)
  157. __isub__ = make_proxy_method(operator.isub)
  158. __imul__ = make_proxy_method(operator.imul)
  159. __imatmul__ = make_proxy_method(operator.imatmul)
  160. __itruediv__ = make_proxy_method(operator.itruediv)
  161. __ifloordiv__ = make_proxy_method(operator.ifloordiv)
  162. __imod__ = make_proxy_method(operator.imod)
  163. __ipow__ = make_proxy_method(operator.ipow)
  164. __ilshift__ = make_proxy_method(operator.ilshift)
  165. __irshift__ = make_proxy_method(operator.irshift)
  166. __iand__ = make_proxy_method(operator.iand)
  167. __ixor__ = make_proxy_method(operator.ixor)
  168. __ior__ = make_proxy_method(operator.ior)
  169. __neg__ = make_proxy_method(operator.neg)
  170. __pos__ = make_proxy_method(operator.pos)
  171. __abs__ = make_proxy_method(operator.abs)
  172. __invert__ = make_proxy_method(operator.invert)
  173. __int__ = make_proxy_method(int)
  174. __float__ = make_proxy_method(float)
  175. __oct__ = make_proxy_method(oct)
  176. __hex__ = make_proxy_method(hex)
  177. def __index__(self):
  178. if hasattr(self.__wrapped__, '__index__'):
  179. return operator.index(self.__wrapped__)
  180. else:
  181. return int(self.__wrapped__)
  182. __len__ = make_proxy_method(len)
  183. __contains__ = make_proxy_method(operator.contains)
  184. __getitem__ = make_proxy_method(operator.getitem)
  185. __setitem__ = make_proxy_method(operator.setitem)
  186. __delitem__ = make_proxy_method(operator.delitem)
  187. def __enter__(self):
  188. return self.__wrapped__.__enter__()
  189. def __exit__(self, *args, **kwargs):
  190. return self.__wrapped__.__exit__(*args, **kwargs)
  191. __iter__ = make_proxy_method(iter)
  192. def __call__(self, *args, **kwargs):
  193. return self.__wrapped__(*args, **kwargs)
  194. def __reduce__(self):
  195. return identity, (self.__wrapped__,)
  196. def __reduce_ex__(self, protocol):
  197. return identity, (self.__wrapped__,)
  198. if await_:
  199. from .utils import __aenter__
  200. from .utils import __aexit__
  201. from .utils import __aiter__
  202. from .utils import __anext__
  203. from .utils import __await__
  204. __aiter__, __anext__, __await__, __aenter__, __aexit__ # noqa