|
@@ -12,14 +12,21 @@ from collections import MutableSequence, deque
|
|
|
from copy import deepcopy
|
|
from copy import deepcopy
|
|
|
from functools import partial as _partial, reduce
|
|
from functools import partial as _partial, reduce
|
|
|
from operator import itemgetter
|
|
from operator import itemgetter
|
|
|
|
|
+from typing import (
|
|
|
|
|
+ Any, Callable, Dict, Iterable, Iterator,
|
|
|
|
|
+ List, Mapping, Sequence, Tuple, Optional,
|
|
|
|
|
+ cast,
|
|
|
|
|
+)
|
|
|
|
|
|
|
|
|
|
+from kombu.types import ConnectionT, ProducerT
|
|
|
from kombu.utils.functional import fxrange, reprcall
|
|
from kombu.utils.functional import fxrange, reprcall
|
|
|
from kombu.utils.objects import cached_property
|
|
from kombu.utils.objects import cached_property
|
|
|
from kombu.utils.uuid import uuid
|
|
from kombu.utils.uuid import uuid
|
|
|
-from vine import barrier
|
|
|
|
|
|
|
+from vine import Thenable, barrier
|
|
|
|
|
|
|
|
from celery._state import current_app
|
|
from celery._state import current_app
|
|
|
from celery.result import GroupResult
|
|
from celery.result import GroupResult
|
|
|
|
|
+from celery.types import AppT, ResultT, RouterT, SignatureT, TaskT
|
|
|
from celery.utils import abstract
|
|
from celery.utils import abstract
|
|
|
from celery.utils.functional import (
|
|
from celery.utils.functional import (
|
|
|
maybe_list, is_list, _regen, regen, chunks as _chunks,
|
|
maybe_list, is_list, _regen, regen, chunks as _chunks,
|
|
@@ -34,7 +41,7 @@ __all__ = [
|
|
|
]
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
-def maybe_unroll_group(g):
|
|
|
|
|
|
|
+def maybe_unroll_group(g: SignatureT) -> Any:
|
|
|
"""Unroll group with only one member."""
|
|
"""Unroll group with only one member."""
|
|
|
# Issue #1656
|
|
# Issue #1656
|
|
|
try:
|
|
try:
|
|
@@ -50,11 +57,11 @@ def maybe_unroll_group(g):
|
|
|
return g.tasks[0] if size == 1 else g
|
|
return g.tasks[0] if size == 1 else g
|
|
|
|
|
|
|
|
|
|
|
|
|
-def task_name_from(task):
|
|
|
|
|
|
|
+def task_name_from(task: Any) -> str:
|
|
|
return getattr(task, 'name', task)
|
|
return getattr(task, 'name', task)
|
|
|
|
|
|
|
|
|
|
|
|
|
-def _upgrade(fields, sig):
|
|
|
|
|
|
|
+def _upgrade(fields: Mapping, sig: SignatureT) -> SignatureT:
|
|
|
"""Used by custom signatures in .from_dict, to keep common fields."""
|
|
"""Used by custom signatures in .from_dict, to keep common fields."""
|
|
|
sig.update(chord_size=fields.get('chord_size'))
|
|
sig.update(chord_size=fields.get('chord_size'))
|
|
|
return sig
|
|
return sig
|
|
@@ -118,17 +125,18 @@ class Signature(dict):
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
TYPES = {}
|
|
TYPES = {}
|
|
|
- _app = _type = None
|
|
|
|
|
|
|
+ _app: AppT = None
|
|
|
|
|
+ _type: TaskT = None
|
|
|
|
|
|
|
|
@classmethod
|
|
@classmethod
|
|
|
- def register_type(cls, name=None):
|
|
|
|
|
- def _inner(subclass):
|
|
|
|
|
|
|
+ def register_type(cls, name: str = None) -> Callable:
|
|
|
|
|
+ def _inner(subclass: type) -> type:
|
|
|
cls.TYPES[name or subclass.__name__] = subclass
|
|
cls.TYPES[name or subclass.__name__] = subclass
|
|
|
return subclass
|
|
return subclass
|
|
|
return _inner
|
|
return _inner
|
|
|
|
|
|
|
|
@classmethod
|
|
@classmethod
|
|
|
- def from_dict(cls, d, app=None):
|
|
|
|
|
|
|
+ def from_dict(cls, d: Mapping, app: AppT = None) -> SignatureT:
|
|
|
typ = d.get('subtask_type')
|
|
typ = d.get('subtask_type')
|
|
|
if typ:
|
|
if typ:
|
|
|
target_cls = cls.TYPES[typ]
|
|
target_cls = cls.TYPES[typ]
|
|
@@ -136,9 +144,16 @@ class Signature(dict):
|
|
|
return target_cls.from_dict(d, app=app)
|
|
return target_cls.from_dict(d, app=app)
|
|
|
return Signature(d, app=app)
|
|
return Signature(d, app=app)
|
|
|
|
|
|
|
|
- def __init__(self, task=None, args=None, kwargs=None, options=None,
|
|
|
|
|
- type=None, subtask_type=None, immutable=False,
|
|
|
|
|
- app=None, **ex):
|
|
|
|
|
|
|
+ def __init__(self,
|
|
|
|
|
+ task: str = None,
|
|
|
|
|
+ args: Sequence = None,
|
|
|
|
|
+ kwargs: Mapping = None,
|
|
|
|
|
+ options: Mapping = None,
|
|
|
|
|
+ type: TaskT = None,
|
|
|
|
|
+ subtask_type: str = None,
|
|
|
|
|
+ immutable: bool = False,
|
|
|
|
|
+ app: AppT = None,
|
|
|
|
|
+ **ex) -> None:
|
|
|
self._app = app
|
|
self._app = app
|
|
|
|
|
|
|
|
if isinstance(task, dict):
|
|
if isinstance(task, dict):
|
|
@@ -161,16 +176,17 @@ class Signature(dict):
|
|
|
chord_size=None,
|
|
chord_size=None,
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- def __call__(self, *partial_args, **partial_kwargs):
|
|
|
|
|
|
|
+ def __call__(self, *partial_args, **partial_kwargs) -> Any:
|
|
|
"""Call the task directly (in the current process)."""
|
|
"""Call the task directly (in the current process)."""
|
|
|
args, kwargs, _ = self._merge(partial_args, partial_kwargs, None)
|
|
args, kwargs, _ = self._merge(partial_args, partial_kwargs, None)
|
|
|
return self.type(*args, **kwargs)
|
|
return self.type(*args, **kwargs)
|
|
|
|
|
|
|
|
- def delay(self, *partial_args, **partial_kwargs):
|
|
|
|
|
|
|
+ def delay(self, *partial_args, **partial_kwargs) -> ResultT:
|
|
|
"""Shortcut to :meth:`apply_async` using star arguments."""
|
|
"""Shortcut to :meth:`apply_async` using star arguments."""
|
|
|
return self.apply_async(partial_args, partial_kwargs)
|
|
return self.apply_async(partial_args, partial_kwargs)
|
|
|
|
|
|
|
|
- def apply(self, args=(), kwargs={}, **options):
|
|
|
|
|
|
|
+ def apply(self, args: Sequence = (), kwargs: Mapping = {},
|
|
|
|
|
+ **options) -> ResultT:
|
|
|
"""Call task locally.
|
|
"""Call task locally.
|
|
|
|
|
|
|
|
Same as :meth:`apply_async` but executed the task inline instead
|
|
Same as :meth:`apply_async` but executed the task inline instead
|
|
@@ -180,7 +196,11 @@ class Signature(dict):
|
|
|
args, kwargs, options = self._merge(args, kwargs, options)
|
|
args, kwargs, options = self._merge(args, kwargs, options)
|
|
|
return self.type.apply(args, kwargs, **options)
|
|
return self.type.apply(args, kwargs, **options)
|
|
|
|
|
|
|
|
- def apply_async(self, args=(), kwargs={}, route_name=None, **options):
|
|
|
|
|
|
|
+ def apply_async(self,
|
|
|
|
|
+ args: Sequence = (),
|
|
|
|
|
+ kwargs: Mapping = {},
|
|
|
|
|
+ route_name: str = None,
|
|
|
|
|
+ **options) -> None:
|
|
|
"""Apply this task asynchronously.
|
|
"""Apply this task asynchronously.
|
|
|
|
|
|
|
|
Arguments:
|
|
Arguments:
|
|
@@ -209,7 +229,10 @@ class Signature(dict):
|
|
|
# Borks on this, as it's a property
|
|
# Borks on this, as it's a property
|
|
|
return _apply(args, kwargs, **options)
|
|
return _apply(args, kwargs, **options)
|
|
|
|
|
|
|
|
- def _merge(self, args=(), kwargs={}, options={}, force=False):
|
|
|
|
|
|
|
+ def _merge(self, args: Sequence = (),
|
|
|
|
|
+ kwargs: Mapping = {},
|
|
|
|
|
+ options: Mapping = {},
|
|
|
|
|
+ force: bool = False) -> Tuple[Tuple, Dict, Dict]:
|
|
|
if self.immutable and not force:
|
|
if self.immutable and not force:
|
|
|
return (self.args, self.kwargs,
|
|
return (self.args, self.kwargs,
|
|
|
dict(self.options, **options) if options else self.options)
|
|
dict(self.options, **options) if options else self.options)
|
|
@@ -217,7 +240,10 @@ class Signature(dict):
|
|
|
dict(self.kwargs, **kwargs) if kwargs else self.kwargs,
|
|
dict(self.kwargs, **kwargs) if kwargs else self.kwargs,
|
|
|
dict(self.options, **options) if options else self.options)
|
|
dict(self.options, **options) if options else self.options)
|
|
|
|
|
|
|
|
- def clone(self, args=(), kwargs={}, **opts):
|
|
|
|
|
|
|
+ def clone(self,
|
|
|
|
|
+ args: Sequence = (),
|
|
|
|
|
+ kwargs: Mapping = {},
|
|
|
|
|
+ **opts) -> SignatureT:
|
|
|
"""Create a copy of this signature.
|
|
"""Create a copy of this signature.
|
|
|
|
|
|
|
|
Arguments:
|
|
Arguments:
|
|
@@ -240,8 +266,13 @@ class Signature(dict):
|
|
|
return s
|
|
return s
|
|
|
partial = clone
|
|
partial = clone
|
|
|
|
|
|
|
|
- def freeze(self, _id=None, group_id=None, chord=None,
|
|
|
|
|
- root_id=None, parent_id=None):
|
|
|
|
|
|
|
+ def freeze(self,
|
|
|
|
|
+ _id: str = None,
|
|
|
|
|
+ *,
|
|
|
|
|
+ group_id: str = None,
|
|
|
|
|
+ chord: SignatureT = None,
|
|
|
|
|
+ root_id: str = None,
|
|
|
|
|
+ parent_id: str = None) -> ResultT:
|
|
|
"""Finalize the signature by adding a concrete task id.
|
|
"""Finalize the signature by adding a concrete task id.
|
|
|
|
|
|
|
|
The task won't be called and you shouldn't call the signature
|
|
The task won't be called and you shouldn't call the signature
|
|
@@ -273,7 +304,10 @@ class Signature(dict):
|
|
|
return self.AsyncResult(tid)
|
|
return self.AsyncResult(tid)
|
|
|
_freeze = freeze
|
|
_freeze = freeze
|
|
|
|
|
|
|
|
- def replace(self, args=None, kwargs=None, options=None):
|
|
|
|
|
|
|
+ def replace(self,
|
|
|
|
|
+ args: Sequence = None,
|
|
|
|
|
+ kwargs: Mapping = None,
|
|
|
|
|
+ options: Mapping = None) -> SignatureT:
|
|
|
"""Replace the args, kwargs or options set for this signature.
|
|
"""Replace the args, kwargs or options set for this signature.
|
|
|
|
|
|
|
|
These are only replaced if the argument for the section is
|
|
These are only replaced if the argument for the section is
|
|
@@ -288,7 +322,7 @@ class Signature(dict):
|
|
|
s.options = options
|
|
s.options = options
|
|
|
return s
|
|
return s
|
|
|
|
|
|
|
|
- def set(self, immutable=None, **options):
|
|
|
|
|
|
|
+ def set(self, immutable: bool = None, **options) -> SignatureT:
|
|
|
"""Set arbitrary execution options (same as ``.options.update(…)``).
|
|
"""Set arbitrary execution options (same as ``.options.update(…)``).
|
|
|
|
|
|
|
|
Returns:
|
|
Returns:
|
|
@@ -300,44 +334,45 @@ class Signature(dict):
|
|
|
self.options.update(options)
|
|
self.options.update(options)
|
|
|
return self
|
|
return self
|
|
|
|
|
|
|
|
- def set_immutable(self, immutable):
|
|
|
|
|
|
|
+ def set_immutable(self, immutable: bool) -> None:
|
|
|
self.immutable = immutable
|
|
self.immutable = immutable
|
|
|
|
|
|
|
|
- def _with_list_option(self, key):
|
|
|
|
|
|
|
+ def _with_list_option(self, key: str) -> Any:
|
|
|
items = self.options.setdefault(key, [])
|
|
items = self.options.setdefault(key, [])
|
|
|
if not isinstance(items, MutableSequence):
|
|
if not isinstance(items, MutableSequence):
|
|
|
items = self.options[key] = [items]
|
|
items = self.options[key] = [items]
|
|
|
return items
|
|
return items
|
|
|
|
|
|
|
|
- def append_to_list_option(self, key, value):
|
|
|
|
|
|
|
+ def append_to_list_option(self, key: str, value: Any) -> Any:
|
|
|
items = self._with_list_option(key)
|
|
items = self._with_list_option(key)
|
|
|
if value not in items:
|
|
if value not in items:
|
|
|
items.append(value)
|
|
items.append(value)
|
|
|
return value
|
|
return value
|
|
|
|
|
|
|
|
- def extend_list_option(self, key, value):
|
|
|
|
|
|
|
+ def extend_list_option(self, key: str, value: Any) -> None:
|
|
|
items = self._with_list_option(key)
|
|
items = self._with_list_option(key)
|
|
|
items.extend(maybe_list(value))
|
|
items.extend(maybe_list(value))
|
|
|
|
|
|
|
|
- def link(self, callback):
|
|
|
|
|
|
|
+ def link(self, callback: SignatureT) -> SignatureT:
|
|
|
"""Add callback task to be applied if this task succeeds.
|
|
"""Add callback task to be applied if this task succeeds.
|
|
|
|
|
|
|
|
Returns:
|
|
Returns:
|
|
|
Signature: the argument passed, for chaining
|
|
Signature: the argument passed, for chaining
|
|
|
or use with :func:`~functools.reduce`.
|
|
or use with :func:`~functools.reduce`.
|
|
|
"""
|
|
"""
|
|
|
- return self.append_to_list_option('link', callback)
|
|
|
|
|
|
|
+ return cast(SignatureT, self.append_to_list_option('link', callback))
|
|
|
|
|
|
|
|
- def link_error(self, errback):
|
|
|
|
|
|
|
+ def link_error(self, errback: SignatureT) -> SignatureT:
|
|
|
"""Add callback task to be applied on error in task execution.
|
|
"""Add callback task to be applied on error in task execution.
|
|
|
|
|
|
|
|
Returns:
|
|
Returns:
|
|
|
Signature: the argument passed, for chaining
|
|
Signature: the argument passed, for chaining
|
|
|
or use with :func:`~functools.reduce`.
|
|
or use with :func:`~functools.reduce`.
|
|
|
"""
|
|
"""
|
|
|
- return self.append_to_list_option('link_error', errback)
|
|
|
|
|
|
|
+ return cast(SignatureT,
|
|
|
|
|
+ self.append_to_list_option('link_error', errback))
|
|
|
|
|
|
|
|
- def on_error(self, errback):
|
|
|
|
|
|
|
+ def on_error(self, errback: SignatureT) -> SignatureT:
|
|
|
"""Version of :meth:`link_error` that supports chaining.
|
|
"""Version of :meth:`link_error` that supports chaining.
|
|
|
|
|
|
|
|
on_error chains the original signature, not the errback so::
|
|
on_error chains the original signature, not the errback so::
|
|
@@ -350,7 +385,7 @@ class Signature(dict):
|
|
|
self.link_error(errback)
|
|
self.link_error(errback)
|
|
|
return self
|
|
return self
|
|
|
|
|
|
|
|
- def flatten_links(self):
|
|
|
|
|
|
|
+ def flatten_links(self) -> List[SignatureT]:
|
|
|
"""Return a recursive list of dependencies.
|
|
"""Return a recursive list of dependencies.
|
|
|
|
|
|
|
|
"unchain" if you will, but with links intact.
|
|
"unchain" if you will, but with links intact.
|
|
@@ -361,7 +396,7 @@ class Signature(dict):
|
|
|
for link in maybe_list(self.options.get('link')) or [])
|
|
for link in maybe_list(self.options.get('link')) or [])
|
|
|
)))
|
|
)))
|
|
|
|
|
|
|
|
- def __or__(self, other):
|
|
|
|
|
|
|
+ def __or__(self, other: SignatureT) -> SignatureT:
|
|
|
# These could be implemented in each individual class,
|
|
# These could be implemented in each individual class,
|
|
|
# I'm sure, but for now we have this.
|
|
# I'm sure, but for now we have this.
|
|
|
if isinstance(other, chord) and len(other.tasks) == 1:
|
|
if isinstance(other, chord) and len(other.tasks) == 1:
|
|
@@ -431,7 +466,7 @@ class Signature(dict):
|
|
|
return _chain(self, other, app=self._app)
|
|
return _chain(self, other, app=self._app)
|
|
|
return NotImplemented
|
|
return NotImplemented
|
|
|
|
|
|
|
|
- def election(self):
|
|
|
|
|
|
|
+ def election(self) -> ResultT:
|
|
|
type = self.type
|
|
type = self.type
|
|
|
app = type.app
|
|
app = type.app
|
|
|
tid = self.options.get('task_id') or uuid()
|
|
tid = self.options.get('task_id') or uuid()
|
|
@@ -442,50 +477,50 @@ class Signature(dict):
|
|
|
connection=P.connection)
|
|
connection=P.connection)
|
|
|
return type.AsyncResult(tid)
|
|
return type.AsyncResult(tid)
|
|
|
|
|
|
|
|
- def reprcall(self, *args, **kwargs):
|
|
|
|
|
|
|
+ def reprcall(self, *args, **kwargs) -> str:
|
|
|
args, kwargs, _ = self._merge(args, kwargs, {}, force=True)
|
|
args, kwargs, _ = self._merge(args, kwargs, {}, force=True)
|
|
|
return reprcall(self['task'], args, kwargs)
|
|
return reprcall(self['task'], args, kwargs)
|
|
|
|
|
|
|
|
- def __deepcopy__(self, memo):
|
|
|
|
|
|
|
+ def __deepcopy__(self, memo) -> SignatureT:
|
|
|
memo[id(self)] = self
|
|
memo[id(self)] = self
|
|
|
return dict(self)
|
|
return dict(self)
|
|
|
|
|
|
|
|
- def __invert__(self):
|
|
|
|
|
|
|
+ def __invert__(self) -> Any:
|
|
|
return self.apply_async().get()
|
|
return self.apply_async().get()
|
|
|
|
|
|
|
|
- def __reduce__(self):
|
|
|
|
|
|
|
+ def __reduce__(self) -> Tuple:
|
|
|
# for serialization, the task type is lazily loaded,
|
|
# for serialization, the task type is lazily loaded,
|
|
|
# and not stored in the dict itself.
|
|
# and not stored in the dict itself.
|
|
|
return signature, (dict(self),)
|
|
return signature, (dict(self),)
|
|
|
|
|
|
|
|
- def __json__(self):
|
|
|
|
|
|
|
+ def __json__(self) -> Any:
|
|
|
return dict(self)
|
|
return dict(self)
|
|
|
|
|
|
|
|
- def __repr__(self):
|
|
|
|
|
|
|
+ def __repr__(self) -> str:
|
|
|
return self.reprcall()
|
|
return self.reprcall()
|
|
|
|
|
|
|
|
@property
|
|
@property
|
|
|
- def name(self):
|
|
|
|
|
|
|
+ def name(self) -> str:
|
|
|
# for duck typing compatibility with Task.name
|
|
# for duck typing compatibility with Task.name
|
|
|
return self.task
|
|
return self.task
|
|
|
|
|
|
|
|
@cached_property
|
|
@cached_property
|
|
|
- def type(self):
|
|
|
|
|
|
|
+ def type(self) -> TaskT:
|
|
|
return self._type or self.app.tasks[self['task']]
|
|
return self._type or self.app.tasks[self['task']]
|
|
|
|
|
|
|
|
@cached_property
|
|
@cached_property
|
|
|
- def app(self):
|
|
|
|
|
|
|
+ def app(self) -> AppT:
|
|
|
return self._app or current_app
|
|
return self._app or current_app
|
|
|
|
|
|
|
|
@cached_property
|
|
@cached_property
|
|
|
- def AsyncResult(self):
|
|
|
|
|
|
|
+ def AsyncResult(self) -> type:
|
|
|
try:
|
|
try:
|
|
|
return self.type.AsyncResult
|
|
return self.type.AsyncResult
|
|
|
except KeyError: # task not registered
|
|
except KeyError: # task not registered
|
|
|
return self.app.AsyncResult
|
|
return self.app.AsyncResult
|
|
|
|
|
|
|
|
@cached_property
|
|
@cached_property
|
|
|
- def _apply_async(self):
|
|
|
|
|
|
|
+ def _apply_async(self) -> Callable:
|
|
|
try:
|
|
try:
|
|
|
return self.type.apply_async
|
|
return self.type.apply_async
|
|
|
except KeyError:
|
|
except KeyError:
|
|
@@ -509,7 +544,7 @@ class _chain(Signature):
|
|
|
tasks = getitem_property('kwargs.tasks', 'Tasks in chain.')
|
|
tasks = getitem_property('kwargs.tasks', 'Tasks in chain.')
|
|
|
|
|
|
|
|
@classmethod
|
|
@classmethod
|
|
|
- def from_dict(cls, d, app=None):
|
|
|
|
|
|
|
+ def from_dict(cls, d: Mapping, app: AppT = None) -> SignatureT:
|
|
|
tasks = d['kwargs']['tasks']
|
|
tasks = d['kwargs']['tasks']
|
|
|
if tasks:
|
|
if tasks:
|
|
|
if isinstance(tasks, tuple): # aaaargh
|
|
if isinstance(tasks, tuple): # aaaargh
|
|
@@ -518,7 +553,7 @@ class _chain(Signature):
|
|
|
tasks[0] = maybe_signature(tasks[0], app=app)
|
|
tasks[0] = maybe_signature(tasks[0], app=app)
|
|
|
return _upgrade(d, _chain(tasks, app=app, **d['options']))
|
|
return _upgrade(d, _chain(tasks, app=app, **d['options']))
|
|
|
|
|
|
|
|
- def __init__(self, *tasks, **options):
|
|
|
|
|
|
|
+ def __init__(self, *tasks, **options) -> None:
|
|
|
tasks = (regen(tasks[0]) if len(tasks) == 1 and is_list(tasks[0])
|
|
tasks = (regen(tasks[0]) if len(tasks) == 1 and is_list(tasks[0])
|
|
|
else tasks)
|
|
else tasks)
|
|
|
Signature.__init__(
|
|
Signature.__init__(
|
|
@@ -528,11 +563,11 @@ class _chain(Signature):
|
|
|
self.subtask_type = 'chain'
|
|
self.subtask_type = 'chain'
|
|
|
self._frozen = None
|
|
self._frozen = None
|
|
|
|
|
|
|
|
- def __call__(self, *args, **kwargs):
|
|
|
|
|
|
|
+ def __call__(self, *args, **kwargs) -> Any:
|
|
|
if self.tasks:
|
|
if self.tasks:
|
|
|
return self.apply_async(args, kwargs)
|
|
return self.apply_async(args, kwargs)
|
|
|
|
|
|
|
|
- def clone(self, *args, **kwargs):
|
|
|
|
|
|
|
+ def clone(self, *args, **kwargs) -> SignatureT:
|
|
|
to_signature = maybe_signature
|
|
to_signature = maybe_signature
|
|
|
s = Signature.clone(self, *args, **kwargs)
|
|
s = Signature.clone(self, *args, **kwargs)
|
|
|
s.kwargs['tasks'] = [
|
|
s.kwargs['tasks'] = [
|
|
@@ -541,7 +576,10 @@ class _chain(Signature):
|
|
|
]
|
|
]
|
|
|
return s
|
|
return s
|
|
|
|
|
|
|
|
- def apply_async(self, args=(), kwargs={}, **options):
|
|
|
|
|
|
|
+ def apply_async(self,
|
|
|
|
|
+ args: Sequence = (),
|
|
|
|
|
+ kwargs: Mapping = {},
|
|
|
|
|
+ **options) -> ResultT:
|
|
|
# python is best at unpacking kwargs, so .run is here to do that.
|
|
# python is best at unpacking kwargs, so .run is here to do that.
|
|
|
app = self.app
|
|
app = self.app
|
|
|
if app.conf.task_always_eager:
|
|
if app.conf.task_always_eager:
|
|
@@ -549,9 +587,19 @@ class _chain(Signature):
|
|
|
return self.run(args, kwargs, app=app, **(
|
|
return self.run(args, kwargs, app=app, **(
|
|
|
dict(self.options, **options) if options else self.options))
|
|
dict(self.options, **options) if options else self.options))
|
|
|
|
|
|
|
|
- def run(self, args=(), kwargs={}, group_id=None, chord=None,
|
|
|
|
|
- task_id=None, link=None, link_error=None,
|
|
|
|
|
- producer=None, root_id=None, parent_id=None, app=None, **options):
|
|
|
|
|
|
|
+ def run(self,
|
|
|
|
|
+ args: Sequence = (),
|
|
|
|
|
+ kwargs: Mapping = {},
|
|
|
|
|
+ group_id: str = None,
|
|
|
|
|
+ chord: SignatureT = None,
|
|
|
|
|
+ task_id: str = None,
|
|
|
|
|
+ link: Sequence[SignatureT] = None,
|
|
|
|
|
+ link_error: Sequence[SignatureT] = None,
|
|
|
|
|
+ producer: ProducerT = None,
|
|
|
|
|
+ root_id: str = None,
|
|
|
|
|
+ parent_id: str = None,
|
|
|
|
|
+ app: AppT = None,
|
|
|
|
|
+ **options) -> ResultT:
|
|
|
# pylint: disable=redefined-outer-name
|
|
# pylint: disable=redefined-outer-name
|
|
|
# XXX chord is also a class in outer scope.
|
|
# XXX chord is also a class in outer scope.
|
|
|
app = app or self.app
|
|
app = app or self.app
|
|
@@ -580,8 +628,13 @@ class _chain(Signature):
|
|
|
first_task.apply_async(**options)
|
|
first_task.apply_async(**options)
|
|
|
return results[0]
|
|
return results[0]
|
|
|
|
|
|
|
|
- def freeze(self, _id=None, group_id=None, chord=None,
|
|
|
|
|
- root_id=None, parent_id=None):
|
|
|
|
|
|
|
+ def freeze(self,
|
|
|
|
|
+ _id: str = None,
|
|
|
|
|
+ *,
|
|
|
|
|
+ group_id: str = None,
|
|
|
|
|
+ chord: SignatureT = None,
|
|
|
|
|
+ root_id: str = None,
|
|
|
|
|
+ parent_id: str = None) -> ResultT:
|
|
|
# pylint: disable=redefined-outer-name
|
|
# pylint: disable=redefined-outer-name
|
|
|
# XXX chord is also a class in outer scope.
|
|
# XXX chord is also a class in outer scope.
|
|
|
_, results = self._frozen = self.prepare_steps(
|
|
_, results = self._frozen = self.prepare_steps(
|
|
@@ -590,10 +643,17 @@ class _chain(Signature):
|
|
|
)
|
|
)
|
|
|
return results[0]
|
|
return results[0]
|
|
|
|
|
|
|
|
- def prepare_steps(self, args, tasks,
|
|
|
|
|
- root_id=None, parent_id=None, link_error=None, app=None,
|
|
|
|
|
- last_task_id=None, group_id=None, chord_body=None,
|
|
|
|
|
- clone=True, from_dict=Signature.from_dict):
|
|
|
|
|
|
|
+ def prepare_steps(self, args: Sequence, tasks: Sequence[SignatureT],
|
|
|
|
|
+ root_id: str = None,
|
|
|
|
|
+ parent_id: str = None,
|
|
|
|
|
+ link_error: Sequence[SignatureT] = None,
|
|
|
|
|
+ app: AppT = None,
|
|
|
|
|
+ last_task_id: str = None,
|
|
|
|
|
+ group_id: str = None,
|
|
|
|
|
+ chord_body: SignatureT = None,
|
|
|
|
|
+ clone: bool = True,
|
|
|
|
|
+ from_dict: Callable = Signature.from_dict
|
|
|
|
|
+ ) -> Tuple[Sequence[SignatureT], Sequence[ResultT]]:
|
|
|
app = app or self.app
|
|
app = app or self.app
|
|
|
# use chain message field for protocol 2 and later.
|
|
# use chain message field for protocol 2 and later.
|
|
|
# this avoids pickle blowing the stack on the recursion
|
|
# this avoids pickle blowing the stack on the recursion
|
|
@@ -693,7 +753,10 @@ class _chain(Signature):
|
|
|
prev_res = node
|
|
prev_res = node
|
|
|
return tasks, results
|
|
return tasks, results
|
|
|
|
|
|
|
|
- def apply(self, args=(), kwargs={}, **options):
|
|
|
|
|
|
|
+ def apply(self,
|
|
|
|
|
+ args: Sequence = (),
|
|
|
|
|
+ kwargs: Mapping = {},
|
|
|
|
|
+ **options) -> ResultT:
|
|
|
last, fargs = None, args
|
|
last, fargs = None, args
|
|
|
for task in self.tasks:
|
|
for task in self.tasks:
|
|
|
res = task.clone(fargs).apply(
|
|
res = task.clone(fargs).apply(
|
|
@@ -702,7 +765,7 @@ class _chain(Signature):
|
|
|
return last
|
|
return last
|
|
|
|
|
|
|
|
@property
|
|
@property
|
|
|
- def app(self):
|
|
|
|
|
|
|
+ def app(self) -> AppT:
|
|
|
app = self._app
|
|
app = self._app
|
|
|
if app is None:
|
|
if app is None:
|
|
|
try:
|
|
try:
|
|
@@ -711,7 +774,7 @@ class _chain(Signature):
|
|
|
pass
|
|
pass
|
|
|
return app or current_app
|
|
return app or current_app
|
|
|
|
|
|
|
|
- def __repr__(self):
|
|
|
|
|
|
|
+ def __repr__(self) -> str:
|
|
|
if not self.tasks:
|
|
if not self.tasks:
|
|
|
return '<{0}@{1:#x}: empty>'.format(
|
|
return '<{0}@{1:#x}: empty>'.format(
|
|
|
type(self).__name__, id(self))
|
|
type(self).__name__, id(self))
|
|
@@ -769,7 +832,7 @@ class chain(_chain):
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
# could be function, but must be able to reference as :class:`chain`.
|
|
# could be function, but must be able to reference as :class:`chain`.
|
|
|
- def __new__(cls, *tasks, **kwargs):
|
|
|
|
|
|
|
+ def __new__(cls, *tasks, **kwargs) -> SignatureT:
|
|
|
# This forces `chain(X, Y, Z)` to work the same way as `X | Y | Z`
|
|
# This forces `chain(X, Y, Z)` to work the same way as `X | Y | Z`
|
|
|
if not kwargs and tasks:
|
|
if not kwargs and tasks:
|
|
|
if len(tasks) == 1 and is_list(tasks[0]):
|
|
if len(tasks) == 1 and is_list(tasks[0]):
|
|
@@ -784,18 +847,21 @@ class _basemap(Signature):
|
|
|
_unpack_args = itemgetter('task', 'it')
|
|
_unpack_args = itemgetter('task', 'it')
|
|
|
|
|
|
|
|
@classmethod
|
|
@classmethod
|
|
|
- def from_dict(cls, d, app=None):
|
|
|
|
|
|
|
+ def from_dict(cls, d: Mapping, app: AppT = None) -> SignatureT:
|
|
|
return _upgrade(
|
|
return _upgrade(
|
|
|
d, cls(*cls._unpack_args(d['kwargs']), app=app, **d['options']),
|
|
d, cls(*cls._unpack_args(d['kwargs']), app=app, **d['options']),
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- def __init__(self, task, it, **options):
|
|
|
|
|
|
|
+ def __init__(self, task: str, it: Iterable, **options) -> None:
|
|
|
Signature.__init__(
|
|
Signature.__init__(
|
|
|
self, self._task_name, (),
|
|
self, self._task_name, (),
|
|
|
{'task': task, 'it': regen(it)}, immutable=True, **options
|
|
{'task': task, 'it': regen(it)}, immutable=True, **options
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- def apply_async(self, args=(), kwargs={}, **opts):
|
|
|
|
|
|
|
+ def apply_async(self,
|
|
|
|
|
+ args: Sequence = (),
|
|
|
|
|
+ kwargs: Mapping = {},
|
|
|
|
|
+ **opts) -> ResultT:
|
|
|
# need to evaluate generators
|
|
# need to evaluate generators
|
|
|
task, it = self._unpack_args(self.kwargs)
|
|
task, it = self._unpack_args(self.kwargs)
|
|
|
return self.type.apply_async(
|
|
return self.type.apply_async(
|
|
@@ -815,7 +881,7 @@ class xmap(_basemap):
|
|
|
|
|
|
|
|
_task_name = 'celery.map'
|
|
_task_name = 'celery.map'
|
|
|
|
|
|
|
|
- def __repr__(self):
|
|
|
|
|
|
|
+ def __repr__(self) -> str:
|
|
|
task, it = self._unpack_args(self.kwargs)
|
|
task, it = self._unpack_args(self.kwargs)
|
|
|
return '[{0}(x) for x in {1}]'.format(
|
|
return '[{0}(x) for x in {1}]'.format(
|
|
|
task.task, truncate(repr(it), 100))
|
|
task.task, truncate(repr(it), 100))
|
|
@@ -827,7 +893,7 @@ class xstarmap(_basemap):
|
|
|
|
|
|
|
|
_task_name = 'celery.starmap'
|
|
_task_name = 'celery.starmap'
|
|
|
|
|
|
|
|
- def __repr__(self):
|
|
|
|
|
|
|
+ def __repr__(self) -> str:
|
|
|
task, it = self._unpack_args(self.kwargs)
|
|
task, it = self._unpack_args(self.kwargs)
|
|
|
return '[{0}(*x) for x in {1}]'.format(
|
|
return '[{0}(*x) for x in {1}]'.format(
|
|
|
task.task, truncate(repr(it), 100))
|
|
task.task, truncate(repr(it), 100))
|
|
@@ -840,29 +906,32 @@ class chunks(Signature):
|
|
|
_unpack_args = itemgetter('task', 'it', 'n')
|
|
_unpack_args = itemgetter('task', 'it', 'n')
|
|
|
|
|
|
|
|
@classmethod
|
|
@classmethod
|
|
|
- def from_dict(cls, d, app=None):
|
|
|
|
|
|
|
+ def from_dict(cls, d: Mapping, app: AppT = None) -> SignatureT:
|
|
|
return _upgrade(
|
|
return _upgrade(
|
|
|
d, chunks(*cls._unpack_args(
|
|
d, chunks(*cls._unpack_args(
|
|
|
d['kwargs']), app=app, **d['options']),
|
|
d['kwargs']), app=app, **d['options']),
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- def __init__(self, task, it, n, **options):
|
|
|
|
|
|
|
+ def __init__(self, task: str, it: Iterable, n: int, **options) -> None:
|
|
|
Signature.__init__(
|
|
Signature.__init__(
|
|
|
self, 'celery.chunks', (),
|
|
self, 'celery.chunks', (),
|
|
|
{'task': task, 'it': regen(it), 'n': n},
|
|
{'task': task, 'it': regen(it), 'n': n},
|
|
|
immutable=True, **options
|
|
immutable=True, **options
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- def __call__(self, **options):
|
|
|
|
|
|
|
+ def __call__(self, **options) -> ResultT:
|
|
|
return self.apply_async(**options)
|
|
return self.apply_async(**options)
|
|
|
|
|
|
|
|
- def apply_async(self, args=(), kwargs={}, **opts):
|
|
|
|
|
|
|
+ def apply_async(self,
|
|
|
|
|
+ args: Sequence = (),
|
|
|
|
|
+ kwargs: Mapping = {},
|
|
|
|
|
+ **opts) -> ResultT:
|
|
|
return self.group().apply_async(
|
|
return self.group().apply_async(
|
|
|
args, kwargs,
|
|
args, kwargs,
|
|
|
route_name=task_name_from(self.kwargs.get('task')), **opts
|
|
route_name=task_name_from(self.kwargs.get('task')), **opts
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- def group(self):
|
|
|
|
|
|
|
+ def group(self) -> SignatureT:
|
|
|
# need to evaluate generators
|
|
# need to evaluate generators
|
|
|
task, it, n = self._unpack_args(self.kwargs)
|
|
task, it, n = self._unpack_args(self.kwargs)
|
|
|
return group((xstarmap(task, part, app=self._app)
|
|
return group((xstarmap(task, part, app=self._app)
|
|
@@ -870,11 +939,12 @@ class chunks(Signature):
|
|
|
app=self._app)
|
|
app=self._app)
|
|
|
|
|
|
|
|
@classmethod
|
|
@classmethod
|
|
|
- def apply_chunks(cls, task, it, n, app=None):
|
|
|
|
|
|
|
+ def apply_chunks(cls, task: str, it: Iterable, n: int,
|
|
|
|
|
+ app: AppT = None) -> ResultT:
|
|
|
return cls(task, it, n, app=app)()
|
|
return cls(task, it, n, app=app)()
|
|
|
|
|
|
|
|
|
|
|
|
|
-def _maybe_group(tasks, app):
|
|
|
|
|
|
|
+def _maybe_group(tasks: Any, app: AppT) -> Sequence[SignatureT]:
|
|
|
if isinstance(tasks, dict):
|
|
if isinstance(tasks, dict):
|
|
|
tasks = signature(tasks, app=app)
|
|
tasks = signature(tasks, app=app)
|
|
|
|
|
|
|
@@ -921,12 +991,12 @@ class group(Signature):
|
|
|
tasks = getitem_property('kwargs.tasks', 'Tasks in group.')
|
|
tasks = getitem_property('kwargs.tasks', 'Tasks in group.')
|
|
|
|
|
|
|
|
@classmethod
|
|
@classmethod
|
|
|
- def from_dict(cls, d, app=None):
|
|
|
|
|
|
|
+ def from_dict(cls, d: Mapping, app: AppT = None) -> SignatureT:
|
|
|
return _upgrade(
|
|
return _upgrade(
|
|
|
d, group(d['kwargs']['tasks'], app=app, **d['options']),
|
|
d, group(d['kwargs']['tasks'], app=app, **d['options']),
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- def __init__(self, *tasks, **options):
|
|
|
|
|
|
|
+ def __init__(self, *tasks, **options) -> None:
|
|
|
if len(tasks) == 1:
|
|
if len(tasks) == 1:
|
|
|
tasks = tasks[0]
|
|
tasks = tasks[0]
|
|
|
if isinstance(tasks, group):
|
|
if isinstance(tasks, group):
|
|
@@ -938,17 +1008,27 @@ class group(Signature):
|
|
|
)
|
|
)
|
|
|
self.subtask_type = 'group'
|
|
self.subtask_type = 'group'
|
|
|
|
|
|
|
|
- def __call__(self, *partial_args, **options):
|
|
|
|
|
|
|
+ def __call__(self, *partial_args, **options) -> ResultT:
|
|
|
return self.apply_async(partial_args, **options)
|
|
return self.apply_async(partial_args, **options)
|
|
|
|
|
|
|
|
- def skew(self, start=1.0, stop=None, step=1.0):
|
|
|
|
|
|
|
+ def skew(self,
|
|
|
|
|
+ start: float = 1.0,
|
|
|
|
|
+ stop: float = None,
|
|
|
|
|
+ step: float = 1.0) -> SignatureT:
|
|
|
it = fxrange(start, stop, step, repeatlast=True)
|
|
it = fxrange(start, stop, step, repeatlast=True)
|
|
|
for task in self.tasks:
|
|
for task in self.tasks:
|
|
|
task.set(countdown=next(it))
|
|
task.set(countdown=next(it))
|
|
|
return self
|
|
return self
|
|
|
|
|
|
|
|
- def apply_async(self, args=(), kwargs=None, add_to_parent=True,
|
|
|
|
|
- producer=None, link=None, link_error=None, **options):
|
|
|
|
|
|
|
+ def apply_async(self,
|
|
|
|
|
+ args: Sequence = (),
|
|
|
|
|
+ kwargs: Mapping = None,
|
|
|
|
|
+ *,
|
|
|
|
|
+ add_to_parent: bool = True,
|
|
|
|
|
+ producer: ProducerT = None,
|
|
|
|
|
+ link: Sequence[SignatureT] = None,
|
|
|
|
|
+ link_error: Sequence[SignatureT] = None,
|
|
|
|
|
+ **options) -> ResultT:
|
|
|
if link is not None:
|
|
if link is not None:
|
|
|
raise TypeError('Cannot add link to group: use a chord')
|
|
raise TypeError('Cannot add link to group: use a chord')
|
|
|
if link_error is not None:
|
|
if link_error is not None:
|
|
@@ -982,7 +1062,10 @@ class group(Signature):
|
|
|
parent_task.add_trail(result)
|
|
parent_task.add_trail(result)
|
|
|
return result
|
|
return result
|
|
|
|
|
|
|
|
- def apply(self, args=(), kwargs={}, **options):
|
|
|
|
|
|
|
+ def apply(self,
|
|
|
|
|
+ args: Sequence = (),
|
|
|
|
|
+ kwargs: Mapping = {},
|
|
|
|
|
+ **options) -> ResultT:
|
|
|
app = self.app
|
|
app = self.app
|
|
|
if not self.tasks:
|
|
if not self.tasks:
|
|
|
return self.freeze() # empty group returns GroupResult
|
|
return self.freeze() # empty group returns GroupResult
|
|
@@ -992,23 +1075,30 @@ class group(Signature):
|
|
|
sig.apply(args=args, kwargs=kwargs, **options) for sig, _ in tasks
|
|
sig.apply(args=args, kwargs=kwargs, **options) for sig, _ in tasks
|
|
|
])
|
|
])
|
|
|
|
|
|
|
|
- def set_immutable(self, immutable):
|
|
|
|
|
|
|
+ def set_immutable(self, immutable: bool) -> None:
|
|
|
for task in self.tasks:
|
|
for task in self.tasks:
|
|
|
task.set_immutable(immutable)
|
|
task.set_immutable(immutable)
|
|
|
|
|
|
|
|
- def link(self, sig):
|
|
|
|
|
|
|
+ def link(self, sig: SignatureT) -> SignatureT:
|
|
|
# Simply link to first task
|
|
# Simply link to first task
|
|
|
sig = sig.clone().set(immutable=True)
|
|
sig = sig.clone().set(immutable=True)
|
|
|
return self.tasks[0].link(sig)
|
|
return self.tasks[0].link(sig)
|
|
|
|
|
|
|
|
- def link_error(self, sig):
|
|
|
|
|
|
|
+ def link_error(self, sig: SignatureT) -> SignatureT:
|
|
|
sig = sig.clone().set(immutable=True)
|
|
sig = sig.clone().set(immutable=True)
|
|
|
return self.tasks[0].link_error(sig)
|
|
return self.tasks[0].link_error(sig)
|
|
|
|
|
|
|
|
- def _prepared(self, tasks, partial_args, group_id, root_id, app,
|
|
|
|
|
- CallableSignature=abstract.CallableSignature,
|
|
|
|
|
- from_dict=Signature.from_dict,
|
|
|
|
|
- isinstance=isinstance, tuple=tuple):
|
|
|
|
|
|
|
+ def _prepared(self, tasks: Sequence[SignatureT],
|
|
|
|
|
+ partial_args: Sequence,
|
|
|
|
|
+ group_id: str,
|
|
|
|
|
+ root_id: str,
|
|
|
|
|
+ app: AppT,
|
|
|
|
|
+ *,
|
|
|
|
|
+ CallableSignature: Callable = abstract.CallableSignature,
|
|
|
|
|
+ from_dict: Callable = Signature.from_dict,
|
|
|
|
|
+ isinstance: Callable = isinstance,
|
|
|
|
|
+ tuple: Callable = tuple
|
|
|
|
|
+ ) -> Iterable[Tuple[SignatureT, ResultT]]:
|
|
|
for task in tasks:
|
|
for task in tasks:
|
|
|
if isinstance(task, CallableSignature):
|
|
if isinstance(task, CallableSignature):
|
|
|
# local sigs are always of type Signature, and we
|
|
# local sigs are always of type Signature, and we
|
|
@@ -1029,9 +1119,15 @@ class group(Signature):
|
|
|
task.args = tuple(partial_args) + tuple(task.args)
|
|
task.args = tuple(partial_args) + tuple(task.args)
|
|
|
yield task, task.freeze(group_id=group_id, root_id=root_id)
|
|
yield task, task.freeze(group_id=group_id, root_id=root_id)
|
|
|
|
|
|
|
|
- def _apply_tasks(self, tasks, producer=None, app=None, p=None,
|
|
|
|
|
- add_to_parent=None, chord=None,
|
|
|
|
|
- args=None, kwargs=None, **options):
|
|
|
|
|
|
|
+ def _apply_tasks(self, tasks: Sequence[SignatureT],
|
|
|
|
|
+ producer: ProducerT = None,
|
|
|
|
|
+ app: AppT = None,
|
|
|
|
|
+ p: Thenable = None,
|
|
|
|
|
+ add_to_parent: bool = None,
|
|
|
|
|
+ chord: SignatureT = None,
|
|
|
|
|
+ args: Sequence = None,
|
|
|
|
|
+ kwargs: Mapping = None,
|
|
|
|
|
+ **options) -> Iterable[ResultT]:
|
|
|
# pylint: disable=redefined-outer-name
|
|
# pylint: disable=redefined-outer-name
|
|
|
# XXX chord is also a class in outer scope.
|
|
# XXX chord is also a class in outer scope.
|
|
|
app = app or self.app
|
|
app = app or self.app
|
|
@@ -1053,7 +1149,7 @@ class group(Signature):
|
|
|
res.then(p, weak=True)
|
|
res.then(p, weak=True)
|
|
|
yield res # <-- r.parent, etc set in the frozen result.
|
|
yield res # <-- r.parent, etc set in the frozen result.
|
|
|
|
|
|
|
|
- def _freeze_gid(self, options):
|
|
|
|
|
|
|
+ def _freeze_gid(self, options: Mapping) -> Tuple[Mapping, str, str]:
|
|
|
# remove task_id and use that as the group_id,
|
|
# remove task_id and use that as the group_id,
|
|
|
# if we don't remove it then every task will have the same id...
|
|
# if we don't remove it then every task will have the same id...
|
|
|
options = dict(self.options, **options)
|
|
options = dict(self.options, **options)
|
|
@@ -1061,8 +1157,13 @@ class group(Signature):
|
|
|
options.pop('task_id', uuid()))
|
|
options.pop('task_id', uuid()))
|
|
|
return options, group_id, options.get('root_id')
|
|
return options, group_id, options.get('root_id')
|
|
|
|
|
|
|
|
- def freeze(self, _id=None, group_id=None, chord=None,
|
|
|
|
|
- root_id=None, parent_id=None):
|
|
|
|
|
|
|
+ def freeze(self,
|
|
|
|
|
+ _id: str = None,
|
|
|
|
|
+ *,
|
|
|
|
|
+ group_id: str = None,
|
|
|
|
|
+ chord: SignatureT = None,
|
|
|
|
|
+ root_id: str = None,
|
|
|
|
|
+ parent_id: str = None) -> ResultT:
|
|
|
# pylint: disable=redefined-outer-name
|
|
# pylint: disable=redefined-outer-name
|
|
|
# XXX chord is also a class in outer scope.
|
|
# XXX chord is also a class in outer scope.
|
|
|
opts = self.options
|
|
opts = self.options
|
|
@@ -1089,7 +1190,9 @@ class group(Signature):
|
|
|
return self.app.GroupResult(gid, results)
|
|
return self.app.GroupResult(gid, results)
|
|
|
_freeze = freeze
|
|
_freeze = freeze
|
|
|
|
|
|
|
|
- def _freeze_unroll(self, new_tasks, group_id, chord, root_id, parent_id):
|
|
|
|
|
|
|
+ def _freeze_unroll(self, new_tasks: Sequence[SignatureT],
|
|
|
|
|
+ group_id: str, chord: SignatureT,
|
|
|
|
|
+ root_id: str, parent_id: str) -> Iterator[ResultT]:
|
|
|
# pylint: disable=redefined-outer-name
|
|
# pylint: disable=redefined-outer-name
|
|
|
# XXX chord is also a class in outer scope.
|
|
# XXX chord is also a class in outer scope.
|
|
|
stack = deque(self.tasks)
|
|
stack = deque(self.tasks)
|
|
@@ -1103,18 +1206,18 @@ class group(Signature):
|
|
|
chord=chord, root_id=root_id,
|
|
chord=chord, root_id=root_id,
|
|
|
parent_id=parent_id)
|
|
parent_id=parent_id)
|
|
|
|
|
|
|
|
- def __repr__(self):
|
|
|
|
|
|
|
+ def __repr__(self) -> str:
|
|
|
if self.tasks:
|
|
if self.tasks:
|
|
|
return remove_repeating_from_task(
|
|
return remove_repeating_from_task(
|
|
|
self.tasks[0]['task'],
|
|
self.tasks[0]['task'],
|
|
|
'group({0.tasks!r})'.format(self))
|
|
'group({0.tasks!r})'.format(self))
|
|
|
return 'group(<empty>)'
|
|
return 'group(<empty>)'
|
|
|
|
|
|
|
|
- def __len__(self):
|
|
|
|
|
|
|
+ def __len__(self) -> int:
|
|
|
return len(self.tasks)
|
|
return len(self.tasks)
|
|
|
|
|
|
|
|
@property
|
|
@property
|
|
|
- def app(self):
|
|
|
|
|
|
|
+ def app(self) -> AppT:
|
|
|
app = self._app
|
|
app = self._app
|
|
|
if app is None:
|
|
if app is None:
|
|
|
try:
|
|
try:
|
|
@@ -1153,18 +1256,25 @@ class chord(Signature):
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
@classmethod
|
|
@classmethod
|
|
|
- def from_dict(cls, d, app=None):
|
|
|
|
|
|
|
+ def from_dict(cls, d: Mapping, app: AppT = None) -> SignatureT:
|
|
|
args, d['kwargs'] = cls._unpack_args(**d['kwargs'])
|
|
args, d['kwargs'] = cls._unpack_args(**d['kwargs'])
|
|
|
return _upgrade(d, cls(*args, app=app, **d))
|
|
return _upgrade(d, cls(*args, app=app, **d))
|
|
|
|
|
|
|
|
@staticmethod
|
|
@staticmethod
|
|
|
- def _unpack_args(header=None, body=None, **kwargs):
|
|
|
|
|
|
|
+ def _unpack_args(header: Sequence[SignatureT] = None,
|
|
|
|
|
+ body: SignatureT = None,
|
|
|
|
|
+ **kwargs) -> Tuple[Tuple, Mapping]:
|
|
|
# Python signatures are better at extracting keys from dicts
|
|
# Python signatures are better at extracting keys from dicts
|
|
|
# than manually popping things off.
|
|
# than manually popping things off.
|
|
|
return (header, body), kwargs
|
|
return (header, body), kwargs
|
|
|
|
|
|
|
|
- def __init__(self, header, body=None, task='celery.chord',
|
|
|
|
|
- args=(), kwargs={}, app=None, **options):
|
|
|
|
|
|
|
+ def __init__(self, header: Sequence[SignatureT],
|
|
|
|
|
+ body: SignatureT = None,
|
|
|
|
|
+ task: str = 'celery.chord',
|
|
|
|
|
+ args: Sequence = (),
|
|
|
|
|
+ kwargs: Mapping = {},
|
|
|
|
|
+ app: AppT = None,
|
|
|
|
|
+ **options) -> None:
|
|
|
Signature.__init__(
|
|
Signature.__init__(
|
|
|
self, task, args,
|
|
self, task, args,
|
|
|
dict(kwargs=kwargs, header=_maybe_group(header, app),
|
|
dict(kwargs=kwargs, header=_maybe_group(header, app),
|
|
@@ -1172,11 +1282,16 @@ class chord(Signature):
|
|
|
)
|
|
)
|
|
|
self.subtask_type = 'chord'
|
|
self.subtask_type = 'chord'
|
|
|
|
|
|
|
|
- def __call__(self, body=None, **options):
|
|
|
|
|
|
|
+ def __call__(self, body: SignatureT = None, **options) -> ResultT:
|
|
|
return self.apply_async((), {'body': body} if body else {}, **options)
|
|
return self.apply_async((), {'body': body} if body else {}, **options)
|
|
|
|
|
|
|
|
- def freeze(self, _id=None, group_id=None, chord=None,
|
|
|
|
|
- root_id=None, parent_id=None):
|
|
|
|
|
|
|
+ def freeze(self,
|
|
|
|
|
+ _id: str = None,
|
|
|
|
|
+ *,
|
|
|
|
|
+ group_id: str = None,
|
|
|
|
|
+ chord: SignatureT = None,
|
|
|
|
|
+ root_id: str = None,
|
|
|
|
|
+ parent_id: str = None) -> ResultT:
|
|
|
# pylint: disable=redefined-outer-name
|
|
# pylint: disable=redefined-outer-name
|
|
|
# XXX chord is also a class in outer scope.
|
|
# XXX chord is also a class in outer scope.
|
|
|
if not isinstance(self.tasks, group):
|
|
if not isinstance(self.tasks, group):
|
|
@@ -1200,9 +1315,15 @@ class chord(Signature):
|
|
|
self.id = self.tasks.id
|
|
self.id = self.tasks.id
|
|
|
return bodyres
|
|
return bodyres
|
|
|
|
|
|
|
|
- def apply_async(self, args=(), kwargs={}, task_id=None,
|
|
|
|
|
- producer=None, connection=None,
|
|
|
|
|
- router=None, result_cls=None, **options):
|
|
|
|
|
|
|
+ def apply_async(self,
|
|
|
|
|
+ args: Sequence =(),
|
|
|
|
|
+ kwargs: Mapping = {},
|
|
|
|
|
+ task_id: str = None,
|
|
|
|
|
+ producer: ProducerT = None,
|
|
|
|
|
+ connection: ConnectionT = None,
|
|
|
|
|
+ router: RouterT = None,
|
|
|
|
|
+ result_cls: type = None,
|
|
|
|
|
+ **options) -> ResultT:
|
|
|
kwargs = kwargs or {}
|
|
kwargs = kwargs or {}
|
|
|
args = (tuple(args) + tuple(self.args)
|
|
args = (tuple(args) + tuple(self.args)
|
|
|
if args and not self.immutable else self.args)
|
|
if args and not self.immutable else self.args)
|
|
@@ -1223,7 +1344,10 @@ class chord(Signature):
|
|
|
# chord([A, B, ...], C)
|
|
# chord([A, B, ...], C)
|
|
|
return self.run(tasks, body, args, task_id=task_id, **options)
|
|
return self.run(tasks, body, args, task_id=task_id, **options)
|
|
|
|
|
|
|
|
- def apply(self, args=(), kwargs={}, propagate=True, body=None, **options):
|
|
|
|
|
|
|
+ def apply(self, args: Sequence = (), kwargs: Mapping = {},
|
|
|
|
|
+ propagate: bool = True,
|
|
|
|
|
+ body: SignatureT = None,
|
|
|
|
|
+ **options) -> ResultT:
|
|
|
body = self.body if body is None else body
|
|
body = self.body if body is None else body
|
|
|
tasks = (self.tasks.clone() if isinstance(self.tasks, group)
|
|
tasks = (self.tasks.clone() if isinstance(self.tasks, group)
|
|
|
else group(self.tasks, app=self.app))
|
|
else group(self.tasks, app=self.app))
|
|
@@ -1231,7 +1355,8 @@ class chord(Signature):
|
|
|
args=(tasks.apply(args, kwargs).get(propagate=propagate),),
|
|
args=(tasks.apply(args, kwargs).get(propagate=propagate),),
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- def _traverse_tasks(self, tasks, value=None):
|
|
|
|
|
|
|
+ def _traverse_tasks(self, tasks: Sequence[SignatureT],
|
|
|
|
|
+ value: Any = None) -> Iterator[SignatureT]:
|
|
|
stack = deque(list(tasks))
|
|
stack = deque(list(tasks))
|
|
|
while stack:
|
|
while stack:
|
|
|
task = stack.popleft()
|
|
task = stack.popleft()
|
|
@@ -1240,12 +1365,14 @@ class chord(Signature):
|
|
|
else:
|
|
else:
|
|
|
yield task if value is None else value
|
|
yield task if value is None else value
|
|
|
|
|
|
|
|
- def __length_hint__(self):
|
|
|
|
|
|
|
+ def __length_hint__(self) -> int:
|
|
|
return sum(self._traverse_tasks(self.tasks, 1))
|
|
return sum(self._traverse_tasks(self.tasks, 1))
|
|
|
|
|
|
|
|
- def run(self, header, body, partial_args, app=None, interval=None,
|
|
|
|
|
- countdown=1, max_retries=None, eager=False,
|
|
|
|
|
- task_id=None, **options):
|
|
|
|
|
|
|
+ def run(self, header: SignatureT, body: SignatureT, partial_args: Sequence,
|
|
|
|
|
+ app: AppT = None, interval: float = None,
|
|
|
|
|
+ countdown: float = 1, max_retries: int = None,
|
|
|
|
|
+ eager: bool = False,
|
|
|
|
|
+ task_id: str = None, **options) -> ResultT:
|
|
|
app = app or self._get_app(body)
|
|
app = app or self._get_app(body)
|
|
|
group_id = header.options.get('task_id') or uuid()
|
|
group_id = header.options.get('task_id') or uuid()
|
|
|
root_id = body.options.get('root_id')
|
|
root_id = body.options.get('root_id')
|
|
@@ -1267,7 +1394,7 @@ class chord(Signature):
|
|
|
bodyres.parent = parent
|
|
bodyres.parent = parent
|
|
|
return bodyres
|
|
return bodyres
|
|
|
|
|
|
|
|
- def clone(self, *args, **kwargs):
|
|
|
|
|
|
|
+ def clone(self, *args, **kwargs) -> SignatureT:
|
|
|
s = Signature.clone(self, *args, **kwargs)
|
|
s = Signature.clone(self, *args, **kwargs)
|
|
|
# need to make copy of body
|
|
# need to make copy of body
|
|
|
try:
|
|
try:
|
|
@@ -1276,20 +1403,20 @@ class chord(Signature):
|
|
|
pass
|
|
pass
|
|
|
return s
|
|
return s
|
|
|
|
|
|
|
|
- def link(self, callback):
|
|
|
|
|
|
|
+ def link(self, callback: SignatureT) -> SignatureT:
|
|
|
self.body.link(callback)
|
|
self.body.link(callback)
|
|
|
return callback
|
|
return callback
|
|
|
|
|
|
|
|
- def link_error(self, errback):
|
|
|
|
|
|
|
+ def link_error(self, errback: SignatureT) -> SignatureT:
|
|
|
self.body.link_error(errback)
|
|
self.body.link_error(errback)
|
|
|
return errback
|
|
return errback
|
|
|
|
|
|
|
|
- def set_immutable(self, immutable):
|
|
|
|
|
|
|
+ def set_immutable(self, immutable: bool) -> None:
|
|
|
# changes mutability of header only, not callback.
|
|
# changes mutability of header only, not callback.
|
|
|
for task in self.tasks:
|
|
for task in self.tasks:
|
|
|
task.set_immutable(immutable)
|
|
task.set_immutable(immutable)
|
|
|
|
|
|
|
|
- def __repr__(self):
|
|
|
|
|
|
|
+ def __repr__(self) -> str:
|
|
|
if self.body:
|
|
if self.body:
|
|
|
if isinstance(self.body, _chain):
|
|
if isinstance(self.body, _chain):
|
|
|
return remove_repeating_from_task(
|
|
return remove_repeating_from_task(
|
|
@@ -1304,10 +1431,10 @@ class chord(Signature):
|
|
|
return '<chord without body: {0.tasks!r}>'.format(self)
|
|
return '<chord without body: {0.tasks!r}>'.format(self)
|
|
|
|
|
|
|
|
@cached_property
|
|
@cached_property
|
|
|
- def app(self):
|
|
|
|
|
|
|
+ def app(self) -> AppT:
|
|
|
return self._get_app(self.body)
|
|
return self._get_app(self.body)
|
|
|
|
|
|
|
|
- def _get_app(self, body=None):
|
|
|
|
|
|
|
+ def _get_app(self, body: SignatureT = None) -> AppT:
|
|
|
app = self._app
|
|
app = self._app
|
|
|
if app is None:
|
|
if app is None:
|
|
|
try:
|
|
try:
|
|
@@ -1323,7 +1450,7 @@ class chord(Signature):
|
|
|
body = getitem_property('kwargs.body', 'Body task of chord.')
|
|
body = getitem_property('kwargs.body', 'Body task of chord.')
|
|
|
|
|
|
|
|
|
|
|
|
|
-def signature(varies, *args, **kwargs):
|
|
|
|
|
|
|
+def signature(varies: SignatureT, *args, **kwargs) -> SignatureT:
|
|
|
"""Create new signature.
|
|
"""Create new signature.
|
|
|
|
|
|
|
|
- if the first argument is a signature already then it's cloned.
|
|
- if the first argument is a signature already then it's cloned.
|
|
@@ -1340,11 +1467,13 @@ def signature(varies, *args, **kwargs):
|
|
|
return Signature(varies, *args, **kwargs)
|
|
return Signature(varies, *args, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
-def maybe_signature(d, app=None, clone=False):
|
|
|
|
|
|
|
+def maybe_signature(d: Optional[SignatureT],
|
|
|
|
|
+ app: AppT = None,
|
|
|
|
|
+ clone: bool = False) -> Optional[SignatureT]:
|
|
|
"""Ensure obj is a signature, or None.
|
|
"""Ensure obj is a signature, or None.
|
|
|
|
|
|
|
|
Arguments:
|
|
Arguments:
|
|
|
- d (Optional[Union[abstract.CallableSignature, Mapping]]):
|
|
|
|
|
|
|
+ d (Optional[SignatureT]):
|
|
|
Signature or dict-serialized signature.
|
|
Signature or dict-serialized signature.
|
|
|
app (celery.Celery):
|
|
app (celery.Celery):
|
|
|
App to bind signature to.
|
|
App to bind signature to.
|
|
@@ -1353,7 +1482,7 @@ def maybe_signature(d, app=None, clone=False):
|
|
|
will be cloned when this flag is enabled.
|
|
will be cloned when this flag is enabled.
|
|
|
|
|
|
|
|
Returns:
|
|
Returns:
|
|
|
- Optional[abstract.CallableSignature]
|
|
|
|
|
|
|
+ Optional[SignatureT]
|
|
|
"""
|
|
"""
|
|
|
if d is not None:
|
|
if d is not None:
|
|
|
if isinstance(d, abstract.CallableSignature):
|
|
if isinstance(d, abstract.CallableSignature):
|