Pārlūkot izejas kodu

Implemented celery.config_from_object + .config_from_envvar.

Ask Solem 14 gadi atpakaļ
vecāks
revīzija
1ca89298e6

+ 3 - 2
celery/app/__init__.py

@@ -83,8 +83,9 @@ class App(base.BaseApp):
             return inner_create_task_cls()(*args)
         return inner_create_task_cls(**options)
 
-default_app = App()
-
+# The "default" loader is the default loader used by old applications.
+default_loader = os.environ.get("CELERY_LOADER") or "default"
+default_app = App(loader=default_loader)
 
 if os.environ.get("CELERY_TRACE_APP"):
     def app_or_default(app=None):

+ 9 - 1
celery/app/base.py

@@ -69,9 +69,17 @@ class BaseApp(object):
     _log = None
 
     def __init__(self, loader=None, backend_cls=None):
-        self.loader_cls = loader or os.environ.get("CELERY_LOADER", "default")
+        self.loader_cls = loader or "app"
         self.backend_cls = backend_cls
 
+    def config_from_object(self, obj, silent=False):
+        self._conf = None
+        return self.loader.config_from_object(obj, silent=silent)
+
+    def config_from_envvar(self, variable_name, silent=False):
+        self._conf = None
+        return self.loader.config_from_envvar(variable_name, silent=silent)
+
     def either(self, default_key, *values):
         for value in values:
             if value is not None:

+ 34 - 0
celery/datastructures.py

@@ -23,6 +23,40 @@ class AttributeDict(dict):
         self[key] = value
 
 
+class DictAttribute(object):
+
+    def __init__(self, obj):
+        self.obj = obj
+
+    def get(self, key, default=None):
+        try:
+            return self[key]
+        except KeyError:
+            return default
+
+    def setdefault(self, key, default):
+        try:
+            return self[key]
+        except KeyError:
+            self[key] = default
+            return default
+
+    def __getitem__(self, key):
+        try:
+            return getattr(self.obj, key)
+        except AttributeError:
+            raise KeyError(key)
+
+    def __setitem__(self, key, value):
+        setattr(self.obj, key, value)
+
+    def __contains__(self, key):
+        return hasattr(self.obj, key)
+
+    def iteritems(self):
+        return vars(self.obj).iteritems()
+
+
 class PositionQueue(UserList):
     """A positional queue of a specific length, with slots that are either
     filled or unfilled. When all of the positions are filled, the queue

+ 2 - 1
celery/loaders/__init__.py

@@ -2,7 +2,8 @@ import os
 
 from celery.utils import get_cls_by_name
 
-LOADER_ALIASES = {"default": "celery.loaders.default.Loader",
+LOADER_ALIASES = {"app": "celery.loaders.app.AppLoader",
+                  "default": "celery.loaders.default.Loader",
                   "django": "djcelery.loaders.DjangoLoader"}
 _loader = None
 _settings = None

+ 69 - 0
celery/loaders/app.py

@@ -0,0 +1,69 @@
+import os
+import sys
+
+from importlib import import_module
+
+from celery.datastructures import DictAttribute
+from celery.exceptions import ImproperlyConfigured
+from celery.loaders.base import BaseLoader
+
+
+ERROR_ENVVAR_NOT_SET = (
+"""The environment variable %r is not set,
+and as such the configuration could not be loaded.
+Please set this variable and make it point to
+a configuration module.""")
+
+
+class AppLoader(BaseLoader):
+
+    def __init__(self, *args, **kwargs):
+        self._conf = {}
+        super(AppLoader, self).__init__(*args, **kwargs)
+
+    def config_from_envvar(self, variable_name, silent=False):
+        module_name = os.environ.get(variable_name)
+        if not module_name:
+            if silent:
+                return False
+            raise ImproperlyConfigured(ERROR_ENVVAR_NOT_SET % (module_name, ))
+        return self.config_from_object(module_name, silent=silent)
+
+    def config_from_object(self, obj, silent=False):
+        if isinstance(obj, basestring):
+            try:
+                obj = self.import_from_cwd(obj)
+            except ImportError:
+                if silent:
+                    return False
+                raise
+        if not hasattr(obj, "__getitem__"):
+            obj = DictAttribute(obj)
+        self._conf = obj
+        return True
+
+    def on_worker_init(self):
+        self.import_default_modules()
+
+    def import_from_cwd(self, module, imp=import_module):
+        """Import module, but make sure it finds modules
+        located in the current directory.
+
+        Modules located in the current directory has
+        precedence over modules located in ``sys.path``.
+        """
+        cwd = os.getcwd()
+        if cwd in sys.path:
+            return imp(module)
+        sys.path.insert(0, cwd)
+        try:
+            return imp(module)
+        finally:
+            try:
+                sys.path.remove(cwd)
+            except ValueError:
+                pass
+
+    @property
+    def conf(self):
+        return self._conf

+ 2 - 31
celery/loaders/default.py

@@ -3,6 +3,7 @@ import sys
 import warnings
 from importlib import import_module
 
+from celery.datastructures import AttributeDict
 from celery.loaders.base import BaseLoader
 from celery.exceptions import NotConfigured
 
@@ -25,18 +26,6 @@ def wanted_module_item(item):
     return not item.startswith("_")
 
 
-class Settings(dict):
-
-    def __getattr__(self, key):
-        try:
-            return self[key]
-        except KeyError:
-            raise AttributeError(key)
-
-    def __setattr_(self, key, value):
-        self[key] = value
-
-
 class Loader(BaseLoader):
     """The default loader.
 
@@ -45,7 +34,7 @@ class Loader(BaseLoader):
     """
 
     def setup_settings(self, settingsdict):
-        settings = Settings(DEFAULT_SETTINGS, **settingsdict)
+        settings = AttributeDict(DEFAULT_SETTINGS, **settingsdict)
         installed_apps = set(list(DEFAULT_SETTINGS["INSTALLED_APPS"]) + \
                              list(settings.INSTALLED_APPS))
         settings.INSTALLED_APPS = tuple(installed_apps)
@@ -56,24 +45,6 @@ class Loader(BaseLoader):
 
         return settings
 
-    def import_from_cwd(self, module, imp=import_module):
-        """Import module, but make sure it finds modules
-        located in the current directory.
-
-        Modules located in the current directory has
-        precedence over modules located in ``sys.path``.
-        """
-        cwd = os.getcwd()
-        if cwd in sys.path:
-            return imp(module)
-        sys.path.insert(0, cwd)
-        try:
-            return imp(module)
-        finally:
-            try:
-                sys.path.remove(cwd)
-            except ValueError:
-                pass
 
     def read_configuration(self):
         """Read configuration from ``celeryconfig.py`` and configure