|  | @@ -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
 |