Browse Source

Tasks Userguide: Added section about decorating tasks. Closes #224

Ask Solem 14 years ago
parent
commit
6b1bbb82ad
2 changed files with 71 additions and 1 deletions
  1. 7 1
      FAQ
  2. 64 0
      docs/userguide/tasks.rst

+ 7 - 1
FAQ

@@ -474,11 +474,17 @@ For more information see :ref:`task-request-info`.
 Can I specify a custom task_id?
 -------------------------------
 
-**Answer**: Yes. Use the ``task_id`` argument to
+**Answer**: Yes.  Use the ``task_id`` argument to
 :meth:`~celery.execute.apply_async`::
 
     >>> task.apply_async(args, kwargs, task_id="...")
 
+
+Can I use decorators with tasks?
+--------------------------------
+
+**Answer**: Yes.  But please see note at :ref:`tasks-decorating`.
+
 .. _faq-natural-task-ids:
 
 Can I use natural task ids?

+ 64 - 0
docs/userguide/tasks.rst

@@ -417,6 +417,70 @@ add the project directory to the Python path::
 
 This makes more sense from the reusable app perspective anyway.
 
+.. tasks-decorating:
+
+Decorating tasks
+================
+
+Using decorators with tasks requires extra steps because of the magic keyword
+arguments.
+
+If you have the following task and decorator:
+
+.. code-block:: python
+
+    from celery.utils.functional import wraps
+
+    def decorator(task):
+
+        @wraps(task)
+        def _decorated(*args, **kwargs):
+            print("inside decorator")
+            return task(*args, **kwargs)
+
+
+    @decorator
+    @task
+    def add(x, y):
+        return x + y
+
+Then the worker will see that the task is accepting keyword arguments,
+while it really doesn't, resulting in an error.
+
+The workaround is to either have your task accept arbitrary keyword
+arguments:
+
+.. code-block:: python
+
+    @decorator
+    @task
+    def add(x, y, **kwargs):
+        return x + y
+
+or patch the decorator to preserve the original signature:
+
+.. code-block:: python
+
+    from inspect import getargspec
+    from celery.utils.functional import wraps
+
+    def decorator(task):
+
+        @wraps(task)
+        def _decorated(*args, **kwargs):
+            print("in decorator")
+            return task(*args, **kwargs)
+        _decorated.argspec = inspect.getargspec(task)
+
+Also note the use of :func:`~celery.utils.functional.wraps` here,
+this is necessary to keep the original function name and docstring.
+
+.. note::
+
+    The magic keyword arguments will be deprecated in the future,
+    replaced by the ``task.request`` attribute in 2.2, and the
+    keyword arguments will be removed in 3.0.
+
 .. _task-states:
 
 Task States