__compat__.py 5.5 KB

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