__compat__.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. from __future__ import absolute_import
  2. import operator
  3. import sys
  4. from importlib import import_module
  5. from types import ModuleType
  6. from .local import Proxy
  7. MODULE_DEPRECATED = """
  8. The module %s is deprecated and will be removed in a future version.
  9. """
  10. DEFAULT_ATTRS = set(["__file__", "__path__", "__doc__", "__all__"])
  11. # im_func is no longer available in Py3.
  12. # instead the unbound method itself can be used.
  13. if sys.version_info[0] == 3: # pragma: no cover
  14. def fun_of_method(method):
  15. return method
  16. else:
  17. def fun_of_method(method): # noqa
  18. return method.im_func
  19. def getappattr(path):
  20. """Gets attribute from the current_app recursively,
  21. e.g. getappattr("amqp.get_task_consumer")``."""
  22. from celery import current_app
  23. return current_app._rgetattr(path)
  24. def _compat_task_decorator(*args, **kwargs):
  25. from celery import current_app
  26. kwargs.setdefault("accept_magic_kwargs", True)
  27. return current_app.task(*args, **kwargs)
  28. def _compat_periodic_task_decorator(*args, **kwargs):
  29. from celery.task import periodic_task
  30. kwargs.setdefault("accept_magic_kwargs", True)
  31. return periodic_task(*args, **kwargs)
  32. COMPAT_MODULES = {
  33. "celery": {
  34. "execute": {
  35. "send_task": "send_task",
  36. },
  37. "decorators": {
  38. "task": _compat_task_decorator,
  39. "periodic_task": _compat_periodic_task_decorator,
  40. },
  41. "log": {
  42. "get_default_logger": "log.get_default_logger",
  43. "setup_logger": "log.setup_logger",
  44. "setup_loggig_subsystem": "log.setup_logging_subsystem",
  45. "redirect_stdouts_to_logger": "log.redirect_stdouts_to_logger",
  46. },
  47. "messaging": {
  48. "TaskPublisher": "amqp.TaskPublisher",
  49. "TaskConsumer": "amqp.TaskConsumer",
  50. "establish_connection": "broker_connection",
  51. "with_connection": "with_default_connection",
  52. "get_consumer_set": "amqp.TaskConsumer",
  53. },
  54. "registry": {
  55. "tasks": "tasks",
  56. },
  57. },
  58. "celery.task": {
  59. "control": {
  60. "broadcast": "control.broadcast",
  61. "rate_limit": "control.rate_limit",
  62. "time_limit": "control.time_limit",
  63. "ping": "control.ping",
  64. "revoke": "control.revoke",
  65. "discard_all": "control.purge",
  66. "inspect": "control.inspect",
  67. },
  68. "schedules": "celery.schedules",
  69. "chords": "celery.canvas",
  70. }
  71. }
  72. class class_property(object):
  73. def __init__(self, fget=None, fset=None):
  74. assert fget and isinstance(fget, classmethod)
  75. assert isinstance(fset, classmethod) if fset else True
  76. self.__get = fget
  77. self.__set = fset
  78. info = fget.__get__(object) # just need the info attrs.
  79. self.__doc__ = info.__doc__
  80. self.__name__ = info.__name__
  81. self.__module__ = info.__module__
  82. def __get__(self, obj, type=None):
  83. if obj and type is None:
  84. type = obj.__class__
  85. return self.__get.__get__(obj, type)()
  86. def __set__(self, obj, value):
  87. if obj is None:
  88. return self
  89. return self.__set.__get__(obj)(value)
  90. def reclassmethod(method):
  91. return classmethod(fun_of_method(method))
  92. class MagicModule(ModuleType):
  93. _compat_modules = ()
  94. _all_by_module = {}
  95. _direct = {}
  96. _object_origins = {}
  97. def __getattr__(self, name):
  98. if name in self._object_origins:
  99. module = __import__(self._object_origins[name], None, None, [name])
  100. for item in self._all_by_module[module.__name__]:
  101. setattr(self, item, getattr(module, item))
  102. return getattr(module, name)
  103. elif name in self._direct:
  104. module = __import__(self._direct[name], None, None, [name])
  105. setattr(self, name, module)
  106. return module
  107. return ModuleType.__getattribute__(self, name)
  108. def __dir__(self):
  109. return list(set(self.__all__) | DEFAULT_ATTRS)
  110. def create_module(name, attrs, cls_attrs=None, pkg=None, base=MagicModule,
  111. prepare_attr=None):
  112. fqdn = '.'.join([pkg.__name__, name]) if pkg else name
  113. cls_attrs = {} if cls_attrs is None else cls_attrs
  114. attrs = dict((attr_name, prepare_attr(attr) if prepare_attr else attr)
  115. for attr_name, attr in attrs.iteritems())
  116. module = sys.modules[fqdn] = type(name, (base, ), cls_attrs)(fqdn)
  117. module.__dict__.update(attrs)
  118. return module
  119. def recreate_module(name, compat_modules=(), by_module={}, direct={},
  120. base=MagicModule, **attrs):
  121. old_module = sys.modules[name]
  122. origins = get_origins(by_module)
  123. compat_modules = COMPAT_MODULES.get(name, ())
  124. cattrs = dict(_compat_modules=compat_modules,
  125. _all_by_module=by_module, _direct=direct,
  126. _object_origins=origins,
  127. __all__=tuple(set(reduce(operator.add, map(tuple, [
  128. compat_modules, origins, direct, attrs])))))
  129. new_module = create_module(name, attrs, cls_attrs=cattrs, base=base)
  130. new_module.__dict__.update(dict((mod, get_compat_module(new_module, mod))
  131. for mod in compat_modules))
  132. return old_module, new_module
  133. def get_compat_module(pkg, name):
  134. def prepare(attr):
  135. if isinstance(attr, basestring):
  136. return Proxy(getappattr, (attr, ))
  137. return attr
  138. attrs = COMPAT_MODULES[pkg.__name__][name]
  139. if isinstance(attrs, basestring):
  140. fqdn = '.'.join([pkg.__name__, name])
  141. module = sys.modules[fqdn] = import_module(attrs)
  142. return module
  143. attrs["__all__"] = attrs.keys()
  144. return create_module(name, dict(attrs), pkg=pkg, prepare_attr=prepare)
  145. def get_origins(defs):
  146. origins = {}
  147. for module, items in defs.iteritems():
  148. origins.update(dict((item, module) for item in items))
  149. return origins