瀏覽代碼

Implemented celery.config_from_object + .config_from_envvar.

Ask Solem 14 年之前
父節點
當前提交
1ca89298e6
共有 6 個文件被更改,包括 119 次插入35 次删除
  1. 3 2
      celery/app/__init__.py
  2. 9 1
      celery/app/base.py
  3. 34 0
      celery/datastructures.py
  4. 2 1
      celery/loaders/__init__.py
  5. 69 0
      celery/loaders/app.py
  6. 2 31
      celery/loaders/default.py

+ 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()(*args)
         return inner_create_task_cls(**options)
         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"):
 if os.environ.get("CELERY_TRACE_APP"):
     def app_or_default(app=None):
     def app_or_default(app=None):

+ 9 - 1
celery/app/base.py

@@ -69,9 +69,17 @@ class BaseApp(object):
     _log = None
     _log = None
 
 
     def __init__(self, loader=None, backend_cls=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
         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):
     def either(self, default_key, *values):
         for value in values:
         for value in values:
             if value is not None:
             if value is not None:

+ 34 - 0
celery/datastructures.py

@@ -23,6 +23,40 @@ class AttributeDict(dict):
         self[key] = value
         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):
 class PositionQueue(UserList):
     """A positional queue of a specific length, with slots that are either
     """A positional queue of a specific length, with slots that are either
     filled or unfilled. When all of the positions are filled, the queue
     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
 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"}
                   "django": "djcelery.loaders.DjangoLoader"}
 _loader = None
 _loader = None
 _settings = 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
 import warnings
 from importlib import import_module
 from importlib import import_module
 
 
+from celery.datastructures import AttributeDict
 from celery.loaders.base import BaseLoader
 from celery.loaders.base import BaseLoader
 from celery.exceptions import NotConfigured
 from celery.exceptions import NotConfigured
 
 
@@ -25,18 +26,6 @@ def wanted_module_item(item):
     return not item.startswith("_")
     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):
 class Loader(BaseLoader):
     """The default loader.
     """The default loader.
 
 
@@ -45,7 +34,7 @@ class Loader(BaseLoader):
     """
     """
 
 
     def setup_settings(self, settingsdict):
     def setup_settings(self, settingsdict):
-        settings = Settings(DEFAULT_SETTINGS, **settingsdict)
+        settings = AttributeDict(DEFAULT_SETTINGS, **settingsdict)
         installed_apps = set(list(DEFAULT_SETTINGS["INSTALLED_APPS"]) + \
         installed_apps = set(list(DEFAULT_SETTINGS["INSTALLED_APPS"]) + \
                              list(settings.INSTALLED_APPS))
                              list(settings.INSTALLED_APPS))
         settings.INSTALLED_APPS = tuple(installed_apps)
         settings.INSTALLED_APPS = tuple(installed_apps)
@@ -56,24 +45,6 @@ class Loader(BaseLoader):
 
 
         return settings
         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):
     def read_configuration(self):
         """Read configuration from ``celeryconfig.py`` and configure
         """Read configuration from ``celeryconfig.py`` and configure