Browse Source

New signals: app.on_configure, .on_after_configure, .on_after_finalize

Ask Solem 11 years ago
parent
commit
dba299a152
4 changed files with 43 additions and 16 deletions
  1. 25 5
      celery/app/base.py
  2. 10 2
      docs/reference/celery.rst
  3. 2 8
      funtests/stress/stress/app.py
  4. 6 1
      funtests/stress/stress/templates.py

+ 25 - 5
celery/app/base.py

@@ -34,6 +34,7 @@ from celery.exceptions import AlwaysEagerIgnored, ImproperlyConfigured
 from celery.five import items, values
 from celery.loaders import get_loader_cls
 from celery.local import PromiseProxy, maybe_evaluate
+from celery.utils.dispatch import Signal
 from celery.utils.functional import first, maybe_list
 from celery.utils.imports import instantiate, symbol_by_name
 from celery.utils.objects import mro_lookup
@@ -117,6 +118,15 @@ class Celery(object):
     _pool = None
     builtin_fixups = BUILTIN_FIXUPS
 
+    #: Signal sent when app is loading configuration.
+    on_configure = None
+
+    #: Signal sent after app has prepared the configuration.
+    on_after_configure = None
+
+    #: Signal sent after app has been finalized.
+    on_after_finalize = None
+
     def __init__(self, main=None, loader=None, backend=None,
                  amqp=None, events=None, log=None, control=None,
                  set_as_current=True, accept_magic_kwargs=False,
@@ -171,6 +181,13 @@ class Celery(object):
         if self.set_as_current:
             self.set_current()
 
+        # Signals
+        if self.on_configure is None:
+            # used to be a method pre 3.2
+            self.on_configure = Signal()
+        self.on_after_configure = Signal()
+        self.on_after_finalize = Signal()
+
         self.on_init()
         _register_app(self)
 
@@ -283,6 +300,8 @@ class Celery(object):
                 for task in values(self._tasks):
                     task.bind(self)
 
+                self.on_after_finalize.send(sender=self)
+
     def add_defaults(self, fun):
         if not callable(fun):
             d, fun = fun, lambda: d
@@ -455,12 +474,12 @@ class Celery(object):
             self.loader)
         return backend(app=self, url=url)
 
-    def on_configure(self):
-        """Callback calld when the app loads configuration"""
-        pass
-
     def _get_config(self):
-        self.on_configure()
+        if isinstance(self.on_configure, Signal):
+            self.on_configure.send(sender=self)
+        else:
+            # used to be a method pre 3.2
+            self.on_configure()
         if self._config_source:
             self.loader.config_from_object(self._config_source)
         self.configured = True
@@ -474,6 +493,7 @@ class Celery(object):
         if self._preconf:
             for key, value in items(self._preconf):
                 setattr(s, key, value)
+        self.on_after_configure.send(sender=self, source=s)
         return s
 
     def _after_fork(self, obj_):

+ 10 - 2
docs/reference/celery.rst

@@ -382,9 +382,17 @@ and creating Celery applications.
         Finalizes the app by loading built-in tasks,
         and evaluating pending task decorators
 
-    .. method:: Celery.on_configure()
+    .. signal:: on_configure
 
-        Optional callback for when the first time the configured is required.
+        Signal sent when app is loading configuration.
+
+    .. signal:: on_after_configure
+
+        Signal sent after app has prepared the configuration.
+
+    .. signal:: on_after_finalize
+
+        Signal sent after app has been finalized.
 
     .. attribute:: Celery.Pickler
 

+ 2 - 8
funtests/stress/stress/app.py

@@ -33,7 +33,7 @@ class App(Celery):
             )
         )
         signals.user_preload_options.connect(self.on_preload_parsed)
-        self.after_configure = None
+        self.on_configure.connect(self._maybe_use_default_template)
 
     def on_preload_parsed(self, options=None, **kwargs):
         self.use_template(options['template'])
@@ -44,13 +44,7 @@ class App(Celery):
         use_template(self, name)
         self.template_selected = True
 
-    def _get_config(self):
-        ret = super(App, self)._get_config()
-        if self.after_configure:
-            self.after_configure(ret)
-        return ret
-
-    def on_configure(self):
+    def _maybe_use_default_template(self, **kwargs):
         if not self.template_selected:
             self.use_template('default')
 

+ 6 - 1
funtests/stress/stress/templates.py

@@ -23,7 +23,12 @@ def template(name=None):
 
 def use_template(app, template='default'):
     template = template.split(',')
-    app.after_configure = partial(mixin_templates, template[1:])
+
+    # mixin the rest of the templates when the config is needed
+    @app.on_after_configure.connect
+    def load_template(sender, source, **kwargs):
+        mixin_templates(template[1:], source)
+
     app.config_from_object(templates[template[0]])