simple.py 9.2 KB

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