local.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. # -*- coding: utf-8 -*-
  2. """
  3. celery.local
  4. ~~~~~~~~~~~~
  5. This module contains critical utilities that
  6. needs to be loaded as soon as possible, and that
  7. shall not load any third party modules.
  8. Parts of this module is Copyright by Werkzeug Team.
  9. """
  10. from __future__ import absolute_import
  11. import importlib
  12. from .five import long_t, string, string_t
  13. __module__ = __name__ # used by Proxy class body
  14. def _default_cls_attr(name, type_, cls_value):
  15. # Proxy uses properties to forward the standard
  16. # class attributes __module__, __name__ and __doc__ to the real
  17. # object, but these needs to be a string when accessed from
  18. # the Proxy class directly. This is a hack to make that work.
  19. # -- See Issue #1087.
  20. def __new__(cls, getter):
  21. instance = type_.__new__(cls, cls_value)
  22. instance.__getter = getter
  23. return instance
  24. def __get__(self, obj, cls=None):
  25. return self.__getter(obj) if obj is not None else self
  26. def __set__(self, obj, value):
  27. raise AttributeError('readonly attribute')
  28. return type(name, (type_, ), {
  29. '__new__': __new__, '__get__': __get__, '__set__': __set__,
  30. })
  31. class _cls_spec(str):
  32. def __new__(cls, getter):
  33. s = str.__new__(cls, getter.__module__)
  34. s.__getter = getter
  35. return s
  36. def __get__(self, obj, cls=None):
  37. if obj is not None:
  38. return self.__getter(obj)
  39. return self
  40. def __set__(self, obj, value):
  41. raise AttributeError('cannot set attribute')
  42. def symbol_by_name(name, aliases={}, imp=None, package=None,
  43. sep='.', default=None, **kwargs):
  44. """Get symbol by qualified name.
  45. The name should be the full dot-separated path to the class::
  46. modulename.ClassName
  47. Example::
  48. celery.concurrency.processes.TaskPool
  49. ^- class name
  50. or using ':' to separate module and symbol::
  51. celery.concurrency.processes:TaskPool
  52. If `aliases` is provided, a dict containing short name/long name
  53. mappings, the name is looked up in the aliases first.
  54. Examples:
  55. >>> symbol_by_name('celery.concurrency.processes.TaskPool')
  56. <class 'celery.concurrency.processes.TaskPool'>
  57. >>> symbol_by_name('default', {
  58. ... 'default': 'celery.concurrency.processes.TaskPool'})
  59. <class 'celery.concurrency.processes.TaskPool'>
  60. # Does not try to look up non-string names.
  61. >>> from celery.concurrency.processes import TaskPool
  62. >>> symbol_by_name(TaskPool) is TaskPool
  63. True
  64. """
  65. if imp is None:
  66. imp = importlib.import_module
  67. if not isinstance(name, string_t):
  68. return name # already a class
  69. name = aliases.get(name) or name
  70. sep = ':' if ':' in name else sep
  71. module_name, _, cls_name = name.rpartition(sep)
  72. if not module_name:
  73. cls_name, module_name = None, package if package else cls_name
  74. try:
  75. try:
  76. module = imp(module_name, package=package, **kwargs)
  77. except ValueError as exc:
  78. raise ValueError("Couldn't import %r: %s" % (name, exc))
  79. return getattr(module, cls_name) if cls_name else module
  80. except (ImportError, AttributeError):
  81. if default is None:
  82. raise
  83. return default
  84. def try_import(module, default=None):
  85. """Try to import and return module, or return
  86. None if the module does not exist."""
  87. try:
  88. return importlib.import_module(module)
  89. except ImportError:
  90. return default
  91. class Proxy(object):
  92. """Proxy to another object."""
  93. # Code stolen from werkzeug.local.Proxy.
  94. __slots__ = ('__local', '__args', '__kwargs', '__dict__')
  95. def __init__(self, local, args=None, kwargs=None, name=None):
  96. object.__setattr__(self, '_Proxy__local', local)
  97. object.__setattr__(self, '_Proxy__args', args or ())
  98. object.__setattr__(self, '_Proxy__kwargs', kwargs or {})
  99. if name is not None:
  100. object.__setattr__(self, '__custom_name__', name)
  101. @_default_cls_attr('name', str, __name__)
  102. def __name__(self):
  103. try:
  104. return self.__custom_name__
  105. except AttributeError:
  106. return self._get_current_object().__name__
  107. @_default_cls_attr('module', str, __module__)
  108. def __module__(self):
  109. return self._get_current_object().__module__
  110. @_default_cls_attr('doc', str, __doc__)
  111. def __doc__(self):
  112. return self._get_current_object().__doc__
  113. def _get_class(self):
  114. return self._get_current_object().__class__
  115. @property
  116. def __class__(self):
  117. return self._get_class()
  118. def _get_current_object(self):
  119. """Return the current object. This is useful if you want the real
  120. object behind the proxy at a time for performance reasons or because
  121. you want to pass the object into a different context.
  122. """
  123. loc = object.__getattribute__(self, '_Proxy__local')
  124. if not hasattr(loc, '__release_local__'):
  125. return loc(*self.__args, **self.__kwargs)
  126. try:
  127. return getattr(loc, self.__name__)
  128. except AttributeError:
  129. raise RuntimeError('no object bound to {0.__name__}'.format(self))
  130. @property
  131. def __dict__(self):
  132. try:
  133. return self._get_current_object().__dict__
  134. except RuntimeError: # pragma: no cover
  135. raise AttributeError('__dict__')
  136. def __repr__(self):
  137. try:
  138. obj = self._get_current_object()
  139. except RuntimeError: # pragma: no cover
  140. return '<{0} unbound>'.format(self.__class__.__name__)
  141. return repr(obj)
  142. def __bool__(self):
  143. try:
  144. return bool(self._get_current_object())
  145. except RuntimeError: # pragma: no cover
  146. return False
  147. __nonzero__ = __bool__ # Py2
  148. def __unicode__(self):
  149. try:
  150. return string(self._get_current_object())
  151. except RuntimeError: # pragma: no cover
  152. return repr(self)
  153. def __dir__(self):
  154. try:
  155. return dir(self._get_current_object())
  156. except RuntimeError: # pragma: no cover
  157. return []
  158. def __getattr__(self, name):
  159. if name == '__members__':
  160. return dir(self._get_current_object())
  161. return getattr(self._get_current_object(), name)
  162. def __setitem__(self, key, value):
  163. self._get_current_object()[key] = value
  164. def __delitem__(self, key):
  165. del self._get_current_object()[key]
  166. def __setslice__(self, i, j, seq):
  167. self._get_current_object()[i:j] = seq
  168. def __delslice__(self, i, j):
  169. del self._get_current_object()[i:j]
  170. __setattr__ = lambda x, n, v: setattr(x._get_current_object(), n, v)
  171. __delattr__ = lambda x, n: delattr(x._get_current_object(), n)
  172. __str__ = lambda x: str(x._get_current_object())
  173. __lt__ = lambda x, o: x._get_current_object() < o
  174. __le__ = lambda x, o: x._get_current_object() <= o
  175. __eq__ = lambda x, o: x._get_current_object() == o
  176. __ne__ = lambda x, o: x._get_current_object() != o
  177. __gt__ = lambda x, o: x._get_current_object() > o
  178. __ge__ = lambda x, o: x._get_current_object() >= o
  179. __cmp__ = lambda x, o: cmp(x._get_current_object(), o)
  180. __hash__ = lambda x: hash(x._get_current_object())
  181. __call__ = lambda x, *a, **kw: x._get_current_object()(*a, **kw)
  182. __len__ = lambda x: len(x._get_current_object())
  183. __getitem__ = lambda x, i: x._get_current_object()[i]
  184. __iter__ = lambda x: iter(x._get_current_object())
  185. __contains__ = lambda x, i: i in x._get_current_object()
  186. __getslice__ = lambda x, i, j: x._get_current_object()[i:j]
  187. __add__ = lambda x, o: x._get_current_object() + o
  188. __sub__ = lambda x, o: x._get_current_object() - o
  189. __mul__ = lambda x, o: x._get_current_object() * o
  190. __floordiv__ = lambda x, o: x._get_current_object() // o
  191. __mod__ = lambda x, o: x._get_current_object() % o
  192. __divmod__ = lambda x, o: x._get_current_object().__divmod__(o)
  193. __pow__ = lambda x, o: x._get_current_object() ** o
  194. __lshift__ = lambda x, o: x._get_current_object() << o
  195. __rshift__ = lambda x, o: x._get_current_object() >> o
  196. __and__ = lambda x, o: x._get_current_object() & o
  197. __xor__ = lambda x, o: x._get_current_object() ^ o
  198. __or__ = lambda x, o: x._get_current_object() | o
  199. __div__ = lambda x, o: x._get_current_object().__div__(o)
  200. __truediv__ = lambda x, o: x._get_current_object().__truediv__(o)
  201. __neg__ = lambda x: -(x._get_current_object())
  202. __pos__ = lambda x: +(x._get_current_object())
  203. __abs__ = lambda x: abs(x._get_current_object())
  204. __invert__ = lambda x: ~(x._get_current_object())
  205. __complex__ = lambda x: complex(x._get_current_object())
  206. __int__ = lambda x: int(x._get_current_object())
  207. __long__ = lambda x: long_t(x._get_current_object())
  208. __float__ = lambda x: float(x._get_current_object())
  209. __oct__ = lambda x: oct(x._get_current_object())
  210. __hex__ = lambda x: hex(x._get_current_object())
  211. __index__ = lambda x: x._get_current_object().__index__()
  212. __coerce__ = lambda x, o: x.__coerce__(x, o)
  213. __enter__ = lambda x: x._get_current_object().__enter__()
  214. __exit__ = lambda x, *a, **kw: x._get_current_object().__exit__(*a, **kw)
  215. __reduce__ = lambda x: x._get_current_object().__reduce__()
  216. class PromiseProxy(Proxy):
  217. """This is a proxy to an object that has not yet been evaulated.
  218. :class:`Proxy` will evaluate the object each time, while the
  219. promise will only evaluate it once.
  220. """
  221. def _get_current_object(self):
  222. try:
  223. return object.__getattribute__(self, '__thing')
  224. except AttributeError:
  225. return self.__evaluate__()
  226. def __evaluated__(self):
  227. try:
  228. object.__getattribute__(self, '__thing')
  229. except AttributeError:
  230. return False
  231. return True
  232. def __maybe_evaluate__(self):
  233. return self._get_current_object()
  234. def __evaluate__(self):
  235. try:
  236. thing = Proxy._get_current_object(self)
  237. object.__setattr__(self, '__thing', thing)
  238. return thing
  239. finally:
  240. object.__delattr__(self, '_Proxy__local')
  241. object.__delattr__(self, '_Proxy__args')
  242. object.__delattr__(self, '_Proxy__kwargs')
  243. def maybe_evaluate(obj):
  244. try:
  245. return obj.__maybe_evaluate__()
  246. except AttributeError:
  247. return obj