local.py 10 KB

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