|
@@ -11,6 +11,8 @@ MODULE_DEPRECATED = """
|
|
|
The module %s is deprecated and will be removed in a future version.
|
|
|
"""
|
|
|
|
|
|
+DEFAULT_ATTRS = frozenset(("__file__", "__path__", "__doc__", "__all__"))
|
|
|
+
|
|
|
# im_func is no longer available in Py3.
|
|
|
# instead the unbound method itself can be used.
|
|
|
if sys.version_info[0] == 3:
|
|
@@ -21,6 +23,11 @@ else:
|
|
|
return method.im_func
|
|
|
|
|
|
|
|
|
+def getappattr(path):
|
|
|
+ """Gets attribute from the current_app recursively,
|
|
|
+ e.g. getappattr("amqp.get_task_consumer")``."""
|
|
|
+ from celery import current_app
|
|
|
+ return reduce(lambda a, b: getattr(a, b), [current_app] + path)
|
|
|
def _compat_task_decorator(*args, **kwargs):
|
|
|
from celery import current_app
|
|
|
kwargs.setdefault("accept_magic_kwargs", True)
|
|
@@ -33,8 +40,11 @@ def _compat_periodic_task_decorator(*args, **kwargs):
|
|
|
return periodic_task(*args, **kwargs)
|
|
|
|
|
|
|
|
|
-modules = {
|
|
|
+COMPAT_MODULES = {
|
|
|
"celery": {
|
|
|
+ "execute": {
|
|
|
+ "send_task": "send_task",
|
|
|
+ },
|
|
|
"decorators": {
|
|
|
"task": _compat_task_decorator,
|
|
|
"periodic_task": _compat_periodic_task_decorator,
|
|
@@ -53,7 +63,7 @@ modules = {
|
|
|
"TaskConsumer": "amqp.TaskConsumer",
|
|
|
"establish_connection": "broker_connection",
|
|
|
"with_connection": "with_default_connection",
|
|
|
- "get_consumer_set": "amqp.get_task_consumer"
|
|
|
+ "get_consumer_set": "amqp.get_task_consumer",
|
|
|
},
|
|
|
"registry": {
|
|
|
"tasks": "tasks",
|
|
@@ -62,27 +72,6 @@ modules = {
|
|
|
}
|
|
|
|
|
|
|
|
|
-def rgetattr(obj, path):
|
|
|
- return reduce(lambda a, b: getattr(a, b), [obj] + path)
|
|
|
-
|
|
|
-
|
|
|
-def get_compat(app, pkg, name, bases=(ModuleType, )):
|
|
|
- from warnings import warn
|
|
|
- from .exceptions import CDeprecationWarning
|
|
|
-
|
|
|
- fqdn = '.'.join([pkg.__name__, name])
|
|
|
- warn(CDeprecationWarning(MODULE_DEPRECATED % fqdn))
|
|
|
-
|
|
|
- def build_attr(attr):
|
|
|
- if isinstance(attr, basestring):
|
|
|
- return Proxy(rgetattr, (app, attr.split('.')))
|
|
|
- return attr
|
|
|
- attrs = dict((name, build_attr(attr))
|
|
|
- for name, attr in modules[pkg.__name__][name].iteritems())
|
|
|
- sys.modules[fqdn] = module = type(name, bases, attrs)(fqdn)
|
|
|
- return module
|
|
|
-
|
|
|
-
|
|
|
class class_property(object):
|
|
|
|
|
|
def __init__(self, fget=None, fset=None):
|
|
@@ -115,41 +104,64 @@ class MagicModule(ModuleType):
|
|
|
_compat_modules = ()
|
|
|
_all_by_module = {}
|
|
|
_direct = {}
|
|
|
+ _object_origins = {}
|
|
|
|
|
|
def __getattr__(self, name):
|
|
|
- origins = self._object_origins
|
|
|
- if name in origins:
|
|
|
- module = __import__(origins[name], None, None, [name])
|
|
|
- for extra_name in self._all_by_module[module.__name__]:
|
|
|
- setattr(self, extra_name, getattr(module, extra_name))
|
|
|
+ if name in self._object_origins:
|
|
|
+ module = __import__(self._object_origins[name], None, None, [name])
|
|
|
+ for item in self._all_by_module[module.__name__]:
|
|
|
+ setattr(self, item, getattr(module, item))
|
|
|
return getattr(module, name)
|
|
|
elif name in self._direct:
|
|
|
module = __import__(self._direct[name], None, None, [name])
|
|
|
setattr(self, name, module)
|
|
|
return module
|
|
|
- elif name in self._compat_modules:
|
|
|
- setattr(self, name, get_compat(self.current_app, self, name))
|
|
|
return ModuleType.__getattribute__(self, name)
|
|
|
|
|
|
def __dir__(self):
|
|
|
- return list(set(self.__all__
|
|
|
- + ("__file__", "__path__", "__doc__", "__all__")))
|
|
|
+ return list(set(self.__all__) + DEFAULT_ATTRS)
|
|
|
|
|
|
|
|
|
+def get_compat_module(pkg, name):
|
|
|
|
|
|
-def create_magic_module(name, compat_modules=(), by_module={}, direct={},
|
|
|
- base=MagicModule, **attrs):
|
|
|
- old_module = sys.modules[name]
|
|
|
+ def prepare(attr):
|
|
|
+ if isinstance(attr, basestring):
|
|
|
+ return Proxy(getappattr, (attr.split('.'), ))
|
|
|
+ return attr
|
|
|
+
|
|
|
+ return create_module(name, COMPAT_MODULES[pkg.__name__][name],
|
|
|
+ pkg=pkg, prepare_attr=prepare)
|
|
|
+
|
|
|
+
|
|
|
+def create_module(name, attrs, cls_attrs=None, pkg=None,
|
|
|
+ bases=(MagicModule, ), prepare_attr=None):
|
|
|
+ fqdn = '.'.join([pkg.__name__, name]) if pkg else name
|
|
|
+ cls_attrs = {} if cls_attrs is None else cls_attrs
|
|
|
+
|
|
|
+ attrs = dict((attr_name, prepare_attr(attr) if prepare_attr else attr)
|
|
|
+ for attr_name, attr in attrs.iteritems())
|
|
|
+ module = sys.modules[fqdn] = type(name, bases, cls_attrs)(fqdn)
|
|
|
+ module.__dict__.update(attrs)
|
|
|
+ return module
|
|
|
+
|
|
|
+
|
|
|
+def get_origins(defs):
|
|
|
origins = {}
|
|
|
- for module, items in by_module.iteritems():
|
|
|
- for item in items:
|
|
|
- origins[item] = module
|
|
|
+ for module, items in defs.iteritems():
|
|
|
+ origins.update(dict((item, module) for item in items))
|
|
|
+ return origins
|
|
|
+
|
|
|
+def recreate_module(name, compat_modules=(), by_module={}, direct={}, **attrs):
|
|
|
+ old_module = sys.modules[name]
|
|
|
+ origins = get_origins(by_module)
|
|
|
+ compat_modules = COMPAT_MODULES.get(name, ())
|
|
|
|
|
|
cattrs = dict(_compat_modules=compat_modules,
|
|
|
_all_by_module=by_module, _direct=direct,
|
|
|
_object_origins=origins,
|
|
|
__all__=tuple(set(reduce(operator.add, map(tuple, [
|
|
|
compat_modules, origins, direct, attrs])))))
|
|
|
- new_module = sys.modules[name] = type(name, (base, ), cattrs)(name)
|
|
|
- new_module.__dict__.update(attrs)
|
|
|
+ new_module = create_module(name, attrs, cls_attrs=cattrs)
|
|
|
+ new_module.__dict__.update(dict((mod, get_compat_module(new_module, mod))
|
|
|
+ for mod in compat_modules))
|
|
|
return old_module, new_module
|