|
@@ -28,6 +28,7 @@ from warnings import warn
|
|
|
from .. import app as app_module
|
|
|
from .. import current_app
|
|
|
from .. import states, signals
|
|
|
+from ..app.task import BaseTask
|
|
|
from ..datastructures import ExceptionInfo
|
|
|
from ..exceptions import RetryTaskError
|
|
|
from ..utils.serialization import get_pickleable_exception
|
|
@@ -43,6 +44,27 @@ FAILURE = states.FAILURE
|
|
|
EXCEPTION_STATES = states.EXCEPTION_STATES
|
|
|
|
|
|
|
|
|
+def mro_lookup(cls, attr, stop=()):
|
|
|
+ """Returns the first node by MRO order that defines an attribute.
|
|
|
+
|
|
|
+ :keyword stop: A list of types that if reached will stop the search.
|
|
|
+
|
|
|
+ :returns None: if the attribute was not found.
|
|
|
+
|
|
|
+ """
|
|
|
+ for node in cls.mro():
|
|
|
+ if node in stop:
|
|
|
+ return
|
|
|
+ if attr in node.__dict__:
|
|
|
+ return node
|
|
|
+
|
|
|
+
|
|
|
+def defines_custom_call(task):
|
|
|
+ """Returns true if the task or one of its bases
|
|
|
+ defines __call__ (excluding the one in BaseTask)."""
|
|
|
+ return mro_lookup(task.__class__, "__call__", stop=(BaseTask, object))
|
|
|
+
|
|
|
+
|
|
|
class TraceInfo(object):
|
|
|
__slots__ = ("state", "retval", "exc_info",
|
|
|
"exc_type", "exc_value", "tb", "strtb")
|
|
@@ -106,6 +128,11 @@ class TraceInfo(object):
|
|
|
|
|
|
def build_tracer(name, task, loader=None, hostname=None, store_errors=True,
|
|
|
Info=TraceInfo, eager=False, propagate=False):
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ fun = task if defines_custom_call(task) else task.run
|
|
|
+
|
|
|
task = task or current_app.tasks[name]
|
|
|
loader = loader or current_app.loader
|
|
|
backend = task.backend
|
|
@@ -149,7 +176,7 @@ def build_tracer(name, task, loader=None, hostname=None, store_errors=True,
|
|
|
|
|
|
|
|
|
try:
|
|
|
- R = retval = task(*args, **kwargs)
|
|
|
+ R = retval = fun(*args, **kwargs)
|
|
|
state, einfo = SUCCESS, None
|
|
|
except RetryTaskError, exc:
|
|
|
I = Info(RETRY, exc, sys.exc_info())
|