diff --git a/celery-stubs/__init__.pyi b/celery-stubs/__init__.pyi index 5fe83d3..bec64d1 100644 --- a/celery-stubs/__init__.pyi +++ b/celery-stubs/__init__.pyi @@ -1,5 +1,12 @@ -from celery import local -from celery._state import current_app, current_task +from types import ModuleType +from typing import Any, NamedTuple + +from celery import execute as execute +from celery import local as local +from celery import messaging as messaging +from celery._state import current_app as current_app +from celery._state import current_task as current_task +from celery.app import bugreport as bugreport from celery.app import shared_task from celery.app.base import Celery from celery.app.task import Task @@ -13,22 +20,73 @@ from celery.canvas import ( xmap, xstarmap, ) +from celery.canvas import maybe_signature as maybe_signature +from celery.canvas import signature as subtask from celery.utils import uuid +log: ModuleType +registry: ModuleType + +class version_info_t(NamedTuple): + major: int + minor: int + micro: int + releaselevel: str + serial: str + +VERSION: version_info_t +version_info: version_info_t +VERSION_BANNER: str +SERIES: str +__version__: str +__author__: str +__contact__: str +__homepage__: str +__docformat__: str + +def _find_option_with_arg( + argv: list[str], short_opts: str | None = ..., long_opts: list[str] | None = ... +) -> str | None: ... +def maybe_patch_concurrency( + argv: list[str] | None = ..., + short_opts: str | None = ..., + long_opts: list[str] | None = ..., + patches: dict[str, Any] | None = ..., +) -> None: ... + __all__ = ( + "SERIES", + "VERSION", + "VERSION_BANNER", "Celery", "Signature", "Task", + "__author__", + "__contact__", + "__docformat__", + "__homepage__", + "__version__", + "_find_option_with_arg", + "bugreport", "chain", "chord", "chunks", "current_app", "current_task", + "execute", "group", "local", + "log", + "maybe_patch_concurrency", + "maybe_signature", + "messaging", + "registry", "shared_task", "signature", + "subtask", "uuid", + "version_info", + "version_info_t", "xmap", "xstarmap", ) diff --git a/celery-stubs/__main__.pyi b/celery-stubs/__main__.pyi new file mode 100644 index 0000000..f2e516c --- /dev/null +++ b/celery-stubs/__main__.pyi @@ -0,0 +1,5 @@ +from typing import Any + +__all__ = ("main",) + +def main() -> Any: ... diff --git a/celery-stubs/_state.pyi b/celery-stubs/_state.pyi index 0d02650..b23165d 100644 --- a/celery-stubs/_state.pyi +++ b/celery-stubs/_state.pyi @@ -1,9 +1,26 @@ +from collections.abc import Callable from typing import Any from celery.app.base import Celery from celery.app.task import Task +__all__ = ( + "connect_on_app_finalize", + "current_app", + "current_task", + "get_current_app", + "get_current_task", + "get_current_worker_task", + "set_default_app", +) + current_app: Celery current_task: Task[Any, Any] def get_current_task() -> Task[Any, Any]: ... +def get_current_app() -> Celery: ... +def get_current_worker_task() -> Task[Any, Any] | None: ... +def set_default_app(app: Celery) -> None: ... +def connect_on_app_finalize( + callback: Callable[[Celery], Any], +) -> Callable[[Celery], Any]: ... diff --git a/celery-stubs/app/__init__.pyi b/celery-stubs/app/__init__.pyi index 828d6a5..7e9a9e1 100644 --- a/celery-stubs/app/__init__.pyi +++ b/celery-stubs/app/__init__.pyi @@ -8,14 +8,55 @@ from typing import ( overload, ) -from celery.app import beat as beat from celery.app import control as control from celery.app import events as events from celery.app import task as task +from celery.app.base import Celery from celery.app.task import Context, Task from celery.utils.threads import _LocalStack from typing_extensions import ParamSpec +__all__ = ( + "AppPickler", + "Celery", + "app_or_default", + "bugreport", + "default_app", + "disable_trace", + "enable_trace", + "pop_current_task", + "push_current_task", + "shared_task", +) + +class AppPickler: + def __call__(self, cls: type[Celery], *args: Any) -> Celery: ... + def build_kwargs(self, *args: Any) -> dict[str, Any]: ... + def build_standard_kwargs( + self, + main: str | None, + changes: dict[str, Any] | None, + loader: Any, + backend: Any, + amqp: Any, + events: Any, # noqa: F811 + log: Any, + control: Any, # noqa: F811 + accept_magic_kwargs: bool, + config_source: Any | None = None, + ) -> dict[str, Any]: ... + def construct(self, cls: type[Celery], **kwargs: Any) -> Celery: ... + def prepare(self, app: Celery, **kwargs: Any) -> dict[str, Any]: ... + +def app_or_default(app: Celery | None = ...) -> Celery: ... +def bugreport(app: Celery | None = ...) -> str: ... +def enable_trace() -> None: ... +def disable_trace() -> None: ... +def push_current_task(obj: Task[Any, Any]) -> None: ... +def pop_current_task() -> Task[Any, Any] | None: ... + +default_app: Celery + _T = TypeVar("_T", bound=Task[Any, Any]) _P = ParamSpec("_P") _R = TypeVar("_R") diff --git a/celery-stubs/app/amqp.pyi b/celery-stubs/app/amqp.pyi index cc61e1e..5132f39 100644 --- a/celery-stubs/app/amqp.pyi +++ b/celery-stubs/app/amqp.pyi @@ -1 +1,158 @@ -class AMQP: ... +from datetime import datetime +from typing import Any, NamedTuple, TypeAlias + +import kombu +import kombu.pools +from celery.app.base import Celery +from celery.app.routes import Router as RouterClass +from kombu.transport.base import StdChannel + +__all__ = ("AMQP", "Queues", "task_message") + +class task_message(NamedTuple): + headers: dict[str, Any] + properties: dict[str, Any] + body: tuple[Any, ...] + sent_event: dict[str, Any] | None + +class Queues(dict[str, kombu.Queue]): + def __init__( + self, + queues: list[kombu.Queue] | dict[str, kombu.Queue] | None = None, + default_exchange: kombu.Exchange | None = None, + create_missing: bool = True, + create_missing_queue_type: str | None = None, + create_missing_queue_exchange_type: str | None = None, + autoexchange: kombu.Exchange | None = None, + max_priority: int | None = None, + default_routing_key: str | None = None, + ) -> None: ... + def __missing__(self, name: str) -> kombu.Queue: ... + def add(self, queue: kombu.Queue, **kwargs: Any) -> None: ... + def add_compat(self, name: str, **options: Any) -> kombu.Queue: ... + @property + def consume_from(self) -> dict[str, kombu.Queue]: ... + def deselect(self, exclude: list[str]) -> None: ... + def format(self, indent: int = 0, indent_first: bool = True) -> str: ... + def new_missing(self, name: str) -> kombu.Queue: ... + def select(self, include: list[str]) -> None: ... + def select_add(self, queue: kombu.Queue, **kwargs: Any) -> None: ... + +# Type alias to avoid conflict with AMQP.Queues method +_Queues: TypeAlias = Queues + +class AMQP: + # Class attributes + BrokerConnection: type[kombu.Connection] + Connection: type[kombu.Connection] + Consumer: type[kombu.Consumer] + Producer: type[kombu.Producer] + queues_cls: type[_Queues] + argsrepr_maxsize: int + kwargsrepr_maxsize: int + autoexchange: kombu.Exchange | None + + app: Celery + + def __init__(self, app: Celery) -> None: ... + def TaskConsumer( + self, + channel: StdChannel, + queues: list[kombu.Queue] | None = None, + accept: list[str] | None = None, + **kw: Any, + ) -> kombu.Consumer: ... + def Queues( + self, + queues: list[kombu.Queue] | dict[str, kombu.Queue], + create_missing: bool | None = None, + create_missing_queue_type: str | None = None, + create_missing_queue_exchange_type: str | None = None, + autoexchange: kombu.Exchange | None = None, + max_priority: int | None = None, + ) -> _Queues: ... + def Router( + self, + queues: _Queues | None = None, + create_missing: bool | None = None, + ) -> RouterClass: ... + def flush_routes(self) -> None: ... + def as_task_v1( + self, + task_id: str, + name: str, + args: tuple[Any, ...] | None = None, + kwargs: dict[str, Any] | None = None, + countdown: float | None = None, + eta: datetime | None = None, + group_id: str | None = None, + group_index: int | None = None, + expires: float | datetime | None = None, + retries: int = 0, + chord: Any | None = None, + callbacks: list[Any] | None = None, + errbacks: list[Any] | None = None, + reply_to: str | None = None, + time_limit: int | None = None, + soft_time_limit: int | None = None, + create_sent_event: bool = False, + root_id: str | None = None, + parent_id: str | None = None, + shadow: str | None = None, + now: datetime | None = None, + timezone: Any | None = None, + **compat_kwargs: Any, + ) -> task_message: ... + def as_task_v2( + self, + task_id: str, + name: str, + args: tuple[Any, ...] | None = None, + kwargs: dict[str, Any] | None = None, + countdown: float | None = None, + eta: datetime | None = None, + group_id: str | None = None, + group_index: int | None = None, + expires: float | datetime | None = None, + retries: int = 0, + chord: Any | None = None, + callbacks: list[Any] | None = None, + errbacks: list[Any] | None = None, + reply_to: str | None = None, + time_limit: int | None = None, + soft_time_limit: int | None = None, + create_sent_event: bool = False, + root_id: str | None = None, + parent_id: str | None = None, + shadow: str | None = None, + chain: Any | None = None, + now: datetime | None = None, + timezone: Any | None = None, + origin: str | None = None, + ignore_result: bool = False, + argsrepr: str | None = None, + kwargsrepr: str | None = None, + stamped_headers: list[str] | None = None, + replaced_task_nesting: int = 0, + **options: Any, + ) -> task_message: ... + @property + def create_task_message(self) -> Any: ... + @property + def default_exchange(self) -> kombu.Exchange: ... + @property + def default_queue(self) -> kombu.Queue: ... + @property + def producer_pool(self) -> kombu.pools.ProducerPool: ... + @property + def publisher_pool(self) -> kombu.pools.ProducerPool: ... + @property + def queues(self) -> _Queues: ... + @property + def router(self) -> RouterClass: ... + @property + def routes(self) -> list[dict[str, Any]]: ... + @property + def send_task_message(self) -> Any: ... + @property + def utc(self) -> bool: ... diff --git a/celery-stubs/app/annotations.pyi b/celery-stubs/app/annotations.pyi new file mode 100644 index 0000000..4e0bdea --- /dev/null +++ b/celery-stubs/app/annotations.pyi @@ -0,0 +1,11 @@ +from typing import Any + +__all__ = ("MapAnnotation", "prepare", "resolve_all") + +class MapAnnotation: + def __init__(self, d: dict[str, Any]) -> None: ... + def annotate(self, task: Any) -> dict[str, Any] | None: ... + def annotate_any(self) -> dict[str, Any] | None: ... + +def prepare(annotations: Any) -> Any: ... +def resolve_all(anno: Any, task: Any) -> dict[str, Any]: ... diff --git a/celery-stubs/app/autoretry.pyi b/celery-stubs/app/autoretry.pyi new file mode 100644 index 0000000..1627599 --- /dev/null +++ b/celery-stubs/app/autoretry.pyi @@ -0,0 +1,4 @@ +from collections.abc import Callable +from typing import Any + +def add_autoretry_behaviour(task: Any, **options: Any) -> Callable[..., Any]: ... diff --git a/celery-stubs/app/backends.pyi b/celery-stubs/app/backends.pyi new file mode 100644 index 0000000..8c7daf4 --- /dev/null +++ b/celery-stubs/app/backends.pyi @@ -0,0 +1,15 @@ +from typing import Any + +from celery.backends.base import Backend + +__all__ = ("by_name", "by_url") + +BACKEND_ALIASES: dict[str, str] +UNKNOWN_BACKEND: str + +def by_name( + backend: str | None = None, + loader: Any | None = None, + extension_namespace: str = "celery.result_backends", +) -> type[Backend]: ... +def by_url(backend: str | None = None, loader: Any | None = None) -> type[Backend]: ... diff --git a/celery-stubs/app/base.pyi b/celery-stubs/app/base.pyi index e34ac30..6bbad18 100644 --- a/celery-stubs/app/base.pyi +++ b/celery-stubs/app/base.pyi @@ -11,11 +11,12 @@ from typing import ( overload, ) +__all__ = ("Celery",) + import celery.app import celery.result import kombu from celery.app.amqp import AMQP -from celery.app.beat import Beat as CeleryBeat from celery.app.control import Control from celery.app.events import Events from celery.app.log import Logging @@ -24,6 +25,7 @@ from celery.app.routes import Router from celery.app.task import Context from celery.app.task import Task as CeleryTask from celery.app.utils import Settings +from celery.apps.beat import Beat as CeleryBeat from celery.apps.worker import Worker as CeleryWorker from celery.backends.base import Backend from celery.canvas import Signature, chord @@ -46,13 +48,38 @@ _P = ParamSpec("_P") _R = TypeVar("_R") class Celery(Generic[_T_Global]): + # Class-level constants + IS_WINDOWS: bool + IS_macOS: bool + SYSTEM: str + Pickler: type[Any] + + # Configuration class names + amqp_cls: str | None + backend_cls: str | None + control_cls: str | None + events_cls: str | None + loader_cls: str | None + log_cls: str | None + registry_cls: str | None + task_cls: str | None + + # Instance attributes: None at class level, but always set in __init__ + # Typed as non-optional since users work with instances, not the class + main: str steps: defaultdict[str, set[Any]] + user_options: defaultdict[str, set[Any]] + builtin_fixups: set[str] + # Signals (always set on instances in __init__) on_configure: Signal on_after_configure: Signal on_after_finalize: Signal on_after_fork: Signal + def __reduce_args__(self) -> tuple[Any, ...]: ... + def __reduce_keys__(self) -> dict[str, Any]: ... + def __reduce_v1__(self) -> tuple[Any, ...]: ... def __init__( self, main: str | None = None, @@ -65,7 +92,6 @@ class Celery(Generic[_T_Global]): set_as_current: bool = True, tasks: str | type[TaskRegistry] | None = None, broker: str | None = None, - imports: list[str] | tuple[str, ...] | None = None, include: list[str] | tuple[str, ...] | None = None, changes: dict[str, Any] | None = None, config_source: str | object | None = None, @@ -74,6 +100,9 @@ class Celery(Generic[_T_Global]): autofinalize: bool = True, namespace: str | None = None, strict_typing: bool = True, + *, + # Config kwargs that can be passed directly (captured by **kwargs at runtime) + imports: list[str] | tuple[str, ...] | None = ..., broker_connection_retry: bool = ..., broker_connection_max_retries: int = ..., broker_channel_error_retry: bool = ..., @@ -109,21 +138,28 @@ class Celery(Generic[_T_Global]): worker_task_log_format: str = ..., worker_redirect_stdouts: bool = ..., worker_redirect_stdouts_level: str = ..., + **kwargs: Any, ) -> None: ... def _task_from_fun( self, fun: Callable[_P, _R], - name: str | None = ..., - base: type[_T_Global] | None = ..., - bind: bool = ..., - # options + name: str | None = None, + base: type[_T_Global] | None = None, + bind: bool = False, + # pydantic options (new in celery 5.4+) + pydantic: bool = False, + pydantic_strict: bool = False, + pydantic_context: dict[str, Any] | None = None, + pydantic_dump_kwargs: dict[str, Any] | None = None, + *, + # autoretry options (captured by **options at runtime) autoretry_for: Sequence[type[BaseException]] = ..., dont_autoretry_for: Sequence[type[BaseException]] = ..., retry_kwargs: dict[str, Any] = ..., retry_backoff: bool | int = ..., retry_backoff_max: int = ..., retry_jitter: bool = ..., - # from task + # task options typing: bool = ..., max_retries: int | None = ..., default_retry_delay: int = ..., @@ -148,6 +184,7 @@ class Celery(Generic[_T_Global]): abstract: bool = ..., after_return: Callable[..., Any] = ..., on_retry: Callable[..., Any] = ..., + **options: Any, ) -> _T_Global: ... def on_init(self) -> None: ... def set_current(self) -> None: ... @@ -311,9 +348,10 @@ class Celery(Generic[_T_Global]): self, allowed_serializers: set[str] | None = None, key: str | None = None, + key_password: str | None = None, cert: str | None = None, store: str | None = None, - digest: str = ..., + digest: str = "sha256", serializer: str = "json", ) -> None: ... def autodiscover_tasks( @@ -340,6 +378,7 @@ class Celery(Generic[_T_Global]): link_error: Signature[Any] | None = None, add_to_parent: bool = True, group_id: str | None = None, + group_index: int | None = None, retries: int = 0, chord: chord | None = None, reply_to: str | None = None, @@ -352,8 +391,15 @@ class Celery(Generic[_T_Global]): chain: Any | None = None, task_type: Any | None = None, replaced_task_nesting: int = 0, - # options + *, + # Options (passed through **options at runtime) ignore_result: bool = ..., + priority: int | None = ..., + queue: str | None = ..., + exchange: str | None = ..., + routing_key: str | None = ..., + exchange_type: str | None = ..., + stamped_headers: list[str] | None = ..., **options: Any, ) -> celery.result.AsyncResult[Any]: ... def connection_for_read( @@ -382,7 +428,11 @@ class Celery(Generic[_T_Global]): broker_connection = connection def connection_or_acquire( - self, connection: kombu.Connection | None = None, pool: bool = True + self, + connection: kombu.Connection | None = None, + pool: bool = True, + *_: Any, + **__: Any, ) -> FallbackContext[Any, Any]: ... default_connection = connection_or_acquire @@ -404,7 +454,7 @@ class Celery(Generic[_T_Global]): schedule: BaseSchedule | float, sig: Signature[Any], args: tuple[Any, ...] = (), - kwargs: dict[str, Any] = ..., + kwargs: dict[str, Any] | None = None, name: str | None = None, **opts: Any, ) -> str: ... diff --git a/celery-stubs/app/beat.pyi b/celery-stubs/app/beat.pyi deleted file mode 100644 index 7d2393c..0000000 --- a/celery-stubs/app/beat.pyi +++ /dev/null @@ -1 +0,0 @@ -class Beat: ... diff --git a/celery-stubs/app/builtins.pyi b/celery-stubs/app/builtins.pyi new file mode 100644 index 0000000..08e159b --- /dev/null +++ b/celery-stubs/app/builtins.pyi @@ -0,0 +1,14 @@ +from typing import Any + +__all__ = () + +def add_backend_cleanup_task(app: Any) -> Any: ... +def add_accumulate_task(app: Any) -> Any: ... +def add_chain_task(app: Any) -> Any: ... +def add_chord_task(app: Any) -> Any: ... +def add_chunk_task(app: Any) -> Any: ... +def add_group_task(app: Any) -> Any: ... +def add_map_task(app: Any) -> Any: ... +def add_starmap_task(app: Any) -> Any: ... +def add_unlock_chord_task(app: Any) -> Any: ... +def connect_on_app_finalize(callback: Any) -> Any: ... diff --git a/celery-stubs/app/control.pyi b/celery-stubs/app/control.pyi index 894c1f2..9cabedb 100644 --- a/celery-stubs/app/control.pyi +++ b/celery-stubs/app/control.pyi @@ -1,6 +1,8 @@ from collections.abc import Callable, Iterable, Mapping, Sequence from typing import Any, Literal, TypeAlias, TypedDict +__all__ = ("Control", "Inspect", "flatten_reply") + from celery.app.base import Celery from celery.result import _State from kombu import Connection @@ -114,20 +116,11 @@ class Inspect: ) -> None | dict[str, dict[str, str]]: ... class Control: - Mailbox: KombuMailbox - app: Celery | None - def __init__(self, app: Celery | None = ...) -> None: ... - def inspect( - self, - destination: _Destination | None = ..., - timeout: float = ..., - callback: Callable[..., Any] | None = ..., - connection: Connection | None = ..., - app: Celery | None = ..., - limit: int | None = ..., - pattern: str | None = ..., - matcher: Callable[..., Any] | None = ..., - ) -> Inspect: ... + Mailbox: type[KombuMailbox] + app: Celery # Required, __init__ immediately accesses app.conf + def __init__(self, app: Celery) -> None: ... + @property + def inspect(self) -> type[Inspect]: ... def purge(self, connection: Connection | None = ...) -> int: ... discard_all = purge def election( @@ -145,6 +138,14 @@ class Control: signal: str = ..., **kwargs: Any, ) -> list[dict[str, _Reply]] | None: ... + def revoke_by_stamped_headers( + self, + headers: Mapping[str, str], + destination: _Destination | None = ..., + terminate: bool = ..., + signal: str = ..., + **kwargs: Any, + ) -> list[dict[str, _Reply]] | None: ... def terminate( self, task_id: str, @@ -227,6 +228,6 @@ class Control: callback: Callable[..., Any] | None = ..., channel: Any | None = ..., pattern: str | None = ..., - matcher: Callable[..., Any] = ..., + matcher: Callable[..., Any] | None = ..., **extra_kwargs: Any, ) -> list[dict[str, _Reply]] | None: ... diff --git a/celery-stubs/app/defaults.pyi b/celery-stubs/app/defaults.pyi new file mode 100644 index 0000000..616a7e0 --- /dev/null +++ b/celery-stubs/app/defaults.pyi @@ -0,0 +1,34 @@ +from builtins import type as _type +from collections.abc import Callable +from typing import Any + +__all__ = ("NAMESPACES", "Option", "find", "flatten") + +class Option: + default: Any + type: str | None + deprecate_by: str | None + remove_by: str | None + alt: tuple[str, ...] | None + old: set[str] + typemap: dict[str, _type] + + def __init__( + self, + default: Any = None, + *args: Any, + **kwargs: Any, + ) -> None: ... + def to_python(self, value: Any) -> Any: ... + +DEFAULTS: dict[str, dict[str, Any]] +NAMESPACES: dict[str, dict[str, Option]] +SETTING_KEYS: set[str] + +def find(name: str, namespace: str = "celery") -> tuple[str, Option] | None: ... +def flatten( + d: dict[str, dict[str, Any]], root: str = "", keyfilter: Callable[..., Any] = ... +) -> dict[str, Any]: ... +def strtobool( + term: str | bool | int | None, table: dict[str, bool] | None = None +) -> bool: ... diff --git a/celery-stubs/app/events.pyi b/celery-stubs/app/events.pyi index 8d38281..08038da 100644 --- a/celery-stubs/app/events.pyi +++ b/celery-stubs/app/events.pyi @@ -1 +1,25 @@ -class Events: ... +from typing import Any + +from celery.app.base import Celery + +class Events: + # Class-level configuration + dispatcher_cls: str + receiver_cls: str + state_cls: str + + app: Celery | None + + def __init__(self, app: Celery | None = ...) -> None: ... + @property + def Dispatcher(self) -> type[Any]: ... + @property + def Receiver(self) -> type[Any]: ... + @property + def State(self) -> type[Any]: ... + def default_dispatcher( + self, + hostname: str | None = None, + enabled: bool = True, + buffer_while_offline: bool = False, + ) -> Any: ... diff --git a/celery-stubs/app/log.pyi b/celery-stubs/app/log.pyi index 8eb4e2c..b4247b5 100644 --- a/celery-stubs/app/log.pyi +++ b/celery-stubs/app/log.pyi @@ -1,8 +1,7 @@ from logging import Logger, LogRecord -from typing import Any +from typing import Any, ClassVar from celery.app.base import Celery -from celery.local import class_property from celery.utils.log import ColorFormatter, LoggingProxy from celery.utils.term import colored from typing_extensions import override @@ -60,7 +59,7 @@ class Logging: ) -> bool: ... def colored( self, logfile: Any | None = ..., enabled: bool | None = ... - ) -> colored: ... + ) -> colored: ... # ty: ignore[invalid-type-form] def setup_handlers( self, logger: Logger, @@ -71,7 +70,4 @@ class Logging: **kwargs: Any, ) -> Logger: ... def get_default_logger(self, name: str = ..., **kwargs: Any) -> Logger: ... - @class_property - def already_setup(self) -> bool: ... # pyright: ignore[reportRedeclaration] - @already_setup.setter # type: ignore[no-redef] - def already_setup(self, was_setup: bool) -> None: ... + already_setup: ClassVar[bool] diff --git a/celery-stubs/app/registry.pyi b/celery-stubs/app/registry.pyi index 50e46d9..48bd26a 100644 --- a/celery-stubs/app/registry.pyi +++ b/celery-stubs/app/registry.pyi @@ -1,3 +1,16 @@ from typing import Any -class TaskRegistry(dict[str, Any]): ... +__all__ = ("TaskRegistry",) + +from celery.app.task import Task +from celery.exceptions import NotRegistered + +class TaskRegistry(dict[str, Task[Any, Any]]): + NotRegistered: type[NotRegistered] + + def __missing__(self, key: str) -> Task[Any, Any]: ... + def filter_types(self, type: str) -> dict[str, Task[Any, Any]]: ... + def periodic(self) -> dict[str, Task[Any, Any]]: ... + def register(self, task: Task[Any, Any]) -> Task[Any, Any]: ... + def regular(self) -> dict[str, Task[Any, Any]]: ... + def unregister(self, name: str) -> None: ... diff --git a/celery-stubs/app/routes.pyi b/celery-stubs/app/routes.pyi index 571fb12..c6ea041 100644 --- a/celery-stubs/app/routes.pyi +++ b/celery-stubs/app/routes.pyi @@ -1 +1,50 @@ -class Router: ... +from typing import Any + +__all__ = ("MapRoute", "Router", "expand_router_string", "prepare") + +from celery.app.base import Celery +from celery.app.task import Task + +def expand_router_string(router: str) -> Any: ... +def prepare(routes: list[Any] | tuple[Any, ...] | None) -> list[Any]: ... + +class MapRoute: + def __init__(self, map: dict[str, Any]) -> None: ... + def __call__( + self, name: str, *args: Any, **kwargs: Any + ) -> dict[str, Any] | None: ... + +class Router: + def __init__( + self, + routes: Any = ..., + queues: Any = ..., + create_missing: bool = ..., + app: Celery | None = ..., + ) -> None: ... + def expand_destination(self, route: dict[str, Any]) -> dict[str, Any]: ... + def lookup_route( + self, + name: str, + args: tuple[Any, ...] | None = None, + kwargs: dict[str, Any] | None = None, + options: dict[str, Any] | None = None, + task_type: type[Task[Any, Any]] | None = None, + ) -> dict[str, Any] | None: ... + def query_router( + self, + router: Any, + task: str, + args: tuple[Any, ...], + kwargs: dict[str, Any], + options: dict[str, Any], + task_type: type[Task[Any, Any]] | None, + ) -> dict[str, Any] | None: ... + def route( + self, + options: dict[str, Any], + name: str, + args: tuple[Any, ...] = (), + kwargs: dict[str, Any] | None = None, + task_type: type[Task[Any, Any]] | None = None, + ) -> dict[str, Any]: ... diff --git a/celery-stubs/app/task.pyi b/celery-stubs/app/task.pyi index 83bf831..8bf45ab 100644 --- a/celery-stubs/app/task.pyi +++ b/celery-stubs/app/task.pyi @@ -8,6 +8,8 @@ from typing import ( overload, ) +__all__ = ("Context", "Task") + import billiard import celery import celery.result @@ -58,6 +60,8 @@ class Context: taskset: str | None # compat alias to group timelimit: tuple[int, int] | tuple[None, None] | None utc: bool | None + stamped_headers: list[str] | None + stamps: dict[str, Any] | None def __init__(self, *args: dict[str, Any], **kwargs: Any) -> None: ... def update(self, *args: dict[str, Any], **kwargs: Any) -> None: ... def clear(self) -> None: ... @@ -67,7 +71,19 @@ class Context: def children(self) -> list[str]: ... class Task(Generic[_P, _R_co]): - name: str + # Class-level references + MaxRetriesExceededError: type[Exception] + OperationalError: type[Exception] + Request: str + Strategy: str + + # Flags + __bound__: bool + __trace__: Any + __v2_compat__: bool + + # Task configuration + name: str # None at class level, always set on instances typing: bool max_retries: int | None default_retry_delay: int @@ -81,15 +97,23 @@ class Task(Generic[_P, _R_co]): soft_time_limit: int | None autoregister: bool track_started: bool - acks_late: bool - acks_on_failure_or_timeout: bool - reject_on_worker_lost: bool + acks_late: bool # None at class level, resolved from config on instances + acks_on_failure_or_timeout: ( + bool # None at class level, resolved from config on instances + ) + reject_on_worker_lost: bool | None throws: tuple[type[Exception], ...] expires: float | datetime | None priority: int | None resultrepr_maxsize: int request_stack: _LocalStack[Context] abstract: bool + store_eager_result: bool + + # Config mapping + from_config: tuple[tuple[str, str], ...] + + def on_replace(self, sig: Signature[Any]) -> None: ... @classmethod def bind(cls, app: Celery) -> Celery: ... @classmethod @@ -143,7 +167,7 @@ class Task(Generic[_P, _R_co]): def signature_from_request( self, request: Context | None = ..., - args: tuple[Any, ...] = ..., + args: tuple[Any, ...] | None = ..., kwargs: dict[str, Any] | None = ..., queue: str | None = ..., **extra_options: Any, @@ -201,13 +225,75 @@ class Task(Generic[_P, _R_co]): priority: int = ..., ) -> EagerResult[_R_co]: ... def AsyncResult( - self, task_id: str, **kwargs: Any + self, + task_id: str, + *, + backend: Any | None = ..., + app: Any | None = ..., + parent: celery.result.AsyncResult[Any] | None = ..., + **kwargs: Any, ) -> celery.result.AsyncResult[_R_co]: ... def signature( - self, args: tuple[Any, ...] | None = ..., *starargs: Any, **starkwargs: Any + self, + args: tuple[Any, ...] | None = ..., + kwargs: dict[str, Any] | None = ..., + *, + # Signature options + options: dict[str, Any] | None = ..., + type: Any | None = ..., + subtask_type: Any | None = ..., + immutable: bool = ..., + app: Celery | None = ..., + task_id: str | None = ..., + countdown: float = ..., + eta: datetime | None = ..., + expires: float | datetime = ..., + retry: bool = ..., + retry_policy: Mapping[str, Any] = ..., + queue: str = ..., + exchange: str = ..., + routing_key: str = ..., + priority: int = ..., + serializer: str = ..., + compression: str = ..., + add_to_parent: bool = ..., + headers: dict[str, str] = ..., + link: Signature[Any] | None = ..., + link_error: Signature[Any] | None = ..., + shadow: str | None = ..., + ignore_result: bool = ..., + **starkwargs: Any, ) -> Signature[_R_co]: ... def subtask( - self, args: tuple[Any, ...] | None = ..., *starargs: Any, **starkwargs: Any + self, + args: tuple[Any, ...] | None = ..., + kwargs: dict[str, Any] | None = ..., + *, + # Signature options + options: dict[str, Any] | None = ..., + type: Any | None = ..., + subtask_type: Any | None = ..., + immutable: bool = ..., + app: Celery | None = ..., + task_id: str | None = ..., + countdown: float = ..., + eta: datetime | None = ..., + expires: float | datetime = ..., + retry: bool = ..., + retry_policy: Mapping[str, Any] = ..., + queue: str = ..., + exchange: str = ..., + routing_key: str = ..., + priority: int = ..., + serializer: str = ..., + compression: str = ..., + add_to_parent: bool = ..., + headers: dict[str, str] = ..., + link: Signature[Any] | None = ..., + link_error: Signature[Any] | None = ..., + shadow: str | None = ..., + ignore_result: bool = ..., + **starkwargs: Any, ) -> Signature[_R_co]: ... def s(self, *args: Any, **kwargs: Any) -> Signature[_R_co]: ... def si(self, *args: _P.args, **kwargs: _P.kwargs) -> Signature[_R_co]: ... diff --git a/celery-stubs/app/trace.pyi b/celery-stubs/app/trace.pyi new file mode 100644 index 0000000..5a729fb --- /dev/null +++ b/celery-stubs/app/trace.pyi @@ -0,0 +1,93 @@ +from collections.abc import Callable +from logging import Logger +from typing import Any + +__all__ = ( + "TraceInfo", + "build_tracer", + "reset_worker_optimizations", + "setup_worker_optimizations", + "trace_task", +) + +from celery.app.base import Celery +from celery.app.task import Task + +class TraceInfo: + state: str + retval: Any + + def __init__(self, state: str, retval: Any = None) -> None: ... + def handle_error_state( + self, + task: Task[..., Any], + req: Any, + eager: bool = False, + call_errbacks: bool = True, + ) -> None: ... + def handle_failure( + self, + task: Task[..., Any], + req: Any, + store_errors: bool = True, + call_errbacks: bool = True, + ) -> None: ... + def handle_ignore(self, task: Task[..., Any], req: Any) -> None: ... + def handle_reject(self, task: Task[..., Any], req: Any, **kwargs: Any) -> None: ... + def handle_retry( + self, + task: Task[..., Any], + req: Any, + store_errors: bool = True, + **kwargs: Any, + ) -> None: ... + +def build_tracer( + name: str, + task: Task[..., Any], + loader: Any | None = None, + hostname: str | None = None, + store_errors: bool = True, + Info: type = ..., + eager: bool = False, + propagate: bool = False, + app: Celery | None = None, + monotonic: Callable[[], float] = ..., + trace_ok_t: type = ..., + IGNORE_STATES: frozenset[str] = ..., +) -> Callable[..., Any]: ... +def trace_task( + task: Task[..., Any], + uuid: str, + args: tuple[Any, ...], + kwargs: dict[str, Any], + request: Any | None = None, + **opts: Any, +) -> TraceInfo: ... +def trace_task_ret( + name: str, + uuid: str, + request: Any, + body: Any, + content_type: str, + content_encoding: str, + loads: Callable[..., Any] = ..., + app: Any = None, + **extra_request: Any, +) -> TraceInfo: ... +def fast_trace_task( + task: Task[..., Any], + uuid: str, + request: Any, + body: Any, + content_type: str, + content_encoding: str, + loads: Callable[..., Any] = ..., + _loc: Any = None, + hostname: str | None = None, + **extra_request: Any, +) -> TraceInfo: ... +def setup_worker_optimizations(app: Celery, hostname: str | None = None) -> None: ... +def reset_worker_optimizations(app: Any = ...) -> None: ... + +logger: Logger diff --git a/celery-stubs/app/utils.pyi b/celery-stubs/app/utils.pyi index 3b93bce..15417ef 100644 --- a/celery-stubs/app/utils.pyi +++ b/celery-stubs/app/utils.pyi @@ -1,3 +1,50 @@ +from collections.abc import Callable +from datetime import tzinfo +from types import ModuleType +from typing import Any + +__all__ = ("Settings", "appstr", "bugreport", "filter_hidden_settings", "find_app") + +from celery.app.base import Celery from celery.utils.collections import ConfigurationView -class Settings(ConfigurationView): ... # type: ignore[misc] # pyright: ignore[reportImplicitAbstractClass] +def appstr(app: Celery) -> str: ... +def bugreport(app: Celery) -> str: ... +def filter_hidden_settings(conf: dict[str, Any]) -> dict[str, Any]: ... +def find_app( + app: str, + symbol_by_name: Callable[[str], Any] = ..., + imp: Callable[[str], ModuleType] | None = ..., +) -> Celery: ... + +class Settings(ConfigurationView): + def __init__( + self, *args: Any, deprecated_settings: set[str] | None = None, **kwargs: Any + ) -> None: ... + @property + def broker_read_url(self) -> str: ... + @property + def broker_url(self) -> str: ... + @property + def broker_write_url(self) -> str: ... + @property + def result_backend(self) -> str: ... + @property + def task_default_exchange(self) -> str: ... + @property + def task_default_routing_key(self) -> str: ... + @property + def timezone(self) -> tzinfo: ... + def finalize(self) -> None: ... + def find_option(self, name: str, namespace: str = "") -> tuple[str, Any]: ... + def find_value_for_key(self, name: str, namespace: str = "celery") -> Any: ... + def get_by_parts(self, *parts: str) -> Any: ... + def humanize( + self, with_defaults: bool = False, censored: bool = True + ) -> dict[str, Any]: ... + def maybe_warn_deprecated_settings(self) -> None: ... + def table( + self, with_defaults: bool = False, censored: bool = True + ) -> dict[str, Any]: ... + def value_set_for(self, key: str) -> bool: ... + def without_defaults(self) -> dict[str, Any]: ... diff --git a/celery-stubs/apps/beat.pyi b/celery-stubs/apps/beat.pyi new file mode 100644 index 0000000..4ac3b1e --- /dev/null +++ b/celery-stubs/apps/beat.pyi @@ -0,0 +1,36 @@ +from typing import Any + +__all__ = ("Beat",) + +from celery.app.base import Celery +from celery.beat import Service as BeatService + +class Beat: + Service: type[BeatService] + app: Celery | None + + def __init__( + self, + max_interval: int | None = None, + app: Celery | None = None, + socket_timeout: int = 30, + pidfile: str | None = None, + no_color: bool | None = None, + loglevel: str = "WARN", + logfile: str | None = None, + schedule: str | None = None, + scheduler: str | None = None, + scheduler_cls: str | None = None, + redirect_stdouts: bool | None = None, + redirect_stdouts_level: str | None = None, + quiet: bool = False, + **kwargs: Any, + ) -> None: ... + def banner(self, service: BeatService) -> str: ... + def init_loader(self) -> None: ... + def install_sync_handler(self, service: BeatService) -> None: ... + def run(self) -> None: ... + def set_process_title(self) -> None: ... + def setup_logging(self, colorize: bool | None = None) -> None: ... + def start_scheduler(self) -> BeatService: ... + def startup_info(self, service: BeatService) -> str: ... diff --git a/celery-stubs/apps/multi.pyi b/celery-stubs/apps/multi.pyi new file mode 100644 index 0000000..628b543 --- /dev/null +++ b/celery-stubs/apps/multi.pyi @@ -0,0 +1,141 @@ +from abc import ABCMeta +from collections import UserList +from collections.abc import Callable, Sequence +from signal import Signals +from typing import Any, TypeAlias + +from typing_extensions import override + +__all__ = ("Cluster", "Node") + +class Cluster(UserList[Node], metaclass=ABCMeta): + name: str + nodes: list[Node] + + def __init__( + self, + nodes: list[str], + cmd: str | None = None, + env: dict[str, str] | None = None, + on_stopping_preamble: Callable[..., Any] | None = None, + on_send_signal: Callable[..., Any] | None = None, + on_still_waiting_for: Callable[..., Any] | None = None, + on_still_waiting_progress: Callable[..., Any] | None = None, + on_still_waiting_end: Callable[..., Any] | None = None, + on_node_start: Callable[..., Any] | None = None, + on_node_restart: Callable[..., Any] | None = None, + on_node_shutdown_ok: Callable[..., Any] | None = None, + on_node_status: Callable[..., Any] | None = None, + on_node_signal: Callable[..., Any] | None = None, + on_node_signal_dead: Callable[..., Any] | None = None, + on_node_down: Callable[..., Any] | None = None, + on_child_spawn: Callable[..., Any] | None = None, + on_child_signalled: Callable[..., Any] | None = None, + on_child_failure: Callable[..., Any] | None = None, + ) -> None: ... + def start(self) -> None: ... + def stop( + self, + retry: int | None = None, + callback: Callable[..., Any] | None = None, + sig: Signals = ..., + ) -> None: ... + def stopwait( + self, + retry: int = 2, + callback: Callable[..., Any] | None = None, + sig: Signals = ..., + ) -> None: ... + def restart(self, sig: Signals = ...) -> None: ... + def kill(self) -> None: ... + @property + @override + def data(self) -> list[Node]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleVariableOverride] # override UserList.data + def find(self, name: str) -> Node | None: ... + def getpids(self, on_down: Callable[..., Any] | None = None) -> dict[str, int]: ... + def send_all(self, sig: Signals) -> None: ... + def shutdown_nodes( + self, + nodes: Sequence[Node], + sig: Signals = ..., + retry: int | None = None, + ) -> None: ... + def start_node(self, node: Node) -> int: ... + +class Node: + name: str + cmd: str | None + append: str | None + options: dict[str, Any] + extra_args: Sequence[str] + pid: int | None + + def __init__( + self, + name: str, + cmd: str | None = None, + append: str | None = None, + options: dict[str, Any] | None = None, + extra_args: Sequence[str] | None = None, + ) -> None: ... + def alive(self) -> bool: ... + def send( + self, sig: int, on_error: Callable[[Exception], Any] | None = None + ) -> bool: ... + def start(self, env: dict[str, str] | None = None, **kwargs: Any) -> int: ... + @classmethod + def from_kwargs(cls, name: str, **kwargs: Any) -> Node: ... + def getopt(self, option: str) -> str | None: ... + def handle_process_exit( + self, + retcode: int, + on_signalled: Callable[[int], Any] | None = None, + on_failure: Callable[[int], Any] | None = None, + ) -> None: ... + def prepare_argv(self, argv: list[str], path: str) -> list[str]: ... + @property + def argv_with_executable(self) -> list[str]: ... + @property + def executable(self) -> str: ... + @property + def logfile(self) -> str | None: ... + @property + def pidfile(self) -> str | None: ... + +# Type alias for use inside MultiParser where the class attribute shadows the module-level class +_Node: TypeAlias = Node + +class MultiParser: + Node: type # type[Node] at runtime + cmd: str + append: str + prefix: str + suffix: str + range_prefix: str + + def __init__( + self, + cmd: str = "celery worker", + append: str = "", + prefix: str = "", + suffix: str = "", + range_prefix: str = "celery", + ) -> None: ... + def parse(self, p: list[str]) -> tuple[list[_Node], list[str]]: ... + +class NamespacedOptionParser: + args: list[str] + options: dict[str, dict[str, Any]] + values: list[str] + passthrough: str + + def __init__(self, args: list[str]) -> None: ... + def add_option( + self, name: str, value: str, short: bool = False, ns: str | None = None + ) -> None: ... + def optmerge( + self, ns: str, defaults: dict[str, Any] | None = None + ) -> dict[str, Any]: ... + def parse(self) -> tuple[dict[str, dict[str, Any]], list[str]]: ... + def process_long_opt(self, arg: str, value: str | None = None) -> None: ... + def process_short_opt(self, arg: str, value: str | None = None) -> None: ... diff --git a/celery-stubs/apps/worker.pyi b/celery-stubs/apps/worker.pyi index 0e7a25c..6604dc7 100644 --- a/celery-stubs/apps/worker.pyi +++ b/celery-stubs/apps/worker.pyi @@ -1,3 +1,36 @@ +from typing import Any + +__all__ = ("Worker",) + from celery.worker import WorkController +from typing_extensions import override -class Worker(WorkController): ... +class Worker(WorkController): + def emit_banner(self) -> None: ... + def extra_info(self) -> str: ... + def install_platform_tweaks(self, worker: WorkController) -> None: ... + def macOS_proxy_detection_workaround(self) -> None: ... + @override + def on_after_init( + self, + purge: bool = False, + no_color: bool | None = None, + redirect_stdouts: bool | None = None, + redirect_stdouts_level: str | None = None, + **kwargs: Any, + ) -> None: ... + @override + def on_before_init(self, quiet: bool = False, **kwargs: Any) -> None: ... + @override + def on_consumer_ready(self, consumer: Any) -> None: ... + @override + def on_init_blueprint(self) -> None: ... + @override + def on_start(self) -> None: ... + def purge_messages(self) -> int: ... + def set_process_status(self, info: str) -> None: ... + def setup_logging(self, colorize: bool | None = None) -> None: ... + def startup_info(self, artlines: bool = True) -> str: ... + def tasklist( + self, include_builtins: bool = True, sep: str = "\n", int_: str = "celery." + ) -> str: ... diff --git a/celery-stubs/backends/arangodb.pyi b/celery-stubs/backends/arangodb.pyi new file mode 100644 index 0000000..fd3640e --- /dev/null +++ b/celery-stubs/backends/arangodb.pyi @@ -0,0 +1,24 @@ +from typing import Any + +from celery.backends.base import KeyValueStoreBackend + +__all__ = ("ArangoDbBackend",) + +class ArangoDbBackend(KeyValueStoreBackend): + host: str + port: str + database: str + collection: str + http_protocol: str + username: str | None + password: str | None + verify: bool + key_t: type[str] # type: ignore[assignment] # pyright: ignore[reportIncompatibleMethodOverride] + + @property + def connection(self) -> Any: ... + @property + def db(self) -> Any: ... + @property + def expires_delta(self) -> float: ... + def __init__(self, url: str | None = None, *args: Any, **kwargs: Any) -> None: ... diff --git a/celery-stubs/backends/asynchronous.pyi b/celery-stubs/backends/asynchronous.pyi new file mode 100644 index 0000000..dcd9fc6 --- /dev/null +++ b/celery-stubs/backends/asynchronous.pyi @@ -0,0 +1,72 @@ +from collections.abc import Callable +from typing import Any + +from celery.backends.base import Backend + +__all__ = ("AsyncBackendMixin", "BaseResultConsumer", "Drainer", "register_drainer") + +def register_drainer(name: str) -> Callable[[type[Drainer]], type[Drainer]]: ... + +class Drainer: + def __init__(self, result_consumer: BaseResultConsumer) -> None: ... + def start(self) -> None: ... + def stop(self) -> None: ... + def drain_events_until( + self, + p: Callable[[], bool], + timeout: float | None = None, + interval: float = 1, + on_interval: Callable[[], None] | None = None, + wait: Callable[[float], None] | None = None, + ) -> None: ... + def wait_for( + self, + p: Callable[[], bool], + wait: Callable[[float], None], + timeout: float | None = None, + ) -> None: ... + +class AsyncBackendMixin: + @property + def is_async(self) -> bool: ... + def wait_for_pending( + self, + result: Any, + callback: Callable[..., Any] | None = None, + propagate: bool = True, + **kwargs: Any, + ) -> Any: ... + def add_pending_result( + self, result: Any, weak: bool = False, start_drainer: bool = True + ) -> Any: ... + def add_pending_results(self, results: list[Any], weak: bool = False) -> None: ... + def remove_pending_result(self, result: Any) -> None: ... + def on_result_fulfilled(self, result: Any) -> None: ... + def iter_native(self, result: Any, no_ack: bool = True, **kwargs: Any) -> Any: ... + +class BaseResultConsumer: + def __init__( + self, + backend: Backend, + app: Any, + accept: Any, + pending_results: Any, + pending_messages: Any, + ) -> None: ... + def start(self, initial_task_id: str, **kwargs: Any) -> None: ... + def stop(self) -> None: ... + def drain_events(self, timeout: float | None = None) -> None: ... + def drain_events_until( + self, + p: Callable[[], bool], + timeout: float | None = None, + on_interval: Callable[[], None] | None = None, + ) -> None: ... + def consume_from(self, task_id: str) -> None: ... + def cancel_for(self, task_id: str) -> None: ... + def on_state_change(self, meta: dict[str, Any], message: Any) -> None: ... + def on_after_fork(self) -> None: ... + def on_out_of_band_result(self, message: Any) -> None: ... + def on_wait_for_pending( + self, result: Any, timeout: float | None = None, **kwargs: Any + ) -> None: ... diff --git a/celery-stubs/backends/azureblockblob.pyi b/celery-stubs/backends/azureblockblob.pyi new file mode 100644 index 0000000..5f66fc2 --- /dev/null +++ b/celery-stubs/backends/azureblockblob.pyi @@ -0,0 +1,14 @@ +from typing import Any + +from celery.backends.base import KeyValueStoreBackend + +__all__ = ("AzureBlockBlobBackend",) + +class AzureBlockBlobBackend(KeyValueStoreBackend): + def __init__( + self, + url: str | None = None, + container_name: str | None = None, + connection_string: str | None = None, + **kwargs: Any, + ) -> None: ... diff --git a/celery-stubs/backends/base.pyi b/celery-stubs/backends/base.pyi index 6c13350..be63877 100644 --- a/celery-stubs/backends/base.pyi +++ b/celery-stubs/backends/base.pyi @@ -2,7 +2,10 @@ from collections.abc import Callable from datetime import timedelta from typing import Any, NamedTuple +__all__ = ("BaseBackend", "DisabledBackend", "KeyValueStoreBackend") + from celery.app.task import Context +from celery.exceptions import TimeoutError as CeleryTimeoutError from celery.result import ResultSet from typing_extensions import override @@ -15,6 +18,8 @@ class Backend: UNREADY_STATES: frozenset[str] EXCEPTION_STATES: frozenset[str] + TimeoutError: type[CeleryTimeoutError] + subpolling_interval: float | None supports_native_join: bool supports_autoexpire: bool @@ -92,8 +97,49 @@ class Backend: self, header_result_args: tuple[Any, Any], body: Any, **kwargs: Any ) -> None: ... def current_task_children(self, request: Context | None = ...) -> list[Any]: ... + def add_to_chord(self, chord_id: str, result: Any) -> None: ... + def chord_error_from_stack( + self, callback: Any, exc: Exception | None = None + ) -> Exception: ... + def decode(self, payload: bytes) -> Any: ... + def decode_result(self, payload: bytes) -> Any: ... + def delete_group(self, group_id: str) -> None: ... + def encode(self, data: Any) -> bytes: ... + def encode_result(self, result: Any, state: str) -> bytes: ... + def ensure_chords_allowed(self) -> None: ... + def exception_safe_to_retry(self, exc: Exception) -> bool: ... + def exception_to_python(self, exc: Any) -> Exception: ... + def fail_from_current_stack( + self, task_id: str, exc: Exception | None = None + ) -> None: ... + def fallback_chord_unlock( + self, header_result: Any, body: Any, countdown: int = 1, **kwargs: Any + ) -> None: ... + def get_status(self, task_id: str) -> str: ... + def get_task_meta(self, task_id: str, cache: bool = True) -> dict[str, Any]: ... + def get_traceback(self, task_id: str) -> str | None: ... + def is_cached(self, task_id: str) -> bool: ... + def meta_from_decoded(self, meta: dict[str, Any]) -> dict[str, Any]: ... + def on_chord_part_return( + self, request: Any, state: str, result: Any, **kwargs: Any + ) -> None: ... + def on_task_call(self, producer: Any, task_id: str) -> None: ... + def prepare_exception( + self, exc: Exception, serializer: str | None = None + ) -> Any: ... + def prepare_expires( + self, value: float | timedelta | None, type: type | None = None + ) -> float | None: ... + def prepare_persistent(self, enabled: bool | None = None) -> bool: ... + def prepare_value(self, result: Any) -> Any: ... + def save_group(self, group_id: str, result: Any) -> None: ... + def set_chord_size(self, group_id: str, chord_size: int) -> None: ... class SyncBackendMixin: + @property + def is_async(self) -> bool: ... + def add_pending_result(self, result: Any, weak: bool = False) -> Any: ... + def remove_pending_result(self, result: Any) -> None: ... def iter_native( self, result: ResultSet, @@ -126,14 +172,46 @@ class SyncBackendMixin: class BaseBackend(Backend, SyncBackendMixin): ... class BaseKeyValueStoreBackend(Backend): + chord_keyprefix: str + group_keyprefix: str + task_keyprefix: str + implements_incr: bool + key_t: Callable[[str], bytes] def get(self, key: str) -> Any: ... def mget(self, keys: list[str]) -> list[Any]: ... def set(self, key: str, value: Any) -> None: ... def delete(self, key: str) -> None: ... def incr(self, key: str) -> int: ... + def expire(self, key: str, value: int) -> None: ... + def get_key_for_chord(self, group_id: str, key: str = "") -> str: ... + def get_key_for_group(self, group_id: str, key: str = "") -> str: ... + def get_key_for_task(self, task_id: str, key: str = "") -> str: ... + def get_many( + self, + task_ids: list[str], + timeout: float | None = None, + interval: float = 0.5, + no_ack: bool = True, + on_message: Callable[[Any], None] | None = None, + on_interval: Callable[[], None] | None = None, + max_iterations: int | None = None, + READY_STATES: frozenset[str] = ..., + ) -> Any: ... + @override + def on_chord_part_return( + self, request: Any, state: str, result: Any, **kwargs: Any + ) -> None: ... class KeyValueStoreBackend(BaseKeyValueStoreBackend, SyncBackendMixin): ... class DisabledBackend(BaseBackend): @override def store_result(self, *args: Any, **kwargs: Any) -> None: ... + @override + def ensure_chords_allowed(self) -> None: ... + def get_many(self, *args: Any, **kwargs: Any) -> Any: ... + @override + def get_status(self, *args: Any, **kwargs: Any) -> str: ... + def get_task_meta_for(self, *args: Any, **kwargs: Any) -> Any: ... + @override + def get_traceback(self, *args: Any, **kwargs: Any) -> str | None: ... diff --git a/celery-stubs/backends/cache.pyi b/celery-stubs/backends/cache.pyi new file mode 100644 index 0000000..592841a --- /dev/null +++ b/celery-stubs/backends/cache.pyi @@ -0,0 +1,21 @@ +from typing import Any + +from celery.backends.base import KeyValueStoreBackend + +__all__ = ("CacheBackend",) + +class CacheBackend(KeyValueStoreBackend): + servers: list[str] | None + supports_native_join: bool + + @property + def client(self) -> Any: ... + def __init__( + self, + app: Any, + expires: float | None = None, + backend: str | None = None, + options: dict[str, Any] | None = None, + url: str | None = None, + **kwargs: Any, + ) -> None: ... diff --git a/celery-stubs/backends/cassandra.pyi b/celery-stubs/backends/cassandra.pyi new file mode 100644 index 0000000..a7cca25 --- /dev/null +++ b/celery-stubs/backends/cassandra.pyi @@ -0,0 +1,20 @@ +from typing import Any + +from celery.backends.base import Backend + +__all__ = ("CassandraBackend",) + +class CassandraBackend(Backend): + servers: list[str] | None + bundle_path: str | None + + def __init__( + self, + servers: list[str] | None = None, + keyspace: str | None = None, + table: str | None = None, + entry_ttl: int | None = None, + port: int | None = None, + bundle_path: str | None = None, + **kwargs: Any, + ) -> None: ... diff --git a/celery-stubs/backends/consul.pyi b/celery-stubs/backends/consul.pyi new file mode 100644 index 0000000..5e8a9f0 --- /dev/null +++ b/celery-stubs/backends/consul.pyi @@ -0,0 +1,14 @@ +from typing import Any + +from celery.backends.base import KeyValueStoreBackend + +__all__ = ("ConsulBackend",) + +class ConsulBackend(KeyValueStoreBackend): + consistency: str + path: str | None + consul: Any + + @property + def client(self) -> Any: ... + def __init__(self, *args: Any, **kwargs: Any) -> None: ... diff --git a/celery-stubs/backends/cosmosdbsql.pyi b/celery-stubs/backends/cosmosdbsql.pyi new file mode 100644 index 0000000..0f64802 --- /dev/null +++ b/celery-stubs/backends/cosmosdbsql.pyi @@ -0,0 +1,18 @@ +from typing import Any + +from celery.backends.base import KeyValueStoreBackend + +__all__ = ("CosmosDBSQLBackend",) + +class CosmosDBSQLBackend(KeyValueStoreBackend): + def __init__( + self, + url: str | None = None, + database_name: str | None = None, + collection_name: str | None = None, + consistency_level: str | None = None, + max_retry_attempts: int | None = None, + max_retry_wait_time: int | None = None, + *args: Any, + **kwargs: Any, + ) -> None: ... diff --git a/celery-stubs/backends/couchbase.pyi b/celery-stubs/backends/couchbase.pyi new file mode 100644 index 0000000..a125ab6 --- /dev/null +++ b/celery-stubs/backends/couchbase.pyi @@ -0,0 +1,19 @@ +from typing import Any + +from celery.backends.base import KeyValueStoreBackend + +__all__ = ("CouchbaseBackend",) + +class CouchbaseBackend(KeyValueStoreBackend): + bucket: str + host: str + port: int + username: str | None + password: str | None + quiet: bool + timeout: float + key_t: type[str] # type: ignore[assignment] # pyright: ignore[reportIncompatibleMethodOverride] + + @property + def connection(self) -> Any: ... + def __init__(self, url: str | None = None, *args: Any, **kwargs: Any) -> None: ... diff --git a/celery-stubs/backends/couchdb.pyi b/celery-stubs/backends/couchdb.pyi new file mode 100644 index 0000000..a409cd6 --- /dev/null +++ b/celery-stubs/backends/couchdb.pyi @@ -0,0 +1,21 @@ +from typing import Any + +from celery.backends.base import Backend + +__all__ = ("CouchBackend",) + +class CouchBackend(Backend): + host: str + port: int + container: str + username: str | None + password: str | None + scheme: str + + @property + def connection(self) -> Any: ... + def __init__(self, url: str | None = None, *args: Any, **kwargs: Any) -> None: ... + def get(self, key: str) -> Any: ... + def set(self, key: str, value: Any) -> None: ... + def mget(self, keys: list[str]) -> list[Any]: ... + def delete(self, key: str) -> None: ... diff --git a/celery-stubs/backends/database/__init__.pyi b/celery-stubs/backends/database/__init__.pyi new file mode 100644 index 0000000..67ee6bf --- /dev/null +++ b/celery-stubs/backends/database/__init__.pyi @@ -0,0 +1,21 @@ +from typing import Any + +from celery.backends.base import Backend +from celery.backends.database.models import Task, TaskSet + +__all__ = ("DatabaseBackend",) + +class DatabaseBackend(Backend): + task_cls: type[Task] + taskset_cls: type[TaskSet] + + @property + def extended_result(self) -> bool: ... + def ResultSession(self, session_manager: Any | None = None) -> Any: ... + def __init__( + self, + dburi: str | None = None, + engine_options: dict[str, Any] | None = None, + url: str | None = None, + **kwargs: Any, + ) -> None: ... diff --git a/celery-stubs/backends/database/models.pyi b/celery-stubs/backends/database/models.pyi new file mode 100644 index 0000000..1288d92 --- /dev/null +++ b/celery-stubs/backends/database/models.pyi @@ -0,0 +1,54 @@ +from datetime import datetime +from typing import Any, ClassVar + +__all__ = ("Task", "TaskExtended", "TaskSet") + +# Note: These are SQLAlchemy declarative models with DeclarativeMeta metaclass +# stubtest cannot reconcile the InstrumentedAttribute class-level types with +# the instance-level types users actually see. Using plain classes here since +# users access these as regular attributes on instances. + +class Task: + __tablename__: ClassVar[str] + __table_args__: ClassVar[dict[str, Any]] + __table__: ClassVar[Any] + __mapper__: ClassVar[Any] + + id: int | None + task_id: str + status: str + result: bytes | None + date_done: datetime | None + traceback: str | None + + def __init__(self, task_id: str) -> None: ... + def to_dict(self) -> dict[str, Any]: ... + @classmethod + def configure(cls, schema: str | None = None, name: str | None = None) -> None: ... + +class TaskExtended(Task): + name: str | None + args: bytes | None + kwargs: bytes | None + worker: str | None + retries: int | None + queue: str | None + children: bytes | None + + def __init__(self, task_id: str) -> None: ... + +class TaskSet: + __tablename__: ClassVar[str] + __table_args__: ClassVar[dict[str, Any]] + __table__: ClassVar[Any] + __mapper__: ClassVar[Any] + + id: int | None + taskset_id: str + result: bytes | None + date_done: datetime | None + + def __init__(self, taskset_id: str, result: bytes | None) -> None: ... + def to_dict(self) -> dict[str, Any]: ... + @classmethod + def configure(cls, schema: str | None = None, name: str | None = None) -> None: ... diff --git a/celery-stubs/backends/database/session.pyi b/celery-stubs/backends/database/session.pyi new file mode 100644 index 0000000..25177c8 --- /dev/null +++ b/celery-stubs/backends/database/session.pyi @@ -0,0 +1,12 @@ +from typing import Any + +__all__ = ("SessionManager",) + +class SessionManager: + def __init__(self) -> None: ... + def get_engine(self, dburi: str, **kwargs: Any) -> Any: ... + def create_session( + self, dburi: str, short_lived_sessions: bool = False, **kwargs: Any + ) -> Any: ... + def prepare_models(self, engine: Any) -> None: ... + def session_factory(self, dburi: str, **kwargs: Any) -> Any: ... diff --git a/celery-stubs/backends/dynamodb.pyi b/celery-stubs/backends/dynamodb.pyi new file mode 100644 index 0000000..90f1543 --- /dev/null +++ b/celery-stubs/backends/dynamodb.pyi @@ -0,0 +1,23 @@ +from typing import Any + +from celery.backends.base import KeyValueStoreBackend + +__all__ = ("DynamoDBBackend",) + +class DynamoDBBackend(KeyValueStoreBackend): + aws_region: str | None + table_name: str + endpoint_url: str | None + read_capacity_units: int + write_capacity_units: int + time_to_live_seconds: int | None + + @property + def client(self) -> Any: ... + def __init__( + self, + url: str | None = None, + table_name: str | None = None, + *args: Any, + **kwargs: Any, + ) -> None: ... diff --git a/celery-stubs/backends/elasticsearch.pyi b/celery-stubs/backends/elasticsearch.pyi new file mode 100644 index 0000000..300d5a5 --- /dev/null +++ b/celery-stubs/backends/elasticsearch.pyi @@ -0,0 +1,21 @@ +from typing import Any + +from celery.backends.base import KeyValueStoreBackend + +__all__ = ("ElasticsearchBackend",) + +class ElasticsearchBackend(KeyValueStoreBackend): + doc_type: str | None + es_max_retries: int + es_retry_on_timeout: bool + es_timeout: int + host: str + port: int + index: str + scheme: str + username: str | None + password: str | None + + @property + def server(self) -> str: ... + def __init__(self, url: str | None = None, *args: Any, **kwargs: Any) -> None: ... diff --git a/celery-stubs/backends/filesystem.pyi b/celery-stubs/backends/filesystem.pyi new file mode 100644 index 0000000..1295997 --- /dev/null +++ b/celery-stubs/backends/filesystem.pyi @@ -0,0 +1,21 @@ +from collections.abc import Callable +from typing import Any + +from celery.backends.base import KeyValueStoreBackend + +E_NO_PATH_SET: str +E_PATH_INVALID: str +E_PATH_NON_CONFORMING_SCHEME: str +default_encoding: str + +class FilesystemBackend(KeyValueStoreBackend): + def __init__( + self, + url: str | None = None, + open: Callable[..., Any] = ..., + unlink: Callable[[str], None] = ..., + sep: str = "/", + encoding: str = "UTF-8", + *args: Any, + **kwargs: Any, + ) -> None: ... diff --git a/celery-stubs/backends/gcs.pyi b/celery-stubs/backends/gcs.pyi new file mode 100644 index 0000000..57fc29f --- /dev/null +++ b/celery-stubs/backends/gcs.pyi @@ -0,0 +1,10 @@ +from typing import Any + +from celery.backends.base import KeyValueStoreBackend + +__all__ = ("GCSBackend",) + +class GCSBackend(KeyValueStoreBackend): + @property + def firestore_client(self) -> Any: ... + def __init__(self, **kwargs: Any) -> None: ... diff --git a/celery-stubs/backends/mongodb.pyi b/celery-stubs/backends/mongodb.pyi new file mode 100644 index 0000000..61a58f1 --- /dev/null +++ b/celery-stubs/backends/mongodb.pyi @@ -0,0 +1,30 @@ +from typing import Any + +from celery.backends.base import Backend +from typing_extensions import override + +__all__ = ("MongoBackend",) + +class MongoBackend(Backend): + host: str + port: int + database_name: str + taskmeta_collection: str + groupmeta_collection: str + options: dict[str, Any] | None + mongo_host: str | None + max_pool_size: int + user: str | None + password: str | None + + @property + def collection(self) -> Any: ... + @property + def database(self) -> Any: ... + @property + def group_collection(self) -> Any: ... + @property + def expires_delta(self) -> float: ... + def __init__(self, app: Any = None, **kwargs: Any) -> None: ... + @override + def decode(self, data: Any) -> Any: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] diff --git a/celery-stubs/backends/redis.pyi b/celery-stubs/backends/redis.pyi new file mode 100644 index 0000000..975e567 --- /dev/null +++ b/celery-stubs/backends/redis.pyi @@ -0,0 +1,55 @@ +from collections.abc import Callable, Iterable +from types import ModuleType +from typing import Any + +from celery.backends.asynchronous import BaseResultConsumer +from celery.backends.base import KeyValueStoreBackend +from kombu.utils.objects import cached_property +from typing_extensions import override + +__all__ = ("RedisBackend", "SentinelBackend") + +class RedisBackend(KeyValueStoreBackend): + ResultConsumer: type[BaseResultConsumer] + connection_class_ssl: type[Any] + max_connections: int | None + redis: Any # redis module + + retry_policy: cached_property[dict[str, Any]] # pyright: ignore[reportIncompatibleVariableOverride] + + @property + def ConnectionPool(self) -> Any: ... + @property + def client(self) -> Any: ... + def __init__( + self, + host: str | None = None, + port: int | None = None, + db: int | None = None, + password: str | None = None, + max_connections: int | None = None, + url: str | None = None, + connection_pool: Any | None = None, + **kwargs: Any, + ) -> None: ... + def ensure( + self, fun: Callable[..., Any], args: tuple[Any, ...], **policy: Any + ) -> Any: ... + def on_connection_error( + self, max_retries: int, exc: Exception, intervals: Iterable[float], retries: int + ) -> None: ... + @override + def add_to_chord(self, group_id: str, result: Any) -> None: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + @override + def on_chord_part_return( + self, + request: Any, + state: str, + result: Any, + propagate: bool | None = None, + **kwargs: Any, + ) -> None: ... + +class SentinelBackend(RedisBackend): + sentinel: ModuleType # redis.sentinel module + def __init__(self, *args: Any, **kwargs: Any) -> None: ... diff --git a/celery-stubs/backends/rpc.pyi b/celery-stubs/backends/rpc.pyi new file mode 100644 index 0000000..8da1123 --- /dev/null +++ b/celery-stubs/backends/rpc.pyi @@ -0,0 +1,49 @@ +from typing import Any + +import kombu +from celery.backends.asynchronous import BaseResultConsumer +from celery.backends.base import Backend +from kombu.utils.objects import cached_property +from typing_extensions import override + +__all__ = ("BacklogLimitExceeded", "RPCBackend") + +class BacklogLimitExceeded(Exception): ... + +class RPCBackend(Backend): + BacklogLimitExceeded: type[BacklogLimitExceeded] + Consumer: type[kombu.Consumer] + Exchange: type[kombu.Exchange] + Producer: type[kombu.Producer] + Queue: type[kombu.Queue] + ResultConsumer: type[BaseResultConsumer] + + oid: cached_property[str] + + @property + def binding(self) -> kombu.Queue: ... + def __init__( + self, + app: Any, + connection: Any | None = None, + exchange: str | None = None, + exchange_type: str | None = None, + persistent: bool | None = None, + serializer: str | None = None, + auto_delete: bool = True, + **kwargs: Any, + ) -> None: ... + def destination_for(self, task_id: str, request: Any) -> tuple[str, str]: ... + def on_reply_declare(self, task_id: str) -> Any: ... + def on_result_fulfilled(self, result: Any) -> None: ... + def on_out_of_band_result(self, task_id: str, message: Any) -> None: ... + @override + def get_task_meta( # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + self, task_id: str, backlog_limit: int = 1000 + ) -> dict[str, Any]: ... + def poll( + self, task_id: str, backlog_limit: int = 1000 + ) -> dict[str, Any] | None: ... + @override + def reload_group_result(self, task_id: str) -> Any: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + def revive(self, channel: Any) -> None: ... diff --git a/celery-stubs/backends/s3.pyi b/celery-stubs/backends/s3.pyi new file mode 100644 index 0000000..f189d68 --- /dev/null +++ b/celery-stubs/backends/s3.pyi @@ -0,0 +1,8 @@ +from typing import Any + +from celery.backends.base import KeyValueStoreBackend + +__all__ = ("S3Backend",) + +class S3Backend(KeyValueStoreBackend): + def __init__(self, **kwargs: Any) -> None: ... diff --git a/celery-stubs/beat.pyi b/celery-stubs/beat.pyi index 0cf4b50..0d50840 100644 --- a/celery-stubs/beat.pyi +++ b/celery-stubs/beat.pyi @@ -1,42 +1,172 @@ import shelve +from collections.abc import Callable +from datetime import datetime from threading import Thread -from typing import NamedTuple +from typing import Any, NamedTuple -from billiard.context import Process +import kombu +from celery.app.base import Celery +from celery.schedules import BaseSchedule from typing_extensions import override -__all__ = [ +__all__ = ( + "EmbeddedService", "PersistentScheduler", "ScheduleEntry", "Scheduler", "SchedulingError", "Service", -] +) -class event_t(NamedTuple): ... class SchedulingError(Exception): ... -class BeatLazyFunc: ... + +class BeatLazyFunc: + def __init__(self, func: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... + def __call__(self) -> Any: ... + def delay(self) -> Any: ... class ScheduleEntry: total_run_count: int + name: str | None + task: str | None + last_run_at: datetime | None + schedule: BaseSchedule | None + args: tuple[Any, ...] | None + kwargs: dict[str, Any] | None + options: dict[str, Any] | None + relative: bool + app: Celery | None + + def __init__( + self, + name: str | None = None, + task: str | None = None, + last_run_at: datetime | None = None, + total_run_count: int | None = None, + schedule: BaseSchedule | None = None, + args: tuple[Any, ...] = (), + kwargs: dict[str, Any] | None = None, + options: dict[str, Any] | None = None, + relative: bool = False, + app: Celery | None = None, + ) -> None: ... + def __ge__(self, other: ScheduleEntry) -> bool: ... + def __gt__(self, other: ScheduleEntry) -> bool: ... + def __le__(self, other: ScheduleEntry) -> bool: ... + def __lt__(self, other: ScheduleEntry) -> bool: ... + def __iter__(self) -> ScheduleEntry: ... + def __next__(self, last_run_at: datetime | None = None) -> ScheduleEntry: ... + def default_now(self) -> datetime: ... + def editable_fields_equal(self, other: ScheduleEntry) -> bool: ... + def is_due(self) -> tuple[bool, float]: ... + def next(self, last_run_at: datetime | None = None) -> ScheduleEntry: ... + def update(self, other: ScheduleEntry) -> None: ... + +class event_t(NamedTuple): + time: float + priority: int + entry: ScheduleEntry class Scheduler: - Entry = ScheduleEntry + Entry: type[ScheduleEntry] + app: Celery + schedule: dict[str, ScheduleEntry] + max_interval: int | None + lazy: bool + + def __init__( + self, + app: Celery, + schedule: dict[str, ScheduleEntry] | None = None, + max_interval: int | None = None, + Producer: type[kombu.Producer] | None = None, + lazy: bool = False, + sync_every_tasks: int | None = None, + **kwargs: Any, + ) -> None: ... def setup_schedule(self) -> None: ... def sync(self) -> None: ... def close(self) -> None: ... + def add(self, **kwargs: Any) -> ScheduleEntry: ... + def adjust(self, n: int, drift: float = -0.01) -> float: ... + def apply_async( + self, + entry: ScheduleEntry, + producer: kombu.Producer | None = None, + advance: bool = True, + **kwargs: Any, + ) -> Any: ... + def apply_entry( + self, entry: ScheduleEntry, producer: kombu.Producer | None = None + ) -> Any: ... + @property + def connection(self) -> kombu.Connection: ... + def get_schedule(self) -> dict[str, ScheduleEntry]: ... + @property + def info(self) -> str: ... + def install_default_entries(self, data: dict[str, Any]) -> None: ... + def is_due(self, entry: ScheduleEntry) -> tuple[bool, float]: ... + @property + def logger(self) -> Any: ... + def merge_inplace(self, b: dict[str, ScheduleEntry]) -> None: ... + def populate_heap( + self, event_t: type[event_t] = ..., heapify: Callable[[list[Any]], None] = ... + ) -> None: ... + @property + def producer(self) -> kombu.Producer: ... + def reserve(self, entry: ScheduleEntry) -> event_t: ... + def schedules_equal( + self, + old_schedules: dict[str, ScheduleEntry], + new_schedules: dict[str, ScheduleEntry], + ) -> bool: ... + def send_task(self, *args: Any, **kwargs: Any) -> Any: ... + def set_schedule(self, schedule: dict[str, ScheduleEntry]) -> None: ... + def should_sync(self) -> bool: ... + @property + def sync_every(self) -> int: ... + @property + def sync_every_tasks(self) -> int | None: ... + def tick( + self, + event_t: type[event_t] = ..., + min: Callable[..., Any] = ..., + heappop: Callable[..., Any] = ..., + heappush: Callable[..., Any] = ..., + ) -> float: ... + def update_from_dict(self, dict_: dict[str, Any]) -> None: ... class PersistentScheduler(Scheduler): - persistence = shelve + persistence: type[shelve.Shelf[Any]] + known_suffixes: tuple[str, ...] + @override + def __init__(self, *args: Any, **kwargs: Any) -> None: ... @override def setup_schedule(self) -> None: ... @override def sync(self) -> None: ... @override def close(self) -> None: ... + @override + def get_schedule(self) -> dict[str, ScheduleEntry]: ... + @override + def set_schedule(self, schedule: dict[str, ScheduleEntry]) -> None: ... + @property + @override + def info(self) -> str: ... class Service: - scheduler_cls = PersistentScheduler + scheduler_cls: type[PersistentScheduler] + app: Celery + max_interval: int | None + + def __init__( + self, + app: Celery, + max_interval: int | None = None, + schedule_filename: str | None = None, + scheduler_cls: type[Scheduler] | None = None, + ) -> None: ... def start(self, embedded_process: bool = ...) -> None: ... def sync(self) -> None: ... def stop(self, wait: bool = ...) -> None: ... @@ -49,12 +179,21 @@ class Service: class _Threaded(Thread): daemon: bool name: str + app: Celery + + def __init__(self, app: Celery, **kwargs: Any) -> None: ... @override def run(self) -> None: ... def stop(self) -> None: ... -class _Process(Process): +class _Process: name: str - @override + app: Celery + + def __init__(self, app: Celery, **kwargs: Any) -> None: ... def run(self) -> None: ... def stop(self) -> None: ... + +def EmbeddedService( + app: Celery, max_interval: int | None = None, **kwargs: Any +) -> _Threaded | _Process: ... diff --git a/celery-stubs/bin/__init__.pyi b/celery-stubs/bin/__init__.pyi new file mode 100644 index 0000000..e4c2f88 --- /dev/null +++ b/celery-stubs/bin/__init__.pyi @@ -0,0 +1 @@ +# celery.bin is a package with no public exports at package level diff --git a/celery-stubs/bin/amqp.pyi b/celery-stubs/bin/amqp.pyi new file mode 100644 index 0000000..23e85f5 --- /dev/null +++ b/celery-stubs/bin/amqp.pyi @@ -0,0 +1,5 @@ +import click + +__all__ = ("amqp",) + +amqp: click.Group diff --git a/celery-stubs/bin/base.pyi b/celery-stubs/bin/base.pyi new file mode 100644 index 0000000..57bceb6 --- /dev/null +++ b/celery-stubs/bin/base.pyi @@ -0,0 +1,91 @@ +from collections.abc import Callable, MutableMapping +from datetime import datetime +from typing import Any + +import click +from celery.app.base import Celery +from celery.utils.dispatch.signal import Signal +from kombu.utils.objects import cached_property + +class CeleryOption(click.Option): ... + +class CeleryCommand(click.Command): + app: Celery | None + def __init__( + self, + name: str | None, + context_settings: MutableMapping[str, Any] | None = None, + callback: Callable[..., Any] | None = None, + params: list[click.Parameter] | None = None, + help: str | None = None, + epilog: str | None = None, + short_help: str | None = None, + options_metavar: str | None = "[OPTIONS]", + add_help_option: bool = True, + no_args_is_help: bool = False, + hidden: bool = False, + deprecated: bool = False, + ) -> None: ... + +class CeleryDaemonCommand(CeleryCommand): ... + +class DaemonOption(click.Option): + def daemon_setting( + self, ctx: click.Context, opt: CeleryOption, value: Any + ) -> Any: ... + +class CLIContext: + app: Celery + OK: cached_property[str] + ERROR: cached_property[str] + + def __init__( + self, + app: Celery, + no_color: bool, + workdir: str | None, + quiet: bool = False, + ) -> None: ... + def echo(self, message: str | None = None, **kwargs: Any) -> None: ... + def error(self, message: str | None = None, **kwargs: Any) -> None: ... + def pretty(self, n: Any) -> str: ... + def pretty_dict_ok_error(self, n: dict[str, Any]) -> str: ... + def pretty_list(self, n: list[Any]) -> str: ... + def say_chat( + self, direction: str, title: str, body: str = "", show_body: bool = False + ) -> None: ... + def secho(self, message: str | None = None, **kwargs: Any) -> None: ... + def style(self, message: str | None = None, **kwargs: Any) -> str: ... + +class CommaSeparatedList(click.ParamType): ... +class LogLevel(click.ParamType): ... +class ISO8601DateTime(click.ParamType): ... +class ISO8601DateTimeOrFloat(click.ParamType): ... +class JsonArray(click.ParamType): ... +class JsonObject(click.ParamType): ... + +COMMA_SEPARATED_LIST: CommaSeparatedList +LOG_LEVEL: LogLevel +ISO8601: ISO8601DateTime +ISO8601_OR_FLOAT: ISO8601DateTimeOrFloat +JSON_ARRAY: JsonArray +JSON_OBJECT: JsonObject +FORMATTER: Any # pygments Terminal256Formatter +LEXER: Any # pygments PythonLexer + +def handle_preload_options(f: Callable[..., Any]) -> Callable[..., Any]: ... +def maybe_iso8601(dt: datetime | str | None) -> datetime | None: ... +def get_current_app() -> Celery: ... +def mlevel(level: str | int) -> int: ... +def pformat( + object: Any, + indent: int = 1, + width: int = 80, + depth: int | None = None, + *, + compact: bool = False, + sort_dicts: bool = True, + underscore_numbers: bool = False, +) -> str: ... + +user_preload_options: Signal diff --git a/celery-stubs/bin/beat.pyi b/celery-stubs/bin/beat.pyi new file mode 100644 index 0000000..a1bd970 --- /dev/null +++ b/celery-stubs/bin/beat.pyi @@ -0,0 +1,3 @@ +from celery.bin.base import CeleryDaemonCommand + +beat: CeleryDaemonCommand diff --git a/celery-stubs/bin/call.pyi b/celery-stubs/bin/call.pyi new file mode 100644 index 0000000..db3f69c --- /dev/null +++ b/celery-stubs/bin/call.pyi @@ -0,0 +1,3 @@ +from celery.bin.base import CeleryCommand + +call: CeleryCommand diff --git a/celery-stubs/bin/celery.pyi b/celery-stubs/bin/celery.pyi new file mode 100644 index 0000000..4a40589 --- /dev/null +++ b/celery-stubs/bin/celery.pyi @@ -0,0 +1,15 @@ +from typing import IO, Any + +import click +from celery.bin.base import CeleryCommand + +UNABLE_TO_LOAD_APP_APP_MISSING: str +UNABLE_TO_LOAD_APP_ERROR_OCCURRED: str +UNABLE_TO_LOAD_APP_MODULE_NOT_FOUND: str +WRONG_APP_OPTION_USAGE_MESSAGE: str + +def main() -> int: ... +def previous_show_implementation(self: Any, file: IO[str] | None = None) -> None: ... + +celery: click.Group +report: CeleryCommand diff --git a/celery-stubs/bin/control.pyi b/celery-stubs/bin/control.pyi new file mode 100644 index 0000000..37a0660 --- /dev/null +++ b/celery-stubs/bin/control.pyi @@ -0,0 +1,5 @@ +from celery.bin.base import CeleryCommand + +control: CeleryCommand +inspect: CeleryCommand +status: CeleryCommand diff --git a/celery-stubs/bin/events.pyi b/celery-stubs/bin/events.pyi new file mode 100644 index 0000000..c1491a2 --- /dev/null +++ b/celery-stubs/bin/events.pyi @@ -0,0 +1,3 @@ +from celery.bin.base import CeleryDaemonCommand + +events: CeleryDaemonCommand diff --git a/celery-stubs/bin/graph.pyi b/celery-stubs/bin/graph.pyi new file mode 100644 index 0000000..28eef18 --- /dev/null +++ b/celery-stubs/bin/graph.pyi @@ -0,0 +1,6 @@ +import click +from celery.bin.base import CeleryCommand + +graph: click.Group +bootsteps: CeleryCommand +workers: CeleryCommand diff --git a/celery-stubs/bin/list.pyi b/celery-stubs/bin/list.pyi new file mode 100644 index 0000000..ceb4926 --- /dev/null +++ b/celery-stubs/bin/list.pyi @@ -0,0 +1,5 @@ +import click +from celery.bin.base import CeleryCommand + +list_: click.Group +bindings: CeleryCommand diff --git a/celery-stubs/bin/logtool.pyi b/celery-stubs/bin/logtool.pyi new file mode 100644 index 0000000..27d7eee --- /dev/null +++ b/celery-stubs/bin/logtool.pyi @@ -0,0 +1,5 @@ +import click + +__all__ = ("logtool",) + +logtool: click.Group diff --git a/celery-stubs/bin/migrate.pyi b/celery-stubs/bin/migrate.pyi new file mode 100644 index 0000000..9b23b63 --- /dev/null +++ b/celery-stubs/bin/migrate.pyi @@ -0,0 +1,3 @@ +from celery.bin.base import CeleryCommand + +migrate: CeleryCommand diff --git a/celery-stubs/bin/multi.pyi b/celery-stubs/bin/multi.pyi new file mode 100644 index 0000000..17dad76 --- /dev/null +++ b/celery-stubs/bin/multi.pyi @@ -0,0 +1,114 @@ +from typing import IO, Any + +from celery.apps.multi import ( + Cluster as _Cluster, +) +from celery.apps.multi import ( + MultiParser as _MultiParser, +) +from celery.apps.multi import ( + NamespacedOptionParser as _NamespacedOptionParser, +) +from celery.bin.base import CeleryCommand +from celery.utils.term import colored + +__all__ = ("MultiTool",) + +class TermLogger: + retcode: int + splash_text: str + splash_context: dict[str, Any] + stdout: IO[str] + stderr: IO[str] + nosplash: bool + quiet: bool + verbose: bool + no_color: bool + + @property + def colored(self) -> colored: ... # ty: ignore[invalid-type-form] + def setup_terminal( + self, + stdout: IO[str] | None, + stderr: IO[str] | None, + nosplash: bool = False, + quiet: bool = False, + verbose: bool = False, + no_color: bool = False, + **kwargs: Any, + ) -> None: ... + def ok(self, m: str, newline: bool = True, file: IO[str] | None = None) -> int: ... + def say( + self, m: str, newline: bool = True, file: IO[str] | None = None + ) -> None: ... + def carp( + self, m: str, newline: bool = True, file: IO[str] | None = None + ) -> int: ... + def error(self, msg: str | None = None) -> int: ... + def info(self, msg: str, newline: bool = True) -> None: ... + def note(self, msg: str, newline: bool = True) -> None: ... + def usage(self) -> None: ... + def splash(self) -> None: ... + +class MultiTool(TermLogger): + MultiParser: type[_MultiParser] + OptionParser: type[_NamespacedOptionParser] + reserved_options: list[tuple[str, str]] + env: dict[str, str] | None + cmd: str | None + fh: IO[str] + prog_name: str + commands: dict[str, Any] + + @property + def OK(self) -> int: ... + @property + def DOWN(self) -> int: ... + @property + def FAILED(self) -> int: ... + def __init__( + self, + env: dict[str, str] | None = None, + cmd: str | None = None, + fh: IO[str] | None = None, + stdout: IO[str] | None = None, + stderr: IO[str] | None = None, + **kwargs: Any, + ) -> None: ... + def Cluster(self, nodes: list[Any], cmd: str | None = None) -> _Cluster: ... + def execute_from_commandline( + self, argv: list[str], cmd: str | None = None + ) -> int: ... + def validate_arguments(self, argv: list[str]) -> bool: ... + def call_command(self, command: str, argv: list[str]) -> int: ... + def cluster_from_argv( + self, argv: list[str], cmd: str | None = None + ) -> _Cluster: ... + def start(self, cluster: _Cluster) -> int: ... + def stop(self, cluster: _Cluster, sig: int, **kwargs: Any) -> int: ... + def stopwait(self, cluster: _Cluster, sig: int, **kwargs: Any) -> int: ... + stop_verify: Any # alias for stopwait + def restart(self, cluster: _Cluster, sig: int, **kwargs: Any) -> int: ... + def names(self, cluster: _Cluster) -> None: ... + def get(self, wanted: str, *argv: str) -> int: ... + def show(self, cluster: _Cluster) -> None: ... + def expand(self, template: str, *argv: str) -> None: ... + def help(self, *argv: str) -> None: ... + def kill(self, cluster: _Cluster) -> None: ... + def on_node_start(self, node: Any) -> None: ... + def on_node_restart(self, node: Any) -> None: ... + def on_node_shutdown_ok(self, node: Any) -> None: ... + def on_node_status(self, node: Any, retval: int) -> None: ... + def on_node_signal(self, node: Any, sig: int) -> None: ... + def on_node_signal_dead(self, node: Any) -> None: ... + def on_node_down(self, node: Any) -> None: ... + def on_child_spawn(self, node: Any, argstr: str, env: dict[str, str]) -> None: ... + def on_child_signalled(self, node: Any, signum: int) -> None: ... + def on_child_failure(self, node: Any, retcode: int) -> None: ... + def on_send_signal(self, node: Any, sig: int) -> None: ... + def on_still_waiting_for(self, nodes: list[Any]) -> None: ... + def on_still_waiting_progress(self, nodes: list[Any]) -> None: ... + def on_still_waiting_end(self) -> None: ... + def on_stopping_preamble(self, nodes: list[Any]) -> None: ... + +multi: CeleryCommand diff --git a/celery-stubs/bin/purge.pyi b/celery-stubs/bin/purge.pyi new file mode 100644 index 0000000..59cf7d6 --- /dev/null +++ b/celery-stubs/bin/purge.pyi @@ -0,0 +1,3 @@ +from celery.bin.base import CeleryCommand + +purge: CeleryCommand diff --git a/celery-stubs/bin/result.pyi b/celery-stubs/bin/result.pyi new file mode 100644 index 0000000..3dd6a11 --- /dev/null +++ b/celery-stubs/bin/result.pyi @@ -0,0 +1,3 @@ +from celery.bin.base import CeleryCommand + +result: CeleryCommand diff --git a/celery-stubs/bin/shell.pyi b/celery-stubs/bin/shell.pyi new file mode 100644 index 0000000..75968d6 --- /dev/null +++ b/celery-stubs/bin/shell.pyi @@ -0,0 +1,3 @@ +from celery.bin.base import CeleryCommand + +shell: CeleryCommand diff --git a/celery-stubs/bin/upgrade.pyi b/celery-stubs/bin/upgrade.pyi new file mode 100644 index 0000000..2ec8bba --- /dev/null +++ b/celery-stubs/bin/upgrade.pyi @@ -0,0 +1,5 @@ +import click +from celery.bin.base import CeleryCommand + +upgrade: click.Group +settings: CeleryCommand diff --git a/celery-stubs/bin/worker.pyi b/celery-stubs/bin/worker.pyi new file mode 100644 index 0000000..a5dadaa --- /dev/null +++ b/celery-stubs/bin/worker.pyi @@ -0,0 +1,57 @@ +from logging import Logger + +import click +from celery.app.base import Celery +from celery.bin.base import CeleryDaemonCommand +from typing_extensions import override + +class Autoscale(click.ParamType): + name: str + @override + def convert( + self, + value: str | None, + param: click.Parameter | None, + ctx: click.Context | None, + ) -> tuple[int, int] | None: ... + +class CeleryBeat(click.ParamType): + name: str + @override + def convert( + self, + value: str | None, + param: click.Parameter | None, + ctx: click.Context | None, + ) -> bool: ... + +class Hostname(click.types.StringParamType): + name: str + +class WorkersPool(click.Choice): + name: str + def __init__(self) -> None: ... + +AUTOSCALE: Autoscale +CELERY_BEAT: CeleryBeat +C_FAKEFORK: str | None +HOSTNAME: Hostname +WORKERS_POOL: WorkersPool +logger: Logger + +def detach( + path: str, + argv: list[str], + logfile: str | None = None, + pidfile: str | None = None, + uid: int | None = None, + gid: int | None = None, + umask: int | None = None, + workdir: str | None = None, + fake: bool = False, + app: Celery | None = None, + executable: str | None = None, + hostname: str | None = None, +) -> int: ... + +worker: CeleryDaemonCommand diff --git a/celery-stubs/bootsteps.pyi b/celery-stubs/bootsteps.pyi index 563f442..49f8030 100644 --- a/celery-stubs/bootsteps.pyi +++ b/celery-stubs/bootsteps.pyi @@ -1,5 +1,7 @@ from typing import Any, ClassVar +__all__ = ("Blueprint", "ConsumerStep", "StartStopStep", "Step") + from celery.utils.graph import GraphFormatter from kombu import Consumer from typing_extensions import override @@ -8,8 +10,11 @@ class StepFormatter(GraphFormatter): blueprint_prefix: str conditional_prefix: str blueprint_scheme: dict[str, str] - def label(self, step: Any) -> Any: ... + @override + def label(self, step: Any) -> Any: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + @override def node(self, obj: Any, **attrs: Any) -> Any: ... + @override def edge(self, a: Any, b: Any, **attrs: Any) -> Any: ... class Blueprint: @@ -17,7 +22,7 @@ class Blueprint: name: ClassVar[str | None] state: Any started: int - default_steps: list[str] + default_steps: set[Any] state_to_name: Any types: Any on_start: Any @@ -65,7 +70,7 @@ class Blueprint: class StepType(type): name: ClassVar[str | None] - requires: tuple[type[Step] | str, ...] + requires: tuple[type[Step] | str, ...] | None def __new__(cls, name: Any, bases: Any, attrs: Any) -> Any: ... class Step(metaclass=StepType): @@ -97,11 +102,11 @@ class ConsumerStep(StartStopStep): consumers: list[Consumer] | None def get_consumers(self, channel: Any) -> list[Consumer]: ... @override - def start( # pyright: ignore[reportIncompatibleMethodOverride] + def start( # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] self, c: Any ) -> None: ... @override - def stop( # pyright: ignore[reportIncompatibleMethodOverride] + def stop( # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] self, c: Any ) -> None: ... def shutdown(self, c: Any) -> None: ... diff --git a/celery-stubs/canvas.pyi b/celery-stubs/canvas.pyi index 0d71895..2e21131 100644 --- a/celery-stubs/canvas.pyi +++ b/celery-stubs/canvas.pyi @@ -3,7 +3,18 @@ from datetime import datetime from typing import ( Any, Generic, - overload, +) + +__all__ = ( + "Signature", + "chain", + "chord", + "chunks", + "group", + "maybe_signature", + "signature", + "xmap", + "xstarmap", ) import celery.result @@ -18,6 +29,12 @@ _F = TypeVar("_F", bound=Callable[..., Any]) _R_co = TypeVar("_R_co", covariant=True, default=Any) class Signature(dict[str, Any], Generic[_R_co]): + TYPES: dict[str, type[Signature[Any]]] # ty: ignore[invalid-type-form] + + @classmethod + def register_type( + cls, name: str | None = None + ) -> Callable[[type[Signature[Any]]], type[Signature[Any]]]: ... # ty: ignore[invalid-type-form] @classmethod def from_dict( cls, d: dict[str, Any], app: Celery | None = ... @@ -63,6 +80,17 @@ class Signature(dict[str, Any], Generic[_R_co]): self, args: tuple[Any, ...] | None = ..., kwargs: dict[str, Any] | None = ..., + *, + # options (passed through to Task.apply) + link: Signature[Any] | list[Signature[Any]] | None = ..., + link_error: Signature[Any] | list[Signature[Any]] | None = ..., + task_id: str | None = ..., + retries: int | None = ..., + throw: bool | None = ..., + logfile: str | None = ..., + loglevel: str | None = ..., + headers: Mapping[str, str] | None = ..., + ignore_result: bool = ..., **options: Any, ) -> EagerResult[_R_co]: ... def apply_async( @@ -71,7 +99,7 @@ class Signature(dict[str, Any], Generic[_R_co]): kwargs: dict[str, Any] | None = ..., route_name: str | None = ..., *, - # options + # options (captured by **options at runtime) task_id: str | None = ..., producer: kombu.Producer | None = ..., link: Signature[Any] | list[Signature[Any]] | None = ..., @@ -92,6 +120,7 @@ class Signature(dict[str, Any], Generic[_R_co]): add_to_parent: bool = ..., publisher: kombu.Producer = ..., headers: dict[str, str] = ..., + **options: Any, ) -> celery.result.AsyncResult[_R_co]: ... def clone( self, @@ -128,6 +157,7 @@ class Signature(dict[str, Any], Generic[_R_co]): chord: chord | None = ..., root_id: str | None = ..., parent_id: str | None = ..., + group_index: int | None = ..., ) -> celery.result.AsyncResult[_R_co]: ... def replace( self, @@ -168,6 +198,22 @@ class Signature(dict[str, Any], Generic[_R_co]): def link_error(self, errback: Callable[..., Any]) -> Signature[_R_co]: ... def on_error(self, errback: _F) -> _F: ... def flatten_links(self) -> list[Signature[Any]]: ... + def stamp( + self, + visitor: Any = ..., + append_stamps: bool = ..., + **headers: Any, + ) -> Any: ... + def stamp_links( + self, + visitor: Any, + append_stamps: bool = ..., + **headers: Any, + ) -> Any: ... + def __deepcopy__(self, memo: dict[int, Any]) -> Signature[_R_co]: ... + def __invert__(self) -> Any: ... + def __json__(self) -> dict[str, Any]: ... + def reprcall(self, *args: Any, **kwargs: Any) -> str: ... # TODO(sbdchd): use overloads to properly type this @override def __or__( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] @@ -180,19 +226,30 @@ class Signature(dict[str, Any], Generic[_R_co]): def type(self) -> Any: ... @property def app(self) -> Celery: ... + @property def AsyncResult(self) -> celery.result.AsyncResult[_R_co]: ... - id: str | None - parent_id: str | None - root_id: str | None - task: str | None - args: tuple[Any, ...] - kwargs: dict[str, Any] - options: dict[str, Any] - subtask_type: Any - chord_size: int | None - immutable: bool + @property + def id(self) -> str | None: ... + @property + def parent_id(self) -> str | None: ... + @property + def root_id(self) -> str | None: ... + @property + def task(self) -> str | None: ... + @property + def args(self) -> tuple[Any, ...]: ... + @property + def kwargs(self) -> dict[str, Any]: ... + @property + def options(self) -> dict[str, Any]: ... + @property + def subtask_type(self) -> Any: ... + @property + def immutable(self) -> bool: ... class _chain(Signature[Any]): + @property + def tasks(self) -> tuple[Signature[Any], ...]: ... def __init__( self, *tasks: Signature[Any], @@ -222,6 +279,86 @@ class _chain(Signature[Any]): publisher: kombu.Producer = ..., headers: dict[str, str] = ..., ) -> None: ... + @override + def apply_async( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + self, + args: tuple[Any, ...] | None = ..., + kwargs: dict[str, Any] | None = ..., + *, + # options (passed through to Signature.apply_async) + task_id: str | None = ..., + producer: kombu.Producer | None = ..., + link: Signature[Any] | list[Signature[Any]] | None = ..., + link_error: Signature[Any] | list[Signature[Any]] | None = ..., + shadow: str | None = ..., + countdown: float = ..., + eta: datetime | None = ..., + expires: float | datetime = ..., + retry: bool = ..., + retry_policy: Mapping[str, Any] = ..., + queue: str | kombu.Queue = ..., + exchange: str | kombu.Exchange = ..., + routing_key: str = ..., + priority: int = ..., + serializer: str = ..., + compression: str = ..., + add_to_parent: bool = ..., + publisher: kombu.Producer = ..., + headers: dict[str, str] = ..., + ignore_result: bool = ..., + **options: Any, + ) -> celery.result.AsyncResult[Any]: ... + def prepare_steps( + self, + args: tuple[Any, ...], + kwargs: dict[str, Any], + tasks: list[Signature[Any]], + root_id: str | None = None, + parent_id: str | None = None, + link_error: Signature[Any] | None = None, + app: Celery | None = None, + last_task_id: str | None = None, + group_id: str | None = None, + chord_body: Signature[Any] | None = None, + clone: bool = True, + from_dict: Callable[[dict[str, Any], Celery | None], Signature[Any]] = ..., + group_index: int | None = None, + ) -> tuple[Any, ...]: ... + def run( + self, + args: tuple[Any, ...] | None = None, + kwargs: dict[str, Any] | None = None, + group_id: str | None = None, + chord: chord | None = None, + task_id: str | None = None, + link: Signature[Any] | None = None, + link_error: Signature[Any] | None = None, + publisher: kombu.Producer | None = None, + producer: kombu.Producer | None = None, + root_id: str | None = None, + parent_id: str | None = None, + app: Celery | None = None, + group_index: int | None = None, + *, + # options (passed through to apply_async) + shadow: str | None = ..., + countdown: float = ..., + eta: datetime | None = ..., + expires: float | datetime = ..., + retry: bool = ..., + retry_policy: Mapping[str, Any] = ..., + queue: str | kombu.Queue = ..., + exchange: str | kombu.Exchange = ..., + routing_key: str = ..., + priority: int = ..., + serializer: str = ..., + compression: str = ..., + add_to_parent: bool = ..., + headers: dict[str, str] = ..., + ignore_result: bool = ..., + **options: Any, + ) -> celery.result.AsyncResult[Any]: ... + def unchain_tasks(self) -> list[Signature[Any]]: ... class chain(_chain): ... @@ -259,6 +396,35 @@ class _basemap(Signature[Any]): publisher: kombu.Producer = ..., headers: dict[str, str] = ..., ) -> None: ... + @override + def apply_async( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + self, + args: tuple[Any, ...] | None = ..., + kwargs: dict[str, Any] | None = ..., + *, + # options (passed through to Signature.apply_async) + task_id: str | None = ..., + producer: kombu.Producer | None = ..., + link: Signature[Any] | list[Signature[Any]] | None = ..., + link_error: Signature[Any] | list[Signature[Any]] | None = ..., + shadow: str | None = ..., + countdown: float = ..., + eta: datetime | None = ..., + expires: float | datetime = ..., + retry: bool = ..., + retry_policy: Mapping[str, Any] = ..., + queue: str | kombu.Queue = ..., + exchange: str | kombu.Exchange = ..., + routing_key: str = ..., + priority: int = ..., + serializer: str = ..., + compression: str = ..., + add_to_parent: bool = ..., + publisher: kombu.Producer = ..., + headers: dict[str, str] = ..., + ignore_result: bool = ..., + **opts: Any, + ) -> celery.result.AsyncResult[Any]: ... class xmap(_basemap): ... class xstarmap(_basemap): ... @@ -298,21 +464,81 @@ class chunks(Signature[Any]): publisher: kombu.Producer = ..., headers: dict[str, str] = ..., ) -> None: ... + @classmethod + def apply_chunks( + cls, + task: Task[Any, Any], + it: Iterable[Any], + n: int, + app: Celery | None = ..., + ) -> list[Any]: ... + @override + def __call__( + self, + *, + # options (passed through to apply_async) + task_id: str | None = ..., + producer: kombu.Producer | None = ..., + link: Signature[Any] | list[Signature[Any]] | None = ..., + link_error: Signature[Any] | list[Signature[Any]] | None = ..., + shadow: str | None = ..., + countdown: float = ..., + eta: datetime | None = ..., + expires: float | datetime = ..., + retry: bool = ..., + retry_policy: Mapping[str, Any] = ..., + queue: str | kombu.Queue = ..., + exchange: str | kombu.Exchange = ..., + routing_key: str = ..., + priority: int = ..., + serializer: str = ..., + compression: str = ..., + add_to_parent: bool = ..., + publisher: kombu.Producer = ..., + headers: dict[str, str] = ..., + ignore_result: bool = ..., + **options: Any, + ) -> Any: ... + @override + def apply_async( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + self, + args: tuple[Any, ...] | None = ..., + kwargs: dict[str, Any] | None = ..., + *, + # options (passed through to Signature.apply_async) + task_id: str | None = ..., + producer: kombu.Producer | None = ..., + link: Signature[Any] | list[Signature[Any]] | None = ..., + link_error: Signature[Any] | list[Signature[Any]] | None = ..., + shadow: str | None = ..., + countdown: float = ..., + eta: datetime | None = ..., + expires: float | datetime = ..., + retry: bool = ..., + retry_policy: Mapping[str, Any] = ..., + queue: str | kombu.Queue = ..., + exchange: str | kombu.Exchange = ..., + routing_key: str = ..., + priority: int = ..., + serializer: str = ..., + compression: str = ..., + add_to_parent: bool = ..., + publisher: kombu.Producer = ..., + headers: dict[str, str] = ..., + ignore_result: bool = ..., + **opts: Any, + ) -> celery.result.AsyncResult[Any]: ... def group(self) -> _group: ... class group(Signature[Any]): - tasks: list[Signature[Any]] - - @overload - def __init__( - self, - *tasks: group | abstract.CallableSignature | Iterable[Signature[Any]], - **options: Any, - ) -> None: ... - @overload + @property + def tasks(self) -> list[Signature[Any]]: ... def __init__( self, - *tasks: Signature[Any], + *tasks: group + | abstract.CallableSignature + | Iterable[Signature[Any]] + | Signature[Any], # Signature extras args: tuple[Any, ...] | None = ..., kwargs: dict[str, Any] | None = ..., @@ -340,16 +566,61 @@ class group(Signature[Any]): add_to_parent: bool = ..., publisher: kombu.Producer = ..., headers: dict[str, str] = ..., + **options_: Any, ) -> None: ... def skew( self, start: float = ..., stop: float | None = ..., step: float = ... ) -> group: ... @override + def apply_async( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + self, + args: tuple[Any, ...] | None = ..., + kwargs: dict[str, Any] | None = ..., + add_to_parent: bool = ..., + producer: kombu.Producer | None = ..., + link: Signature[Any] | list[Signature[Any]] | None = ..., + link_error: Signature[Any] | list[Signature[Any]] | None = ..., + *, + # options (passed through to Signature.apply_async) + task_id: str | None = ..., + shadow: str | None = ..., + countdown: float = ..., + eta: datetime | None = ..., + expires: float | datetime = ..., + retry: bool = ..., + retry_policy: Mapping[str, Any] = ..., + queue: str | kombu.Queue = ..., + exchange: str | kombu.Exchange = ..., + routing_key: str = ..., + priority: int = ..., + serializer: str = ..., + compression: str = ..., + publisher: kombu.Producer = ..., + headers: dict[str, str] = ..., + ignore_result: bool = ..., + **options: Any, + ) -> celery.result.AsyncResult[Any]: ... + @override + def link(self, sig: Signature[Any]) -> Signature[Any]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + @override + def link_error(self, sig: Signature[Any]) -> Signature[Any]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + @override + def stamp( + self, + visitor: Any = ..., + append_stamps: bool = ..., + **headers: Any, + ) -> Any: ... + @override def __or__(self, other: Signature[Any]) -> chord: ... # type: ignore[override] _group = group class chord(Signature[Any]): + @property + def tasks(self) -> Any: ... + @property + def body(self) -> Any: ... def __init__( self, header: Any, @@ -384,12 +655,128 @@ class chord(Signature[Any]): publisher: kombu.Producer = ..., headers: dict[str, str] = ..., ) -> None: ... + def run( + self, + header: Any, + body: Any, + partial_args: tuple[Any, ...], + app: Celery | None = ..., + interval: float | None = ..., + countdown: int = ..., + max_retries: int | None = ..., + eager: bool = ..., + task_id: str | None = ..., + kwargs: dict[str, Any] | None = ..., + *, + # options (passed through to apply_async) + producer: kombu.Producer | None = ..., + link: Signature[Any] | list[Signature[Any]] | None = ..., + link_error: Signature[Any] | list[Signature[Any]] | None = ..., + shadow: str | None = ..., + eta: datetime | None = ..., + expires: float | datetime = ..., + retry: bool = ..., + retry_policy: Mapping[str, Any] = ..., + queue: str | kombu.Queue = ..., + exchange: str | kombu.Exchange = ..., + routing_key: str = ..., + priority: int = ..., + serializer: str = ..., + compression: str = ..., + add_to_parent: bool = ..., + publisher: kombu.Producer = ..., + headers: dict[str, str] = ..., + ignore_result: bool = ..., + **options: Any, + ) -> Any: ... + def __length_hint__(self) -> int: ... + @override + def apply( + self, + args: tuple[Any, ...] | None = ..., + kwargs: dict[str, Any] | None = ..., + propagate: bool = ..., + body: Signature[Any] | None = ..., + *, + # options (passed through to Task.apply) + link: Signature[Any] | list[Signature[Any]] | None = ..., + link_error: Signature[Any] | list[Signature[Any]] | None = ..., + task_id: str | None = ..., + retries: int | None = ..., + throw: bool | None = ..., + logfile: str | None = ..., + loglevel: str | None = ..., + headers: Mapping[str, str] | None = ..., + ignore_result: bool = ..., + **options: Any, + ) -> EagerResult[Any]: ... + @override + def apply_async( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + self, + args: tuple[Any, ...] | None = ..., + kwargs: dict[str, Any] | None = ..., + task_id: str | None = ..., + producer: kombu.Producer | None = ..., + publisher: kombu.Producer | None = ..., + connection: kombu.Connection | None = ..., + router: Any | None = ..., + result_cls: type[celery.result.AsyncResult[Any]] | None = ..., + *, + # options (passed through to Signature.apply_async) + link: Signature[Any] | list[Signature[Any]] | None = ..., + link_error: Signature[Any] | list[Signature[Any]] | None = ..., + shadow: str | None = ..., + countdown: float = ..., + eta: datetime | None = ..., + expires: float | datetime = ..., + retry: bool = ..., + retry_policy: Mapping[str, Any] = ..., + queue: str | kombu.Queue = ..., + exchange: str | kombu.Exchange = ..., + routing_key: str = ..., + priority: int = ..., + serializer: str = ..., + compression: str = ..., + add_to_parent: bool = ..., + headers: dict[str, str] = ..., + ignore_result: bool = ..., + **options: Any, + ) -> celery.result.AsyncResult[Any]: ... + @override + def stamp( + self, + visitor: Any = ..., + append_stamps: bool = ..., + **headers: Any, + ) -> Any: ... @override def __or__(self, other: Signature[Any]) -> chord: ... # type: ignore[override] @override def __call__( self, body: Signature[Any] | None = ..., + *, + # options (passed through to apply_async) + task_id: str | None = ..., + producer: kombu.Producer | None = ..., + link: Signature[Any] | list[Signature[Any]] | None = ..., + link_error: Signature[Any] | list[Signature[Any]] | None = ..., + shadow: str | None = ..., + countdown: float = ..., + eta: datetime | None = ..., + expires: float | datetime = ..., + retry: bool = ..., + retry_policy: Mapping[str, Any] = ..., + queue: str | kombu.Queue = ..., + exchange: str | kombu.Exchange = ..., + routing_key: str = ..., + priority: int = ..., + serializer: str = ..., + compression: str = ..., + add_to_parent: bool = ..., + publisher: kombu.Producer = ..., + headers: dict[str, str] = ..., + ignore_result: bool = ..., **options: Any, ) -> celery.result.AsyncResult[Any]: ... diff --git a/celery-stubs/concurrency/__init__.pyi b/celery-stubs/concurrency/__init__.pyi index e69de29..93de499 100644 --- a/celery-stubs/concurrency/__init__.pyi +++ b/celery-stubs/concurrency/__init__.pyi @@ -0,0 +1,6 @@ +from typing import Any + +__all__ = ("get_available_pool_names", "get_implementation") + +def get_implementation(cls: str | type[Any]) -> type[Any]: ... +def get_available_pool_names() -> set[str]: ... diff --git a/celery-stubs/concurrency/asynpool.pyi b/celery-stubs/concurrency/asynpool.pyi index af7df11..e6ef1a4 100644 --- a/celery-stubs/concurrency/asynpool.pyi +++ b/celery-stubs/concurrency/asynpool.pyi @@ -1,16 +1,43 @@ -from typing import NamedTuple +from typing import Any, NamedTuple from billiard import pool as _pool from typing_extensions import override -__all__ = ["AsynPool"] +__all__ = ("AsynPool",) + +class Ack(NamedTuple): + id: int + fd: int + payload: Any -class Ack(NamedTuple): ... class Worker(_pool.Worker): ... class ResultHandler(_pool.ResultHandler): @override def on_stop_not_started(self) -> None: ... + def register_with_event_loop(self, hub: Any) -> None: ... class AsynPool(_pool.Pool): + @property + def timers(self) -> dict[Any, Any]: ... + def __init__( + self, + processes: int | None = None, + synack: bool = False, + sched_strategy: int | None = None, + proc_alive_timeout: float | None = None, + *args: Any, + **kwargs: Any, + ) -> None: ... def flush(self) -> None: ... + def create_process_queues(self) -> tuple[Any, Any, Any]: ... + @override + def create_result_handler(self) -> ResultHandler: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def destroy_queues(self, queues: tuple[Any, Any, Any], proc: Any) -> None: ... + def human_write_stats(self) -> str: ... + @override + def on_partial_read(self, job: Any, proc: Any) -> None: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + def on_process_alive(self, pid: int) -> None: ... + @override + def process_flush_queues(self, proc: Any) -> None: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + def register_with_event_loop(self, hub: Any) -> None: ... diff --git a/celery-stubs/concurrency/base.pyi b/celery-stubs/concurrency/base.pyi index 90c9bd7..2f84573 100644 --- a/celery-stubs/concurrency/base.pyi +++ b/celery-stubs/concurrency/base.pyi @@ -1,5 +1,7 @@ from typing import Any +__all__ = ("BasePool", "apply_target") + def apply_target( target: Any, args: Any = ..., diff --git a/celery-stubs/concurrency/eventlet.pyi b/celery-stubs/concurrency/eventlet.pyi new file mode 100644 index 0000000..9952741 --- /dev/null +++ b/celery-stubs/concurrency/eventlet.pyi @@ -0,0 +1,25 @@ +from typing import Any + +from celery.concurrency.base import BasePool +from typing_extensions import override + +__all__ = ("TaskPool",) + +class TaskPool(BasePool): + def __init__(self, *args: Any, **kwargs: Any) -> None: ... + @override + def on_start(self) -> None: ... + @override + def on_stop(self) -> None: ... + @override + def on_apply( + self, + target: Any, + args: tuple[Any, ...] | None = None, + kwargs: dict[str, Any] | None = None, + callback: Any = None, + accept_callback: Any = None, + **opts: Any, + ) -> Any: ... + def grow(self, n: int = 1) -> None: ... + def shrink(self, n: int = 1) -> None: ... diff --git a/celery-stubs/concurrency/gevent.pyi b/celery-stubs/concurrency/gevent.pyi new file mode 100644 index 0000000..dc70b1c --- /dev/null +++ b/celery-stubs/concurrency/gevent.pyi @@ -0,0 +1,29 @@ +from collections.abc import Callable +from typing import Any + +from celery.concurrency.base import BasePool +from typing_extensions import override + +__all__ = ("TaskPool",) + +class TaskPool(BasePool): + def __init__(self, *args: Any, **kwargs: Any) -> None: ... + @override + def on_start(self) -> None: ... + @override + def on_stop(self) -> None: ... + @override + def on_apply( + self, + target: Any, + args: tuple[Any, ...] | None = None, + kwargs: dict[str, Any] | None = None, + callback: Any = None, + accept_callback: Any = None, + timeout: float | None = None, + timeout_callback: Callable[..., Any] | None = None, + apply_target: Callable[..., Any] = ..., + **_: Any, + ) -> Any: ... + def grow(self, n: int = 1) -> None: ... + def shrink(self, n: int = 1) -> None: ... diff --git a/celery-stubs/concurrency/prefork.pyi b/celery-stubs/concurrency/prefork.pyi index 7bd5c9f..61dc02c 100644 --- a/celery-stubs/concurrency/prefork.pyi +++ b/celery-stubs/concurrency/prefork.pyi @@ -1,12 +1,22 @@ +from collections.abc import Callable +from typing import Any + +from billiard.pool import Pool as BilliardPool from celery.concurrency.asynpool import AsynPool from celery.concurrency.base import BasePool from typing_extensions import override -__all__ = ["TaskPool"] +__all__ = ("TaskPool", "process_destructor", "process_initializer") + +def process_initializer(app: Any, hostname: str) -> None: ... +def process_destructor(pid: int, exitcode: int) -> None: ... class TaskPool(BasePool): - Pool = AsynPool + Pool: type[AsynPool] + BlockingPool: Callable[..., BilliardPool] uses_semaphore: bool + write_stats: Callable[[], str | None] | None + @override def on_start(self) -> None: ... @override diff --git a/celery-stubs/concurrency/solo.pyi b/celery-stubs/concurrency/solo.pyi new file mode 100644 index 0000000..09063ed --- /dev/null +++ b/celery-stubs/concurrency/solo.pyi @@ -0,0 +1,23 @@ +from typing import Any + +from celery.concurrency.base import BasePool +from typing_extensions import override + +__all__ = ("TaskPool",) + +class TaskPool(BasePool): + def __init__(self, *args: Any, **kwargs: Any) -> None: ... + @override + def on_start(self) -> None: ... + @override + def on_stop(self) -> None: ... + @override + def on_apply( + self, + target: Any, + args: tuple[Any, ...] | None = None, + kwargs: dict[str, Any] | None = None, + callback: Any = None, + accept_callback: Any = None, + **opts: Any, + ) -> Any: ... diff --git a/celery-stubs/concurrency/thread.pyi b/celery-stubs/concurrency/thread.pyi new file mode 100644 index 0000000..09063ed --- /dev/null +++ b/celery-stubs/concurrency/thread.pyi @@ -0,0 +1,23 @@ +from typing import Any + +from celery.concurrency.base import BasePool +from typing_extensions import override + +__all__ = ("TaskPool",) + +class TaskPool(BasePool): + def __init__(self, *args: Any, **kwargs: Any) -> None: ... + @override + def on_start(self) -> None: ... + @override + def on_stop(self) -> None: ... + @override + def on_apply( + self, + target: Any, + args: tuple[Any, ...] | None = None, + kwargs: dict[str, Any] | None = None, + callback: Any = None, + accept_callback: Any = None, + **opts: Any, + ) -> Any: ... diff --git a/celery-stubs/contrib/migrate.pyi b/celery-stubs/contrib/migrate.pyi index 9965e04..8592035 100644 --- a/celery-stubs/contrib/migrate.pyi +++ b/celery-stubs/contrib/migrate.pyi @@ -52,7 +52,7 @@ _T = TypeVar("_T") def filter_callback( callback: Callable[[Mapping[str, Any], Message], _T], - tasks: Container[str] | None = None, + tasks: Container[str], ) -> Callable[[Mapping[str, Any], Message], _T | None]: ... def migrate_tasks( source: Sequence[str], diff --git a/celery-stubs/contrib/sphinx.pyi b/celery-stubs/contrib/sphinx.pyi index b3a5e67..1ecbf33 100644 --- a/celery-stubs/contrib/sphinx.pyi +++ b/celery-stubs/contrib/sphinx.pyi @@ -1,4 +1,4 @@ -from typing import Any, Literal +from typing import Any, ClassVar, Literal from celery.app.task import Task as BaseTask from docutils import nodes @@ -7,8 +7,8 @@ from sphinx.ext.autodoc import Documenter, FunctionDocumenter from typing_extensions import override class TaskDocumenter(FunctionDocumenter): - objtype: str = "task" - member_order: int = 11 + objtype: ClassVar[str] + member_order: ClassVar[int] @override @classmethod diff --git a/celery-stubs/contrib/testing/manager.pyi b/celery-stubs/contrib/testing/manager.pyi index b4c11fd..d2f611e 100644 --- a/celery-stubs/contrib/testing/manager.pyi +++ b/celery-stubs/contrib/testing/manager.pyi @@ -16,7 +16,7 @@ class Sentinel(Exception): ... class ManagerMixin: def _init_manager( self, - block_timeout: float = 180, + block_timeout: float = 1800.0, no_join: bool = False, stdout: TextIO | None = None, stderr: TextIO | None = None, diff --git a/celery-stubs/contrib/testing/worker.pyi b/celery-stubs/contrib/testing/worker.pyi index 1f336b7..1457fc6 100644 --- a/celery-stubs/contrib/testing/worker.pyi +++ b/celery-stubs/contrib/testing/worker.pyi @@ -16,6 +16,7 @@ test_worker_stopped: Signal class TestWorkController(WorkController): __test__: bool + logger_queue: Any def __init__(self, *args: Any, **kwargs: Any) -> None: ... class QueueHandler(handlers.QueueHandler): @@ -24,7 +25,9 @@ class TestWorkController(WorkController): @override def handleError(self, record: LogRecord) -> None: ... + @override def start(self) -> Any: ... + @override def on_consumer_ready(self, consumer: Any) -> None: ... def ensure_started(self) -> None: ... diff --git a/celery-stubs/events/__init__.pyi b/celery-stubs/events/__init__.pyi new file mode 100644 index 0000000..16cd5f2 --- /dev/null +++ b/celery-stubs/events/__init__.pyi @@ -0,0 +1,18 @@ +from typing import Any + +from celery.events.dispatcher import EventDispatcher as EventDispatcher +from celery.events.event import Event as Event +from celery.events.event import get_exchange as get_exchange +from celery.events.event import group_from as group_from +from celery.events.receiver import EventReceiver as EventReceiver + +__all__ = ( + "Event", + "EventDispatcher", + "EventReceiver", + "event_exchange", + "get_exchange", + "group_from", +) + +event_exchange: Any diff --git a/celery-stubs/events/cursesmon.pyi b/celery-stubs/events/cursesmon.pyi new file mode 100644 index 0000000..02bfe62 --- /dev/null +++ b/celery-stubs/events/cursesmon.pyi @@ -0,0 +1,64 @@ +from typing import Any + +__all__ = ("CursesMonitor", "evtop") + +class CursesMonitor: + keymap: dict[Any, Any] + keyalias: dict[Any, Any] + win: Any + selected_position: int + screen_delay: float + background: int + foreground: int + greet: str + help: str + + def __init__(self, state: Any, app: Any, keymap: Any = None) -> None: ... + def alert(self, callback: Any, title: str | None = None) -> None: ... + def alert_remote_control_reply(self, reply: Any) -> None: ... + @property + def display_height(self) -> int: ... + def display_task_row(self, lineno: int, task: Any) -> None: ... + @property + def display_width(self) -> int: ... + def draw(self) -> None: ... + def find_position(self) -> int: ... + def format_row( + self, uuid: str, task: Any, worker: Any, timestamp: Any, state: Any + ) -> str: ... + def handle_keypress(self) -> bool | None: ... + @property + def help_title(self) -> str: ... + @property + def info_str(self) -> str: ... + def init_screen(self) -> None: ... + @property + def limit(self) -> int: ... + def move_selection(self, direction: int = 1) -> None: ... + def move_selection_down(self) -> None: ... + def move_selection_up(self) -> None: ... + def nap(self) -> None: ... + @property + def online_str(self) -> str: ... + def readline(self, x: int, y: int) -> str: ... + def resetscreen(self) -> None: ... + def revoke_selection(self) -> None: ... + def safe_add_str(self, y: int, x: int, string: str, *args: Any) -> None: ... + @property + def screen_height(self) -> int: ... + @property + def screen_width(self) -> int: ... + @property + def selected_str(self) -> str: ... + @property + def selected_task(self) -> Any: ... + def selection_info(self) -> None: ... + def selection_rate_limit(self) -> None: ... + def selection_result(self) -> None: ... + def selection_traceback(self) -> None: ... + @property + def tasks(self) -> list[Any]: ... + @property + def workers(self) -> list[Any]: ... + +def evtop(app: Any | None = None) -> None: ... diff --git a/celery-stubs/events/dispatcher.pyi b/celery-stubs/events/dispatcher.pyi new file mode 100644 index 0000000..78fc28a --- /dev/null +++ b/celery-stubs/events/dispatcher.pyi @@ -0,0 +1,70 @@ +from collections.abc import Callable +from typing import Any + +import kombu +from celery.app.base import Celery +from kombu.transport.virtual import Channel +from typing_extensions import Self + +__all__ = ("EventDispatcher",) + +class EventDispatcher: + DISABLED_TRANSPORTS: set[str] + app: Celery | None + connection: kombu.Connection | None + hostname: str + groups: set[str] | None + enabled: bool + on_enabled: Callable[[], None] | None + on_disabled: Callable[[], None] | None + + def __init__( + self, + connection: kombu.Connection | None = None, + hostname: str | None = None, + enabled: bool = True, + channel: Channel | None = None, + buffer_while_offline: bool = True, + app: Celery | None = None, + serializer: str | None = None, + groups: list[str] | None = None, + delivery_mode: int | str = ..., + buffer_group: list[str] | None = None, + buffer_limit: int = 24, + on_send_buffered: Callable[..., Any] | None = None, + ) -> None: ... + def enable(self) -> None: ... + def disable(self) -> None: ... + def publish( + self, + type: str, + fields: dict[str, Any], + producer: kombu.Producer, + blind: bool = False, + Event: Callable[..., dict[str, Any]] = ..., + **kwargs: Any, + ) -> None: ... + def send( + self, + type: str, + blind: bool = False, + utcoffset: Callable[[], int] = ..., + retry: bool = False, + retry_policy: dict[str, Any] | None = None, + Event: Callable[..., dict[str, Any]] = ..., + **fields: Any, + ) -> None: ... + def extend_buffer( + self, + other: EventDispatcher, + ) -> None: ... + def flush( + self, + errors: bool = True, + groups: bool = True, + ) -> None: ... + def close(self) -> None: ... + @property + def publisher(self) -> kombu.Producer | None: ... + def __enter__(self) -> Self: ... + def __exit__(self, *args: object) -> None: ... diff --git a/celery-stubs/events/dumper.pyi b/celery-stubs/events/dumper.pyi new file mode 100644 index 0000000..794ba96 --- /dev/null +++ b/celery-stubs/events/dumper.pyi @@ -0,0 +1,20 @@ +from typing import Any, TextIO + +__all__ = ("Dumper", "evdump") + +class Dumper: + out: TextIO + + def __init__(self, out: TextIO = ...) -> None: ... + def say(self, msg: str) -> None: ... + def format_task_event( + self, + hostname: str, + timestamp: float, + type: str, + task: str, + event: dict[str, Any], + ) -> str: ... + def on_event(self, ev: dict[str, Any]) -> None: ... + +def evdump(app: Any | None = None, out: TextIO = ...) -> None: ... diff --git a/celery-stubs/events/event.pyi b/celery-stubs/events/event.pyi new file mode 100644 index 0000000..b173951 --- /dev/null +++ b/celery-stubs/events/event.pyi @@ -0,0 +1,16 @@ +from collections.abc import Callable +from typing import Any + +__all__ = ("Event", "event_exchange", "get_exchange", "group_from") + +event_exchange: Any + +def Event( + type: str, + _fields: dict[str, Any] | None = None, + __dict__: type[dict[str, Any]] = ..., + __now__: Callable[[], float] = ..., + **fields: Any, +) -> dict[str, Any]: ... +def group_from(type: str) -> str: ... +def get_exchange(conn: Any, name: str = ...) -> Any: ... diff --git a/celery-stubs/events/receiver.pyi b/celery-stubs/events/receiver.pyi new file mode 100644 index 0000000..1d54a0a --- /dev/null +++ b/celery-stubs/events/receiver.pyi @@ -0,0 +1,99 @@ +from collections.abc import Callable, Iterable, Iterator +from contextlib import contextmanager +from operator import itemgetter +from typing import Any + +import kombu +from celery.app.base import Celery +from kombu.utils.objects import cached_property + +__all__ = ("EventReceiver",) + +class EventReceiver: + Consumer: Callable[..., Any] + app: Celery | None + handlers: dict[str, Callable[..., Any]] + channel_errors: cached_property[tuple[type[Exception], ...]] + connection_errors: cached_property[tuple[type[Exception], ...]] + connect_max_retries: int | None + restart_limit: Any + should_stop: bool + + def __init__( + self, + channel: Any, + handlers: dict[str, Callable[..., Any]] | None = None, + routing_key: str = "#", + node_id: str | None = None, + app: Celery | None = None, + queue_prefix: str | None = None, + accept: Iterable[str] | None = None, + queue_ttl: float | None = None, + queue_expires: float | None = None, + queue_exclusive: bool | None = None, + queue_durable: bool | None = None, + ) -> None: ... + @property + def connection(self) -> kombu.Connection: ... + def process( + self, + type: str, + event: dict[str, Any], + ) -> None: ... + def capture( + self, + limit: int | None = None, + timeout: float | None = None, + wakeup: bool = True, + ) -> None: ... + def itercapture( + self, + limit: int | None = None, + timeout: float | None = None, + wakeup: bool = True, + ) -> Iterator[tuple[str, dict[str, Any]]]: ... + def consume( + self, + limit: int | None = None, + timeout: float | None = None, + safety_interval: float = 1, + **kwargs: Any, + ) -> None: ... + def run( + self, + _tokens: int = 1, + **kwargs: Any, + ) -> None: ... + @contextmanager + def consumer_context(self, wakeup: bool = True) -> Iterator[kombu.Consumer]: ... + def on_consume_ready( + self, + connection: Any, + channel: Any, + consumers: list[Any], + wakeup: bool = True, + **kwargs: Any, + ) -> None: ... + def on_consume_end(self, connection: Any, channel: Any) -> None: ... + def on_connection_revived(self) -> None: ... + def on_connection_error(self, exc: Exception, interval: float) -> None: ... + def on_decode_error(self, message: Any, exc: Exception) -> None: ... + def on_iteration(self) -> None: ... + def maybe_conn_error(self, fun: Callable[..., Any]) -> Any: ... + def create_connection(self) -> kombu.Connection: ... + def establish_connection(self) -> kombu.Connection: ... + @contextmanager + def extra_context( + self, connection: kombu.Connection, channel: Any + ) -> Iterator[None]: ... + def event_from_message( + self, + body: Any, + localize: bool = True, + now: Callable[[], float] = ..., + tzfields: itemgetter[Any] = ..., + adjust_timestamp: Callable[..., float] = ..., + CLIENT_CLOCK_SKEW: int = -1, + ) -> tuple[str, dict[str, Any]]: ... + def get_consumers(self, Consumer: type[Any], channel: Any) -> list[Any]: ... + def wakeup_workers(self, channel: Any = None) -> None: ... diff --git a/celery-stubs/events/snapshot.pyi b/celery-stubs/events/snapshot.pyi new file mode 100644 index 0000000..5663f7b --- /dev/null +++ b/celery-stubs/events/snapshot.pyi @@ -0,0 +1,48 @@ +from typing import Any + +from celery.app.base import Celery +from celery.events.state import State +from typing_extensions import Self + +__all__ = ("Polaroid", "evcam") + +class Polaroid: + app: Celery + state: State + freq: float + timer: Any + + def __init__( + self, + state: State, + freq: float = 1.0, + maxrate: str | None = None, + cleanup_freq: float = 3600.0, + timer: Any | None = None, + app: Celery | None = None, + ) -> None: ... + cleanup_signal: Any + clear_after: bool + shutter_signal: Any + + def install(self) -> None: ... + def on_cleanup(self) -> None: ... + def on_shutter(self, state: State) -> None: ... + def shutter(self) -> None: ... + def capture(self) -> None: ... + def cancel(self) -> None: ... + def cleanup(self) -> None: ... + def __enter__(self) -> Self: ... + def __exit__(self, *args: object) -> None: ... + +def evcam( + camera: str, + freq: float = 1.0, + maxrate: str | None = None, + loglevel: int = 0, + logfile: str | None = None, + pidfile: str | None = None, + timer: Any | None = None, + app: Celery | None = None, + **kwargs: Any, +) -> None: ... diff --git a/celery-stubs/events/state.pyi b/celery-stubs/events/state.pyi new file mode 100644 index 0000000..ff8ce2e --- /dev/null +++ b/celery-stubs/events/state.pyi @@ -0,0 +1,181 @@ +from collections.abc import Callable, Iterator +from datetime import datetime +from decimal import Decimal +from typing import Any + +from kombu.utils.objects import cached_property + +__all__ = ("State", "Task", "Worker", "heartbeat_expires") + +def heartbeat_expires( + timestamp: float, + freq: float = 60, + expire_window: float = 200, + Decimal: type[Decimal] = ..., + float: type[float] = ..., + isinstance: Callable[..., bool] = ..., +) -> float: ... + +class Task: + # Attributes based on runtime inspection + uuid: str + name: str | None + state: str + received: float | None + sent: float | None + started: float | None + succeeded: float | None + failed: float | None + retried: float | None + revoked: float | None + rejected: float | None + args: str | None + kwargs: str | None + eta: datetime | None + expires: datetime | None + retries: int | None + result: Any + exception: str | None + traceback: str | None + worker: Worker | None + client: str | None + clock: int | None + timestamp: float | None + root_id: str | None + parent_id: str | None + exchange: str | None + routing_key: str | None + runtime: float | None + + merge_rules: dict[str, Any] + + @property + def id(self) -> str | None: ... + @property + def origin(self) -> str | None: ... + root: cached_property[str | None] + parent: cached_property[str | None] + + def __init__( + self, + uuid: str | None = None, + cluster_state: State | None = None, + children: list[str] | None = None, + **kwargs: Any, + ) -> None: ... + def event( + self, + type_: str | None, + timestamp: float | None = None, + local_received: float | None = None, + fields: dict[str, Any] | None = None, + precedence: Callable[..., int] = ..., + setattr: Callable[..., None] = ..., + task_event_to_state: Callable[..., str | None] = ..., + RETRY: str = "RETRY", + ) -> str | None: ... + def info( + self, + fields: list[str] | None = None, + extra: list[str] | None = None, + ) -> dict[str, Any]: ... + def as_dict(self) -> dict[str, Any]: ... + @property + def ready(self) -> bool: ... + +class Worker: + hostname: str + pid: int | None + freq: float + heartbeats: list[float] + clock: int + active: int | None + processed: int | None + loadavg: list[float] | None + sw_ident: str | None + sw_ver: str | None + sw_sys: str | None + expire_window: float + heartbeat_max: int + event: Any # member_descriptor at runtime + + @property + def id(self) -> str | None: ... + def __init__( + self, + hostname: str | None = None, + pid: int | None = None, + freq: float = 60, + heartbeats: list[float] | None = None, + clock: int = 0, + active: int | None = None, + processed: int | None = None, + loadavg: list[float] | None = None, + sw_ident: str | None = None, + sw_ver: str | None = None, + sw_sys: str | None = None, + ) -> None: ... + def update( + self, + f: dict[str, Any], + **kw: Any, + ) -> None: ... + @property + def heartbeat_expires(self) -> float: ... + @property + def alive(self) -> bool: ... + @property + def status_string(self) -> str: ... + +_Task = Task +_Worker = Worker + +class State: + event_count: int + task_count: int + heap_multiplier: int + max_workers_in_memory: int + max_tasks_in_memory: int + + Task: type[_Task] + Worker: type[_Worker] + + def __init__( + self, + callback: Callable[..., Any] | None = None, + workers: dict[str, _Worker] | None = None, + tasks: dict[str, _Task] | None = None, + taskheap: Any = None, + max_workers_in_memory: int = 5000, + max_tasks_in_memory: int = 10000, + on_node_join: Callable[..., Any] | None = None, + on_node_leave: Callable[..., Any] | None = None, + tasks_by_type: Callable[..., Any] | None = None, + tasks_by_worker: Callable[..., Any] | None = None, + ) -> None: ... + def freeze_while( + self, fun: Callable[..., Any], *args: Any, **kwargs: Any + ) -> Any: ... + def clear_tasks(self, ready: bool = True) -> None: ... + def clear(self, ready: bool = True) -> None: ... + def get_or_create_worker( + self, hostname: str, **kwargs: Any + ) -> tuple[_Worker, bool]: ... + def get_or_create_task(self, uuid: str) -> tuple[_Task, bool]: ... + def worker_event( + self, type_: str, fields: dict[str, Any] + ) -> tuple[_Worker, bool] | tuple[None, bool]: ... + def task_event( + self, type_: str, fields: dict[str, Any] + ) -> tuple[_Task, bool] | tuple[None, bool]: ... + def event(self, event: dict[str, Any]) -> tuple[_Worker | _Task | None, bool]: ... + def rebuild_taskheap(self, timetuple: Callable[..., Any] = ...) -> None: ... + def itertasks(self, limit: int | None = None) -> Iterator[tuple[str, _Task]]: ... + def tasks_by_time( + self, limit: int | None = None, reverse: bool = True + ) -> list[tuple[str, _Task]]: ... + def tasks_by_timestamp( + self, limit: int | None = None, reverse: bool = True + ) -> list[tuple[str, _Task]]: ... + def task_types(self) -> set[str]: ... + def alive_workers(self) -> list[_Worker]: ... diff --git a/celery-stubs/exceptions.pyi b/celery-stubs/exceptions.pyi index 6d93d3c..7f82ecd 100644 --- a/celery-stubs/exceptions.pyi +++ b/celery-stubs/exceptions.pyi @@ -9,13 +9,18 @@ from billiard.exceptions import ( WorkerLostError, ) from celery.canvas import Signature +from click.exceptions import ClickException from kombu.exceptions import OperationalError -__all__ = [ +__all__ = ( "AlreadyRegistered", "AlwaysEagerIgnored", + "BackendError", + "BackendGetMetaError", + "BackendStoreError", "CDeprecationWarning", "CPendingDeprecationWarning", + "CeleryCommandException", "CeleryError", "CeleryWarning", "ChordError", @@ -33,6 +38,7 @@ __all__ = [ "Reject", "Retry", "SecurityError", + "SecurityWarning", "SoftTimeLimitExceeded", "TaskError", "TaskPredicate", @@ -43,7 +49,8 @@ __all__ = [ "WorkerLostError", "WorkerShutdown", "WorkerTerminate", -] + "reraise", +) class CeleryWarning(UserWarning): ... class AlwaysEagerIgnored(CeleryWarning): ... @@ -101,3 +108,12 @@ class WorkerTerminate(SystemExit): ... SystemTerminate = WorkerTerminate class WorkerShutdown(SystemExit): ... +class BackendError(Exception): ... +class BackendGetMetaError(BackendError): ... +class BackendStoreError(BackendError): ... +class SecurityWarning(CeleryWarning): ... + +def reraise(tp: type[BaseException], value: BaseException, tb: Any = None) -> None: ... + +class CeleryCommandException(ClickException): + def __init__(self, message: str, exit_code: int) -> None: ... diff --git a/celery-stubs/execute.pyi b/celery-stubs/execute.pyi new file mode 100644 index 0000000..de1d630 --- /dev/null +++ b/celery-stubs/execute.pyi @@ -0,0 +1,41 @@ +from datetime import datetime +from typing import Any + +from celery.result import AsyncResult +from kombu import Connection +from kombu.messaging import Producer + +def send_task( + name: str, + args: tuple[Any, ...] | None = ..., + kwargs: dict[str, Any] | None = ..., + countdown: float | None = ..., + eta: datetime | None = ..., + task_id: str | None = ..., + producer: Producer | None = ..., + connection: Connection | None = ..., + router: Any | None = ..., + result_cls: type[AsyncResult[Any]] | None = ..., + expires: float | datetime | None = ..., + publisher: Any | None = ..., + link: Any | None = ..., + link_error: Any | None = ..., + add_to_parent: bool = ..., + group_id: str | None = ..., + group_index: int | None = ..., + retries: int = ..., + chord: Any | None = ..., + reply_to: str | None = ..., + time_limit: float | None = ..., + soft_time_limit: float | None = ..., + root_id: str | None = ..., + parent_id: str | None = ..., + route_name: str | None = ..., + shadow: str | None = ..., + chain: Any | None = ..., + task_type: Any | None = ..., + replaced_task_nesting: int = ..., + **options: Any, +) -> AsyncResult[Any]: ... + +__all__ = ["send_task"] diff --git a/celery-stubs/fixups/__init__.pyi b/celery-stubs/fixups/__init__.pyi new file mode 100644 index 0000000..a01af93 --- /dev/null +++ b/celery-stubs/fixups/__init__.pyi @@ -0,0 +1 @@ +# celery.fixups is a package with no public exports at package level diff --git a/celery-stubs/fixups/django.pyi b/celery-stubs/fixups/django.pyi new file mode 100644 index 0000000..ed3e61e --- /dev/null +++ b/celery-stubs/fixups/django.pyi @@ -0,0 +1,19 @@ +from datetime import datetime +from typing import Any + +from celery.app.base import Celery + +__all__ = ("DjangoFixup", "fixup") + +class DjangoFixup: + app: Celery + def __init__(self, app: Celery) -> None: ... + def install(self) -> None: ... + def autodiscover_tasks(self) -> None: ... + def now(self, utc: bool = False) -> datetime: ... + def on_import_modules(self, **kwargs: Any) -> None: ... + def on_worker_init(self, **kwargs: Any) -> None: ... + @property + def worker_fixup(self) -> Any: ... + +def fixup(app: Celery, env: str = "DJANGO_SETTINGS_MODULE") -> DjangoFixup | None: ... diff --git a/celery-stubs/loaders/__init__.pyi b/celery-stubs/loaders/__init__.pyi index e69de29..61dc0a0 100644 --- a/celery-stubs/loaders/__init__.pyi +++ b/celery-stubs/loaders/__init__.pyi @@ -0,0 +1,5 @@ +from celery.loaders.base import BaseLoader + +__all__ = ("get_loader_cls",) + +def get_loader_cls(loader: str) -> type[BaseLoader]: ... diff --git a/celery-stubs/loaders/app.pyi b/celery-stubs/loaders/app.pyi new file mode 100644 index 0000000..da7ff71 --- /dev/null +++ b/celery-stubs/loaders/app.pyi @@ -0,0 +1,5 @@ +from celery.loaders.base import BaseLoader + +__all__ = ("AppLoader",) + +class AppLoader(BaseLoader): ... diff --git a/celery-stubs/loaders/base.pyi b/celery-stubs/loaders/base.pyi index 158807c..3afbcd0 100644 --- a/celery-stubs/loaders/base.pyi +++ b/celery-stubs/loaders/base.pyi @@ -1,4 +1,52 @@ +import re +from datetime import datetime +from types import ModuleType from typing import Any +from celery.app.base import Celery + +__all__ = ("BaseLoader",) + class BaseLoader: + app: Celery + builtin_modules: frozenset[str] + configured: bool + worker_initialized: bool + override_backends: dict[str, str] + + def __init__(self, app: Celery, **kwargs: Any) -> None: ... def import_default_modules(self) -> list[Any]: ... + def autodiscover_tasks( + self, packages: list[str], related_name: str = "tasks" + ) -> None: ... + def cmdline_config_parser( + self, + args: list[str], + namespace: str = "celery", + re_type: re.Pattern[str] = ..., + extra_types: dict[str, Any] | None = None, + override_types: dict[str, Any] | None = None, + ) -> dict[str, Any]: ... + @property + def conf(self) -> Any: ... + def config_from_object(self, obj: Any, silent: bool = False) -> None: ... + @property + def default_modules(self) -> set[str]: ... + def find_module(self, module: str) -> ModuleType | None: ... + def import_from_cwd( + self, module: str, imp: Any | None = None, package: str | None = None + ) -> ModuleType: ... + def import_module(self, module: str, package: str | None = None) -> ModuleType: ... + def import_task_module(self, module: str) -> ModuleType: ... + def init_worker(self) -> None: ... + def init_worker_process(self) -> None: ... + def now(self, utc: bool = True) -> datetime: ... + def on_process_cleanup(self) -> None: ... + def on_task_init(self, task_id: str, task: Any) -> None: ... + def on_worker_init(self) -> None: ... + def on_worker_process_init(self) -> None: ... + def on_worker_shutdown(self) -> None: ... + def read_configuration( + self, env: str = "CELERY_CONFIG_MODULE" + ) -> dict[str, Any]: ... + def shutdown_worker(self) -> None: ... diff --git a/celery-stubs/loaders/default.pyi b/celery-stubs/loaders/default.pyi new file mode 100644 index 0000000..3205ae2 --- /dev/null +++ b/celery-stubs/loaders/default.pyi @@ -0,0 +1,16 @@ +from typing import Any + +from celery.loaders.base import BaseLoader +from typing_extensions import override + +__all__ = ("DEFAULT_CONFIG_MODULE", "Loader") + +DEFAULT_CONFIG_MODULE: str + +class Loader(BaseLoader): + @override + def read_configuration( # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + self, + fail_silently: bool = True, # type: ignore[override] + ) -> dict[str, Any]: ... + def setup_settings(self, settingsdict: dict[str, Any]) -> dict[str, Any]: ... diff --git a/celery-stubs/local.pyi b/celery-stubs/local.pyi index 0b85c6b..1eeb6d5 100644 --- a/celery-stubs/local.pyi +++ b/celery-stubs/local.pyi @@ -1,7 +1,9 @@ from collections.abc import Callable -from typing import Generic, TypeAlias, TypeVar +from typing import Any, Generic, TypeAlias, TypeVar -from typing_extensions import Self +__all__ = ("PromiseProxy", "Proxy", "maybe_evaluate", "try_import") + +from typing_extensions import Self, override _T = TypeVar("_T") _R = TypeVar("_R") @@ -9,14 +11,92 @@ _R = TypeVar("_R") _Getter: TypeAlias = Callable[[_T], _R] _Setter: TypeAlias = Callable[[_T, _R], None] +def maybe_evaluate(obj: Any) -> Any: ... +def try_import(module: str, default: _T = ...) -> Any | _T: ... + class class_property(Generic[_T, _R]): __get: _Getter[_T, _R] __set: _Setter[_T, _R] | None def __init__( self, - getter: _Getter[_T, _R], + getter: _Getter[_T, _R] | None = None, setter: _Setter[_T, _R] | None = None, ) -> None: ... def __get__(self, obj: _T | None, type: type[_T] | None = None) -> _R: ... def __set__(self, obj: _T | None, value: _R) -> Self: ... def setter(self, setter: _Setter[_T, _R]) -> Self: ... + +class Proxy(Generic[_T]): + def __init__( + self, + local: Callable[[], _T], + args: tuple[Any, ...] | None = ..., + kwargs: dict[str, Any] | None = ..., + name: str | None = ..., + __doc__: str | None = ..., + ) -> None: ... + def _get_current_object(self) -> _T: ... + # All the dunder methods that proxy to the wrapped object + def __abs__(self) -> Any: ... + def __add__(self, other: Any) -> Any: ... + def __and__(self, other: Any) -> Any: ... + def __bool__(self) -> bool: ... + def __call__(self, *a: Any, **kw: Any) -> Any: ... + def __coerce__(self, other: Any) -> Any: ... + def __complex__(self) -> complex: ... + def __contains__(self, i: Any) -> bool: ... + def __delitem__(self, key: Any) -> None: ... + def __divmod__(self, other: Any) -> Any: ... + def __enter__(self) -> Any: ... + def __exit__(self, *a: object, **kw: Any) -> Any: ... + def __float__(self) -> float: ... + def __floordiv__(self, other: Any) -> Any: ... + def __ge__(self, other: Any) -> bool: ... + def __getitem__(self, i: Any) -> Any: ... + def __gt__(self, other: Any) -> bool: ... + def __hex__(self) -> str: ... + def __index__(self) -> int: ... + def __int__(self) -> int: ... + def __invert__(self) -> Any: ... + def __iter__(self) -> Any: ... + def __le__(self, other: Any) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other: Any) -> bool: ... + def __mod__(self, other: Any) -> Any: ... + def __mul__(self, other: Any) -> Any: ... + @override + def __ne__(self, other: object) -> bool: ... + def __neg__(self) -> Any: ... + def __oct__(self) -> str: ... + def __or__(self, other: Any) -> Any: ... + def __pos__(self) -> Any: ... + def __pow__(self, other: Any) -> Any: ... + @override + def __reduce__(self) -> tuple[Any, ...]: ... + def __rshift__(self, other: Any) -> Any: ... + def __lshift__(self, other: Any) -> Any: ... + def __setitem__(self, key: Any, value: Any) -> None: ... + def __sub__(self, other: Any) -> Any: ... + def __truediv__(self, other: Any) -> Any: ... + def __xor__(self, other: Any) -> Any: ... + @property + def __name__(self) -> str: ... + +class PromiseProxy(Proxy[_T]): + def __init__( + self, + local: Callable[[], _T], + args: tuple[Any, ...] | None = ..., + kwargs: dict[str, Any] | None = ..., + name: str | None = ..., + __doc__: str | None = ..., + ) -> None: ... + def __evaluate__( + self, + _clean: tuple[str, ...] = ("_Proxy__local", "_Proxy__args", "_Proxy__kwargs"), + ) -> _T: ... + def __evaluated__(self) -> bool: ... + def __maybe_evaluate__(self) -> _T: ... + @property + def __pending__(self) -> bool: ... + def __then__(self, fun: Callable[..., Any], *args: Any, **kwargs: Any) -> Any: ... diff --git a/celery-stubs/messaging.pyi b/celery-stubs/messaging.pyi new file mode 100644 index 0000000..92ab3fc --- /dev/null +++ b/celery-stubs/messaging.pyi @@ -0,0 +1,34 @@ +from typing import Any + +from kombu import Connection +from kombu.transport.virtual import Channel + +def establish_connection( + hostname: str | None = ..., + userid: str | None = ..., + password: str | None = ..., + virtual_host: str | None = ..., + port: int | None = ..., + ssl: bool | dict[str, Any] | None = ..., + connect_timeout: float | None = ..., + transport: str | None = ..., + transport_options: dict[str, Any] | None = ..., + heartbeat: float | None = ..., + login_method: str | None = ..., + failover_strategy: str | None = ..., + **kwargs: Any, +) -> Connection: ... +def get_consumer_set( + channel: Channel, + queues: Any | None = ..., + accept: list[str] | None = ..., + **kw: Any, +) -> Any: ... +def TaskConsumer( + channel: Channel, + queues: Any | None = ..., + accept: list[str] | None = ..., + **kw: Any, +) -> Any: ... + +__all__ = ["TaskConsumer", "establish_connection", "get_consumer_set"] diff --git a/celery-stubs/platforms.pyi b/celery-stubs/platforms.pyi new file mode 100644 index 0000000..7749204 --- /dev/null +++ b/celery-stubs/platforms.pyi @@ -0,0 +1,143 @@ +from collections.abc import Callable, Iterator +from contextlib import contextmanager +from signal import Handlers +from signal import Signals as SignalEnum +from typing import Any + +from typing_extensions import Self + +__all__ = ( + "EX_FAILURE", + "EX_OK", + "EX_UNAVAILABLE", + "EX_USAGE", + "IS_WINDOWS", + "SIGMAP", + "SYSTEM", + "DaemonContext", + "IS_macOS", + "LockFailed", + "Pidfile", + "close_open_fds", + "create_pidlock", + "detached", + "fd_by_path", + "get_errno_name", + "get_fdmax", + "ignore_errno", + "initgroups", + "isatty", + "maybe_drop_privileges", + "parse_gid", + "parse_uid", + "pyimplementation", + "set_mp_process_title", + "set_process_title", + "setgid", + "setgroups", + "setuid", + "signal_name", + "signals", +) + +DAEMON_WORKDIR: str +EX_OK: int +EX_FAILURE: int +EX_UNAVAILABLE: int +EX_USAGE: int +SYSTEM: str +IS_macOS: bool +IS_WINDOWS: bool +SIGMAP: dict[int, str] + +class Signals: + default: Handlers + ignored: Handlers + def arm_alarm(self, seconds: float) -> None: ... + def ignore(self, *signals: int) -> None: ... + def reset(self, sig: int) -> None: ... + def reset_alarm(self) -> None: ... + def signum(self, name: int | str) -> int: ... + def supported(self, name: int | str) -> bool: ... + def update( + self, + _d_: dict[int | SignalEnum, Callable[[int, Any], None]] | None = None, + **sigmap: Callable[[int, Any], None], + ) -> None: ... + def __getitem__(self, name: int | str) -> Callable[[int, Any], None] | None: ... + def __setitem__( + self, name: int | str, handler: Callable[[int, Any], None] + ) -> None: ... + +signals: Signals + +def pyimplementation() -> str: ... +def signal_name(signum: int) -> str | None: ... +def get_errno_name(n: int) -> str: ... +def get_fdmax(default: int | None = None) -> int: ... +def close_open_fds(keep: set[int] | None = None) -> None: ... +def fd_by_path(paths: list[str]) -> list[int]: ... +@contextmanager +def ignore_errno(*errnos: int) -> Iterator[None]: ... +def set_process_title(progname: str, info: str | None = None) -> None: ... +def set_mp_process_title( + progname: str, info: str | None = None, hostname: str | None = None +) -> None: ... +def maybe_drop_privileges( + uid: int | str | None = None, gid: int | str | None = None +) -> None: ... +def setgroups(groups: list[int]) -> None: ... +def initgroups(uid: int, gid: int) -> None: ... +def setgid(gid: int | str) -> None: ... +def setuid(uid: int | str) -> None: ... +def parse_uid(uid: int | str) -> int: ... +def parse_gid(gid: int | str) -> int: ... +def isatty(fh: Any) -> bool: ... +def detached( + logfile: str | None = None, + pidfile: str | None = None, + uid: int | str | None = None, + gid: int | str | None = None, + umask: int = 0, + workdir: str | None = None, + fake: bool = False, + **opts: Any, +) -> Any: ... +def create_pidlock(pidfile: str) -> Any: ... + +class DaemonContext: + open_fds: set[int] | None + pidfile: str | None + workdir: str + umask: int | None + + def __init__( + self, + pidfile: str | None = None, + workdir: str | None = None, + umask: int | None = None, + fake: bool = False, + after_chdir: Callable[[], None] | None = None, + after_forkers: bool = True, + **kwargs: Any, + ) -> None: ... + def open(self) -> DaemonContext: ... + def close(self, *args: Any) -> None: ... + def redirect_to_null(self, fd: int) -> None: ... + def __enter__(self) -> Self: ... + def __exit__(self, *exc_info: object) -> None: ... + +class Pidfile: + path: str | None + def __init__(self, path: str) -> None: ... + def acquire(self) -> Pidfile: ... + def is_locked(self) -> bool: ... + def release(self, *args: Any) -> None: ... + def read_pid(self) -> int | None: ... + def remove(self) -> None: ... + def remove_if_stale(self) -> bool: ... + def write_pid(self) -> None: ... + def __enter__(self) -> Self: ... + def __exit__(self, *exc_info: object) -> None: ... + +class LockFailed(Exception): ... diff --git a/celery-stubs/result.pyi b/celery-stubs/result.pyi index 1811009..e495851 100644 --- a/celery-stubs/result.pyi +++ b/celery-stubs/result.pyi @@ -10,10 +10,21 @@ from typing import ( TypeVar, ) +__all__ = ( + "AsyncResult", + "EagerResult", + "GroupResult", + "ResultBase", + "ResultSet", + "result_from_tuple", +) + import kombu from celery.app.base import Celery from celery.backends.base import Backend +from celery.exceptions import TimeoutError as CeleryTimeoutError from celery.utils.graph import DependencyGraph, GraphFormatter +from typing_extensions import override from vine import promise @contextmanager @@ -29,9 +40,12 @@ _State: TypeAlias = Literal["PENDING", "STARTED", "RETRY", "FAILURE", "SUCCESS"] _R_co = TypeVar("_R_co", covariant=True) class AsyncResult(ResultBase, Generic[_R_co]): - app: Celery - id: str - backend: Backend + TimeoutError: type[CeleryTimeoutError] + app: ( + Celery # None at class level, always resolved via app_or_default() on instances + ) + id: str # None at class level, always set on instances + backend: Backend # None at class level, always resolved via self.app.backend on instances parent: ResultBase | None on_ready: promise def __init__( @@ -42,6 +56,9 @@ class AsyncResult(ResultBase, Generic[_R_co]): app: Celery | None = ..., parent: ResultBase | None = ..., ) -> None: ... + def __copy__(self) -> AsyncResult[_R_co]: ... + def __del__(self) -> None: ... + def __reduce_args__(self) -> tuple[str, Backend]: ... @property def ignored(self) -> bool: ... @ignored.setter @@ -79,7 +96,20 @@ class AsyncResult(ResultBase, Generic[_R_co]): PROPAGATE_STATES: frozenset[str] = ..., ) -> _R_co: ... def collect( - self, intermediate: bool = ..., **kwargs: Any + self, + intermediate: bool = ..., + *, + # options (passed through to get()) + timeout: float | None = ..., + propagate: bool = ..., + interval: float = ..., + no_ack: bool = ..., + follow_parents: bool = ..., + callback: Callable[..., Any] | None = ..., + on_message: Callable[..., Any] | None = ..., + on_interval: Callable[..., Any] | None = ..., + disable_sync_subtasks: bool = ..., + **kwargs: Any, ) -> Iterator[tuple[AsyncResult[Any], object]]: ... def get_leaf(self) -> object: ... def iterdeps( @@ -92,6 +122,33 @@ class AsyncResult(ResultBase, Generic[_R_co]): def maybe_throw( self, propagate: bool = ..., callback: Callable[..., Any] | None = ... ) -> object: ... + def maybe_reraise( + self, propagate: bool = ..., callback: Callable[..., Any] | None = ... + ) -> None: ... + def as_list(self) -> list[AsyncResult[Any]]: ... + def wait( + self, + timeout: float | None = ..., + propagate: bool = ..., + interval: float = ..., + no_ack: bool = ..., + follow_parents: bool = ..., + callback: Callable[..., Any] | None = ..., + on_message: Callable[..., Any] | None = ..., + on_interval: Callable[..., Any] | None = ..., + disable_sync_subtasks: bool = ..., + EXCEPTION_STATES: frozenset[str] = ..., + PROPAGATE_STATES: frozenset[str] = ..., + ) -> _R_co: ... + def revoke_by_stamped_headers( + self, + headers: list[str], + connection: kombu.Connection | None = ..., + terminate: bool = ..., + signal: str | None = ..., + wait: bool = ..., + timeout: float | None = ..., + ) -> None: ... def build_graph( self, intermediate: bool = ..., formatter: GraphFormatter | None = ... ) -> DependencyGraph: ... @@ -143,6 +200,26 @@ class EagerResult(AsyncResult[_R_co]): traceback: str | None = ..., name: str | None = ..., ) -> None: ... + @override + def __copy__(self) -> EagerResult[_R_co]: ... + @override + def __reduce_args__(self) -> tuple[str, _R_co, str, str | None]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + @override + def get( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + self, + timeout: float | None = ..., + propagate: bool = ..., + disable_sync_subtasks: bool = ..., + **kwargs: Any, + ) -> _R_co: ... + @override + def wait( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + self, + timeout: float | None = ..., + propagate: bool = ..., + disable_sync_subtasks: bool = ..., + **kwargs: Any, + ) -> _R_co: ... class ResultSet(ResultBase): results: list[AsyncResult[Any]] | None @@ -154,6 +231,89 @@ class ResultSet(ResultBase): ready_barrier: Any | None = ..., **kwargs: Any, ) -> None: ... + def __getitem__(self, index: int) -> AsyncResult[Any]: ... + def __iter__(self) -> Iterator[AsyncResult[Any]]: ... + def __len__(self) -> int: ... + def add(self, result: AsyncResult[Any]) -> None: ... + @property + def backend(self) -> Backend: ... + def clear(self) -> None: ... + def completed_count(self) -> int: ... + def discard(self, result: AsyncResult[Any]) -> None: ... + def failed(self) -> bool: ... + def forget(self) -> None: ... + def get( + self, + timeout: float | None = ..., + propagate: bool = ..., + interval: float = ..., + callback: Callable[..., Any] | None = ..., + no_ack: bool = ..., + on_message: Callable[..., Any] | None = ..., + disable_sync_subtasks: bool = ..., + on_interval: Callable[..., Any] | None = ..., + ) -> list[Any]: ... + def iter_native( + self, + timeout: float | None = ..., + interval: float = ..., + no_ack: bool = ..., + on_message: Callable[..., Any] | None = ..., + on_interval: Callable[..., Any] | None = ..., + ) -> Iterator[tuple[str, Any]]: ... + def join( + self, + timeout: float | None = ..., + propagate: bool = ..., + interval: float = ..., + callback: Callable[..., Any] | None = ..., + no_ack: bool = ..., + on_message: Callable[..., Any] | None = ..., + disable_sync_subtasks: bool = ..., + on_interval: Callable[..., Any] | None = ..., + ) -> list[Any]: ... + def join_native( + self, + timeout: float | None = ..., + propagate: bool = ..., + interval: float = ..., + callback: Callable[..., Any] | None = ..., + no_ack: bool = ..., + on_message: Callable[..., Any] | None = ..., + on_interval: Callable[..., Any] | None = ..., + disable_sync_subtasks: bool = ..., + ) -> list[Any]: ... + def maybe_reraise( + self, callback: Callable[..., Any] | None = ..., propagate: bool = ... + ) -> None: ... + def maybe_throw( + self, callback: Callable[..., Any] | None = ..., propagate: bool = ... + ) -> None: ... + def ready(self) -> bool: ... + def remove(self, result: AsyncResult[Any]) -> None: ... + def revoke( + self, + connection: kombu.Connection | None = ..., + terminate: bool = ..., + signal: str | None = ..., + wait: bool = ..., + timeout: float | None = ..., + ) -> None: ... + def successful(self) -> bool: ... + @property + def supports_native_join(self) -> bool: ... + def then( + self, + callback: Callable[..., Any], + on_error: Callable[..., Any] | None = ..., + weak: bool = ..., + ) -> promise: ... + def update(self, results: list[AsyncResult[Any]]) -> None: ... + def waiting(self) -> bool: ... + +def result_from_tuple( + r: tuple[Any, ...], app: Celery | None = ... +) -> AsyncResult[Any]: ... class GroupResult(ResultSet): id: str | None @@ -162,9 +322,11 @@ class GroupResult(ResultSet): id: str | None = ..., results: list[AsyncResult[Any]] | None = ..., parent: ResultBase | None = ..., - app: Celery | None = ..., **kwargs: Any, ) -> None: ... + def __bool__(self) -> bool: ... + def __reduce_args__(self) -> tuple[str | None, list[AsyncResult[Any]] | None]: ... + def as_tuple(self) -> tuple[str | None, list[tuple[Any, ...]] | None]: ... @classmethod def restore( cls, diff --git a/celery-stubs/schedules.pyi b/celery-stubs/schedules.pyi index 71188c7..d219a52 100644 --- a/celery-stubs/schedules.pyi +++ b/celery-stubs/schedules.pyi @@ -1,7 +1,16 @@ import numbers from collections.abc import Callable -from datetime import datetime, timedelta -from typing import Literal, NamedTuple, TypeAlias +from datetime import datetime, timedelta, tzinfo +from typing import Any, Literal, NamedTuple, TypeAlias + +__all__ = ( + "ParseException", + "crontab", + "crontab_parser", + "maybe_schedule", + "schedule", + "solar", +) import ephem from celery.app.base import Celery @@ -26,7 +35,7 @@ class BaseSchedule: def now(self) -> datetime: ... def remaining_estimate(self, last_run_at: datetime) -> timedelta: ... def is_due(self, last_run_at: datetime) -> schedstate: ... - def maybe_make_aware(self, dt: datetime) -> datetime: ... + def maybe_make_aware(self, dt: datetime, naive_as_utc: bool = True) -> datetime: ... @property def app(self) -> Celery: ... @app.setter @@ -40,6 +49,7 @@ class BaseSchedule: def __eq__(self, other: object) -> bool: ... class schedule(BaseSchedule): + relative: bool def __init__( self, run_every: float | timedelta | None = ..., @@ -55,26 +65,37 @@ class schedule(BaseSchedule): _ModuleLevelParseException = ParseException class crontab_parser: - ParseException: _ModuleLevelParseException + ParseException: type[ParseException] def __init__(self, max_: int = ..., min_: int = ...) -> None: ... def parse(self, spec: str) -> set[int]: ... +Cronspec: TypeAlias = str | int | list[int] + class crontab(BaseSchedule): def __init__( self, - minute: str | int | list[int] = ..., - hour: str | int | list[int] = ..., - day_of_week: str | int | list[int] = ..., - day_of_month: str | int | list[int] = ..., - month_of_year: str | int | list[int] = ..., - nowfun: Callable[[], datetime] | None = ..., - app: Celery | None = ..., + minute: Cronspec = "*", + hour: Cronspec = "*", + day_of_week: Cronspec = "*", + day_of_month: Cronspec = "*", + month_of_year: Cronspec = "*", + **kwargs: Any, ) -> None: ... + @classmethod + def from_string(cls, crontab: str) -> crontab: ... def remaining_delta( - self, last_run_at: datetime, tz: str | None = ..., ffwd: ffwd = ... - ) -> tuple[datetime, timedelta, datetime]: ... + self, last_run_at: datetime, tz: tzinfo | None = None, ffwd: type[ffwd] = ... + ) -> tuple[datetime, Any, datetime]: ... + @override + def remaining_estimate( + self, last_run_at: datetime, ffwd: type[ffwd] = ... + ) -> timedelta: ... -def maybe_schedule(s: numbers.Number | timedelta | BaseSchedule) -> schedule: ... +def maybe_schedule( + s: numbers.Number | timedelta | BaseSchedule, + relative: bool = False, + app: Celery | None = None, +) -> float | timedelta | BaseSchedule: ... _SolarEvent: TypeAlias = Literal[ "dawn_astronomical", @@ -98,6 +119,5 @@ class solar(BaseSchedule): event: _SolarEvent, lat: float, lon: float, - nowfun: Callable[[], datetime] | None = ..., - app: Celery | None = ..., + **kwargs: Any, ) -> None: ... diff --git a/celery-stubs/security/__init__.pyi b/celery-stubs/security/__init__.pyi new file mode 100644 index 0000000..6945cd3 --- /dev/null +++ b/celery-stubs/security/__init__.pyi @@ -0,0 +1,17 @@ +from celery.app.base import Celery + +__all__ = ("setup_security",) + +def setup_security( + allowed_serializers: list[str] | None = None, + key: str | None = None, + key_password: str | None = None, + cert: str | None = None, + store: str | None = None, + digest: str | None = None, + serializer: str = "json", + app: Celery | None = None, +) -> None: ... +def disable_untrusted_serializers( + whitelist: list[str] | None = None, +) -> None: ... diff --git a/celery-stubs/security/certificate.pyi b/celery-stubs/security/certificate.pyi new file mode 100644 index 0000000..2e7d3ee --- /dev/null +++ b/celery-stubs/security/certificate.pyi @@ -0,0 +1,21 @@ +from typing import Any + +__all__ = ("CertStore", "Certificate", "FSCertStore") + +class Certificate: + def __init__(self, cert: bytes | str) -> None: ... + def has_expired(self) -> bool: ... + def get_id(self) -> str: ... + def get_pubkey(self) -> Any: ... + def get_serial_number(self) -> int: ... + def get_issuer(self) -> str: ... + def verify(self, data: bytes, signature: bytes, digest: str) -> None: ... + +class CertStore: + def __init__(self) -> None: ... + def __getitem__(self, id: str) -> Certificate: ... + def itercerts(self) -> list[Certificate]: ... + def add_cert(self, cert: Certificate) -> None: ... + +class FSCertStore(CertStore): + def __init__(self, path: str) -> None: ... diff --git a/celery-stubs/security/key.pyi b/celery-stubs/security/key.pyi new file mode 100644 index 0000000..16c3bc0 --- /dev/null +++ b/celery-stubs/security/key.pyi @@ -0,0 +1,5 @@ +__all__ = ("PrivateKey",) + +class PrivateKey: + def __init__(self, key: bytes | str, password: str | None = None) -> None: ... + def sign(self, data: bytes, digest: str) -> bytes: ... diff --git a/celery-stubs/security/serialization.pyi b/celery-stubs/security/serialization.pyi new file mode 100644 index 0000000..923f6df --- /dev/null +++ b/celery-stubs/security/serialization.pyi @@ -0,0 +1,27 @@ +from typing import Any + +from celery.security.certificate import Certificate, CertStore +from celery.security.key import PrivateKey + +__all__ = ("SecureSerializer", "register_auth") + +class SecureSerializer: + def __init__( + self, + key: PrivateKey | None = None, + cert: Certificate | None = None, + cert_store: CertStore | None = None, + digest: str = "sha256", + serializer: str = "json", + ) -> None: ... + def serialize(self, data: Any) -> bytes: ... + def deserialize(self, data: bytes) -> Any: ... + +def register_auth( + key: str | None = None, + key_password: str | None = None, + cert: str | None = None, + store: str | None = None, + digest: str = "sha256", + serializer: str = "json", +) -> SecureSerializer: ... diff --git a/celery-stubs/security/utils.pyi b/celery-stubs/security/utils.pyi new file mode 100644 index 0000000..e27e0d3 --- /dev/null +++ b/celery-stubs/security/utils.pyi @@ -0,0 +1,13 @@ +from collections.abc import Iterator +from contextlib import contextmanager +from typing import Any + +__all__ = ("get_digest_algorithm", "reraise_errors") + +def get_digest_algorithm(digest: str = "sha256") -> Any: ... +@contextmanager +def reraise_errors( + msg: str = "{0!r}", errors: tuple[type[Exception], ...] | None = None +) -> Iterator[None]: ... + +class SecurityError(Exception): ... diff --git a/celery-stubs/signals.pyi b/celery-stubs/signals.pyi index fc2def2..9d06c71 100644 --- a/celery-stubs/signals.pyi +++ b/celery-stubs/signals.pyi @@ -1,6 +1,6 @@ from celery.utils.dispatch import Signal -__all__ = [ +__all__ = ( "after_setup_logger", "after_setup_task_logger", "after_task_publish", @@ -19,16 +19,20 @@ __all__ = [ "task_internal_error", "task_postrun", "task_prerun", + "task_received", + "task_rejected", "task_retry", "task_revoked", "task_success", + "task_unknown", "worker_before_create_process", "worker_init", "worker_process_init", + "worker_process_shutdown", "worker_ready", "worker_shutdown", "worker_shutting_down", -] +) before_task_publish: Signal after_task_publish: Signal diff --git a/celery-stubs/states.pyi b/celery-stubs/states.pyi index be9280a..136fd9b 100644 --- a/celery-stubs/states.pyi +++ b/celery-stubs/states.pyi @@ -37,7 +37,7 @@ PROPAGATE_STATES: frozenset[str] ALL_STATES: frozenset[str] -__all__ = [ +__all__ = ( "EXCEPTION_STATES", "FAILURE", "IGNORED", @@ -52,4 +52,4 @@ __all__ = [ "UNREADY_STATES", "precedence", "state", -] +) diff --git a/celery-stubs/utils/__init__.pyi b/celery-stubs/utils/__init__.pyi index fb49268..7ffd173 100644 --- a/celery-stubs/utils/__init__.pyi +++ b/celery-stubs/utils/__init__.pyi @@ -1 +1,57 @@ +from collections.abc import Callable, Iterable, Sequence +from types import ModuleType +from typing import Any, TypeVar + +import kombu +from kombu.utils.functional import LRUCache +from kombu.utils.objects import cached_property as cached_property from kombu.utils.uuid import uuid as uuid + +__all__ = ( + "LOG_LEVELS", + "cached_property", + "chunks", + "gen_task_name", + "gen_unique_id", + "get_cls_by_name", + "get_full_cls_name", + "import_from_cwd", + "instantiate", + "memoize", + "nodename", + "nodesplit", + "noop", + "uuid", + "worker_direct", +) + +LOG_LEVELS: dict[str, int] +nodenames: ModuleType +_T = TypeVar("_T") + +def chunks(it: Iterable[_T], n: int) -> Iterable[Sequence[_T]]: ... +def gen_task_name(app: Any, name: str, module_name: str) -> str: ... +def gen_unique_id() -> str: ... +def get_cls_by_name( + name: str, + aliases: dict[str, str] | None = None, + imp: Any = None, + package: str | None = None, + sep: str = ".", + default: Any = None, + **kwargs: Any, +) -> Any: ... +def get_full_cls_name(obj: Any) -> str: ... +def import_from_cwd( + module: str, imp: Any = None, package: str | None = None +) -> Any: ... +def instantiate(name: str, *args: Any, **kwargs: Any) -> Any: ... +def memoize( + maxsize: int | None = None, + keyfun: Callable[..., Any] | None = None, + Cache: type[LRUCache[Any, Any]] = ..., +) -> Callable[[Callable[..., _T]], Callable[..., _T]]: ... +def nodename(name: str, hostname: str) -> str: ... +def nodesplit(name: str) -> tuple[None, str] | list[str]: ... +def noop(*args: Any, **kwargs: Any) -> None: ... +def worker_direct(hostname: str | kombu.Queue) -> kombu.Queue: ... diff --git a/celery-stubs/utils/abstract.pyi b/celery-stubs/utils/abstract.pyi index caf09d8..ea09228 100644 --- a/celery-stubs/utils/abstract.pyi +++ b/celery-stubs/utils/abstract.pyi @@ -1,3 +1,76 @@ -class _AbstractClass: ... -class CallableTask(_AbstractClass): ... -class CallableSignature(CallableTask): ... +from abc import ABC, ABCMeta, abstractmethod +from typing import Any + +__all__ = ("CallableSignature", "CallableTask") + +class CallableTask(metaclass=ABCMeta): + __required_attributes__: frozenset[str] + + @abstractmethod + def apply(self, *args: Any, **kwargs: Any) -> Any: ... + @abstractmethod + def apply_async(self, *args: Any, **kwargs: Any) -> Any: ... + @abstractmethod + def delay(self, *args: Any, **kwargs: Any) -> Any: ... + @classmethod + def register(cls, other: type) -> type: ... + +class CallableSignature(CallableTask, ABC): + __required_attributes__: frozenset[str] + + @property + @abstractmethod + def app(self) -> Any: ... + @property + @abstractmethod + def args(self) -> tuple[Any, ...]: ... + @property + @abstractmethod + def chord_size(self) -> int | None: ... + @property + @abstractmethod + def id(self) -> str | None: ... + @property + @abstractmethod + def immutable(self) -> bool: ... + @property + @abstractmethod + def kwargs(self) -> dict[str, Any]: ... + @property + @abstractmethod + def name(self) -> str | None: ... + @property + @abstractmethod + def options(self) -> dict[str, Any]: ... + @property + @abstractmethod + def subtask_type(self) -> str | None: ... + @property + @abstractmethod + def task(self) -> str | None: ... + @property + @abstractmethod + def type(self) -> Any: ... + @abstractmethod + def __invert__(self) -> Any: ... + @abstractmethod + def __or__(self, other: Any) -> Any: ... + @abstractmethod + def clone( + self, args: tuple[Any, ...] | None = None, kwargs: dict[str, Any] | None = None + ) -> Any: ... + @abstractmethod + def freeze( + self, + id: str | None = None, + group_id: str | None = None, + chord: Any | None = None, + root_id: str | None = None, + group_index: int | None = None, + ) -> Any: ... + @abstractmethod + def link(self, callback: Any) -> Any: ... + @abstractmethod + def link_error(self, errback: Any) -> Any: ... + @abstractmethod + def set(self, immutable: bool | None = None, **options: Any) -> Any: ... diff --git a/celery-stubs/utils/annotations.pyi b/celery-stubs/utils/annotations.pyi new file mode 100644 index 0000000..fa08e31 --- /dev/null +++ b/celery-stubs/utils/annotations.pyi @@ -0,0 +1,6 @@ +from typing import Any + +def annotation_is_class(annotation: Any) -> bool: ... +def annotation_issubclass(annotation: Any, cls: type) -> bool: ... +def get_optional_arg(annotation: Any) -> Any: ... +def is_none_type(value: Any) -> bool: ... diff --git a/celery-stubs/utils/collections.pyi b/celery-stubs/utils/collections.pyi index d33a8f9..2725a71 100644 --- a/celery-stubs/utils/collections.pyi +++ b/celery-stubs/utils/collections.pyi @@ -1,16 +1,167 @@ -from collections.abc import MutableMapping -from typing import Any +from collections import OrderedDict as _OrderedDict +from collections import deque +from collections.abc import Callable, Iterable, Iterator, Mapping, MutableMapping +from typing import Any, TypeVar, overload -from typing_extensions import override +from typing_extensions import Self, override + +__all__ = ( + "AttributeDict", + "AttributeDictMixin", + "BufferMap", + "ChainMap", + "ConfigurationView", + "DictAttribute", + "Evictable", + "LimitedSet", + "Messagebuffer", + "OrderedDict", + "force_mapping", + "lpmerge", +) + +_KT = TypeVar("_KT") +_VT = TypeVar("_VT") +_T = TypeVar("_T") + +class OrderedDict(_OrderedDict[_KT, _VT]): + def _LRUkey(self) -> Any: ... + +def force_mapping(m: Mapping[_KT, _VT] | None) -> Mapping[_KT, _VT]: ... +def lpmerge(L: list[Any], R: list[Any]) -> list[Any]: ... class AttributeDictMixin: def __getattr__(self, k: str) -> Any: ... @override def __setattr__(self, key: str, value: Any) -> None: ... -class ChainMap( # type: ignore[misc] # pyright: ignore[reportImplicitAbstractClass] - MutableMapping[str, Any] -): ... -class ConfigurationView( # type: ignore[misc] # pyright: ignore[reportImplicitAbstractClass] - ChainMap, AttributeDictMixin -): ... +class AttributeDict(dict[str, Any], AttributeDictMixin): + def __init__(self, *args: Any, **kwargs: Any) -> None: ... + +class BufferMap(dict[_KT, _VT]): + Buffer: type[Messagebuffer] + Empty: type[BaseException] + maxsize: int | None + bufmaxsize: int | None + total: int + def __init__( + self, + maxsize: int, + iterable: Iterable[tuple[_KT, _VT]] | None = None, + bufmaxsize: int = 1000, + ) -> None: ... + def evict(self) -> None: ... + def extend(self, key: _KT, it: Iterable[_VT]) -> None: ... + def put(self, key: _KT, item: _VT) -> None: ... + def take(self, key: _KT, *default: _VT) -> _VT: ... + +class ChainMap(MutableMapping[str, Any]): + maps: list[Mapping[str, Any]] | None + changes: dict[str, Any] | None + defaults: list[Mapping[str, Any]] | None + key_t: type[str] | None + def __init__(self, *maps: Mapping[str, Any], **kwargs: Any) -> None: ... + def __bool__(self) -> bool: ... + def __copy__(self) -> Self: ... + @override + def __getitem__(self, key: str) -> Any: ... + def __missing__(self, key: str) -> Any: ... + @override + def __setitem__(self, key: str, value: Any) -> None: ... + @override + def __delitem__(self, key: str) -> None: ... + @override + def __iter__(self) -> Iterator[str]: ... + @override + def __len__(self) -> int: ... + def add_defaults(self, d: Mapping[str, Any]) -> None: ... + def bind_to(self, callback: Callable[[MutableMapping[str, Any]], None]) -> None: ... + def copy(self) -> Self: ... + @classmethod + def fromkeys(cls, iterable: Iterable[str], *args: Any) -> Self: ... + @overload + def get(self, key: str) -> Any: ... + @overload + def get(self, key: str, default: _T) -> Any | _T: ... # pyright: ignore[reportIncompatibleMethodOverride] + def iteritems(self) -> Iterator[tuple[str, Any]]: ... + def iterkeys(self) -> Iterator[str]: ... + def itervalues(self) -> Iterator[Any]: ... + @overload + def pop(self, key: str) -> Any: ... + @overload + def pop(self, key: str, default: _T) -> Any | _T: ... # pyright: ignore[reportIncompatibleMethodOverride] + @override + def setdefault(self, key: str, default: Any = None) -> Any: ... + +class ConfigurationView(ChainMap, AttributeDictMixin): + def __init__( + self, + changes: dict[str, Any], + defaults: Mapping[str, Any] | None = None, + keys: Iterable[str] | None = None, + prefix: str | None = None, + ) -> None: ... + def first(self, *keys: str) -> Any: ... + @overload + def get(self, key: str) -> Any: ... + @overload + def get(self, key: str, default: _T) -> Any | _T: ... + def swap_with(self, other: ConfigurationView) -> None: ... + +class DictAttribute(dict[str, Any]): + obj: Any + def __init__(self, obj: Any) -> None: ... + @override + def get(self, key: str, default: Any = None) -> Any: ... + @override + def setdefault(self, key: str, default: Any = None) -> Any: ... + def iteritems(self) -> Iterator[tuple[str, Any]]: ... + def iterkeys(self) -> Iterator[str]: ... + def itervalues(self) -> Iterator[Any]: ... + +class Evictable: + Empty: type[BaseException] + def evict(self) -> None: ... + +class LimitedSet(Evictable): + max_heap_percent_overload: int + maxlen: int + expires: float + minlen: int + def __init__( + self, + maxlen: int = 0, + expires: float = 0, + data: Iterable[Any] | None = None, + minlen: int = 0, + ) -> None: ... + def add(self, item: Any, now: float | None = None) -> None: ... + def as_dict(self) -> dict[Any, float]: ... + def clear(self) -> None: ... + def discard(self, item: Any) -> None: ... + def pop(self, default: Any = None) -> Any: ... + def pop_value(self, item: Any) -> None: ... + def purge(self, now: float | None = None) -> None: ... + def update(self, other: Iterable[Any]) -> None: ... + def __contains__(self, value: object) -> bool: ... + def __iter__(self) -> Iterator[Any]: ... + def __len__(self) -> int: ... + def __bool__(self) -> bool: ... + +class Messagebuffer: + Empty: type[BaseException] + maxsize: int + def __init__( + self, + maxsize: int, + iterable: Iterable[Any] | None = None, + deque: type[deque[Any]] = ..., + ) -> None: ... + def extend(self, it: Iterable[Any]) -> None: ... + def put(self, item: Any) -> None: ... + def take(self, *default: Any) -> Any: ... + def __contains__(self, item: Any) -> bool: ... + def __getitem__(self, index: int) -> Any: ... + def __iter__(self) -> Iterator[Any]: ... + def __len__(self) -> int: ... + def __reversed__(self) -> Iterator[Any]: ... diff --git a/celery-stubs/utils/debug.pyi b/celery-stubs/utils/debug.pyi new file mode 100644 index 0000000..c547528 --- /dev/null +++ b/celery-stubs/utils/debug.pyi @@ -0,0 +1,31 @@ +from collections.abc import Callable, Iterator +from contextlib import contextmanager +from typing import Any, TextIO + +__all__ = ( + "blockdetection", + "cry", + "humanbytes", + "mem_rss", + "memdump", + "ps", + "sample", + "sample_mem", +) + +UNITS: tuple[tuple[float, str], ...] + +def blockdetection(timeout: float) -> Any: ... +def cry( + out: TextIO | Callable[[str], None] | None = None, + sepchr: str = "=", + seplen: int = 49, +) -> str: ... +def hfloat(f: float, p: int = 5) -> str: ... +def humanbytes(s: float) -> str: ... +def mem_rss() -> float: ... +def memdump(samples: int = 10, file: TextIO | None = None) -> None: ... +def ps() -> Any: ... +def sample(x: int, n: int, k: int = 0) -> list[Any]: ... +@contextmanager +def sample_mem() -> Iterator[Callable[[], str]]: ... diff --git a/celery-stubs/utils/deprecated.pyi b/celery-stubs/utils/deprecated.pyi new file mode 100644 index 0000000..fb1e3c8 --- /dev/null +++ b/celery-stubs/utils/deprecated.pyi @@ -0,0 +1,32 @@ +from collections.abc import Callable as _Callable +from typing import Any, TypeVar + +__all__ = ("Callable", "Property", "warn") + +_F = TypeVar("_F", bound=_Callable[..., Any]) + +DEPRECATION_FMT: str +PENDING_DEPRECATION_FMT: str + +class CDeprecationWarning(UserWarning): ... +class CPendingDeprecationWarning(PendingDeprecationWarning): ... + +def warn( + description: str | None = None, + deprecation: str | None = None, + removal: str | None = None, + alternative: str | None = None, + stacklevel: int = 2, +) -> None: ... +def Callable( + deprecation: str | None = None, + removal: str | None = None, + alternative: str | None = None, + description: str | None = None, +) -> _Callable[[_F], _F]: ... +def Property( + deprecation: str | None = None, + removal: str | None = None, + alternative: str | None = None, + description: str | None = None, +) -> _Callable[[_F], _F]: ... diff --git a/celery-stubs/utils/dispatch/__init__.pyi b/celery-stubs/utils/dispatch/__init__.pyi index 5f1ce75..5b7f646 100644 --- a/celery-stubs/utils/dispatch/__init__.pyi +++ b/celery-stubs/utils/dispatch/__init__.pyi @@ -1 +1,3 @@ from celery.utils.dispatch.signal import Signal as Signal + +__all__ = ("Signal",) diff --git a/celery-stubs/utils/dispatch/signal.pyi b/celery-stubs/utils/dispatch/signal.pyi index 40babe7..e9e3555 100644 --- a/celery-stubs/utils/dispatch/signal.pyi +++ b/celery-stubs/utils/dispatch/signal.pyi @@ -1,9 +1,19 @@ -from collections.abc import Callable +from collections.abc import Callable, Sequence from typing import Any, TypeVar, overload +__all__ = ("Signal",) + _F = TypeVar("_F", bound=Callable[..., Any]) class Signal: + receivers: list[tuple[Any, Any]] # None at class level, always set on instances + + def __init__( + self, + providing_args: Sequence[str] | None = None, + use_caching: bool = False, + name: str | None = None, + ) -> None: ... @overload def connect( self, @@ -22,6 +32,14 @@ class Signal: dispatch_uid: str = ..., retry: bool = ..., ) -> Callable[[_F], _F]: ... + def disconnect( + self, + receiver: Callable[..., Any] | None = None, + sender: Any | None = None, + weak: bool | None = None, + dispatch_uid: str | None = None, + ) -> bool: ... + def has_listeners(self, sender: Any | None = None) -> bool: ... def send( self, sender: Any | None, **named: Any ) -> list[tuple[Callable[..., Any], Any]]: ... diff --git a/celery-stubs/utils/graph.pyi b/celery-stubs/utils/graph.pyi index 331cef7..8406227 100644 --- a/celery-stubs/utils/graph.pyi +++ b/celery-stubs/utils/graph.pyi @@ -1,2 +1,74 @@ -class DependencyGraph: ... -class GraphFormatter: ... +from collections.abc import Iterable, Iterator +from typing import IO, Any + +from typing_extensions import override + +__all__ = ("DOT", "CycleError", "DependencyGraph", "GraphFormatter") + +class DOT: + ATTR: str + ATTRSEP: str + DIRS: dict[str, str] + EDGE: str + HEAD: str + NODE: str + TAIL: str + +class CycleError(Exception): + def __init__(self, node: Any) -> None: ... + +class GraphFormatter: + edge_scheme: dict[str, Any] + graph_scheme: dict[str, Any] + node_scheme: dict[str, Any] + scheme: dict[str, Any] + term_scheme: dict[str, Any] + + def __init__( + self, + root: Any | None = None, + type: str | None = None, + id: str | None = None, + indent: int = 0, + inw: str = " ", + **scheme: Any, + ) -> None: ... + def attr(self, name: str, value: Any) -> str: ... + def attrs(self, d: dict[str, Any], scheme: dict[str, Any] | None = None) -> str: ... + def draw_edge( + self, + a: Any, + b: Any, + scheme: dict[str, Any] | None = None, + attrs: dict[str, Any] | None = None, + ) -> str: ... + def draw_node( + self, + obj: Any, + scheme: dict[str, Any] | None = None, + attrs: dict[str, Any] | None = None, + ) -> str: ... + def edge(self, a: Any, b: Any, **attrs: Any) -> str: ... + def FMT(self, fmt: str, *args: Any, **kwargs: Any) -> str: ... + def head(self, **attrs: Any) -> str: ... + def label(self, obj: Any) -> str: ... + def node(self, obj: Any, **attrs: Any) -> str: ... + def tail(self) -> str: ... + def terminal_node(self, obj: Any, **attrs: Any) -> str: ... + +class DependencyGraph(dict[Any, Any]): + def __init__( + self, it: Iterable[Any] | None = None, formatter: GraphFormatter | None = None + ) -> None: ... + def add_arc(self, obj: Any) -> None: ... + def add_edge(self, A: Any, B: Any) -> None: ... + def connect(self, graph: DependencyGraph) -> None: ... + def edges(self) -> list[tuple[Any, Any]]: ... + def format(self, obj: Any) -> str: ... + def iteritems(self) -> Iterator[tuple[Any, Any]]: ... + def repr_node(self, obj: Any, level: int = 1, fmt: str = "{0}({1})") -> str: ... + def to_dot(self, fh: IO[str], formatter: GraphFormatter | None = None) -> None: ... + def topsort(self) -> list[Any]: ... + @override + def update(self, it: Iterable[Any]) -> None: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def valency_of(self, obj: Any) -> int: ... diff --git a/celery-stubs/utils/imports.pyi b/celery-stubs/utils/imports.pyi new file mode 100644 index 0000000..d34e992 --- /dev/null +++ b/celery-stubs/utils/imports.pyi @@ -0,0 +1,50 @@ +from collections.abc import Callable, Iterator +from contextlib import contextmanager +from importlib.metadata import EntryPoints +from types import ModuleType +from typing import Any + +__all__ = ( + "NotAPackage", + "cwd_in_path", + "find_module", + "gen_task_name", + "import_from_cwd", + "instantiate", + "module_file", + "qualname", + "reload_from_cwd", + "symbol_by_name", +) + +class NotAPackage(Exception): ... + +@contextmanager +def cwd_in_path() -> Iterator[None]: ... +def entry_points(**params: Any) -> EntryPoints: ... +def find_module( + module: str, path: list[str] | None = None, imp: Any | None = None +) -> ModuleType | None: ... +def gen_task_name(app: Any, name: str, module_name: str) -> str: ... +def import_from_cwd( + module: str, + imp: Callable[[str], ModuleType] | None = None, + package: str | None = None, +) -> ModuleType: ... +def instantiate(name: str, *args: Any, **kwargs: Any) -> Any: ... +def load_extension_class_names(namespace: str) -> list[str]: ... +def load_extension_classes(namespace: str) -> list[type[Any]]: ... +def module_file(module: ModuleType) -> str | None: ... +def qualname(obj: Any) -> str: ... +def reload_from_cwd( + module: ModuleType, reloader: Callable[[ModuleType], ModuleType] | None = None +) -> ModuleType: ... +def symbol_by_name( + name: str, + aliases: dict[str, str] | None = None, + imp: Callable[[str], ModuleType] | None = None, + package: str | None = None, + sep: str = ".", + default: Any = None, + **kwargs: Any, +) -> Any: ... diff --git a/celery-stubs/utils/iso8601.pyi b/celery-stubs/utils/iso8601.pyi new file mode 100644 index 0000000..1980f2f --- /dev/null +++ b/celery-stubs/utils/iso8601.pyi @@ -0,0 +1,9 @@ +import re +from datetime import datetime + +__all__ = ("parse_iso8601",) + +ISO8601_REGEX: re.Pattern[str] +TIMEZONE_REGEX: re.Pattern[str] + +def parse_iso8601(datestring: str) -> datetime: ... diff --git a/celery-stubs/utils/log.pyi b/celery-stubs/utils/log.pyi index e8e5b0c..45a48d0 100644 --- a/celery-stubs/utils/log.pyi +++ b/celery-stubs/utils/log.pyi @@ -1,16 +1,49 @@ +from collections.abc import Iterable from logging import Formatter, Logger, LogRecord, _SysExcInfoType from typing import ClassVar from celery.utils.term import colored from typing_extensions import override -class LoggingProxy: ... +__all__ = ( + "LOG_LEVELS", + "ColorFormatter", + "LoggingProxy", + "base_logger", + "get_logger", + "get_multiprocessing_logger", + "get_task_logger", + "in_sighandler", + "mlevel", + "reset_multiprocessing_logger", + "set_in_sighandler", +) + +LOG_LEVELS: dict[str, int] +base_logger: Logger +task_logger: Logger +worker_logger: Logger def get_logger(name: str) -> Logger: ... +def get_multiprocessing_logger() -> Logger | None: ... def get_task_logger(name: str) -> Logger: ... +def in_sighandler() -> bool: ... +def mlevel(level: int | str) -> int: ... +def reset_multiprocessing_logger() -> None: ... +def set_in_sighandler(value: bool) -> None: ... -task_logger: Logger -worker_logger: Logger +class LoggingProxy: + loglevel: int + mode: str + name: str | None + closed: bool + + def __init__(self, logger: Logger, loglevel: int | None = None) -> None: ... + def close(self) -> None: ... + def flush(self) -> None: ... + def isatty(self) -> bool: ... + def write(self, data: str) -> None: ... + def writelines(self, sequence: Iterable[str]) -> None: ... class ColorFormatter(Formatter): use_color: bool diff --git a/celery-stubs/utils/objects.pyi b/celery-stubs/utils/objects.pyi index f322a47..5eb3eff 100644 --- a/celery-stubs/utils/objects.pyi +++ b/celery-stubs/utils/objects.pyi @@ -28,6 +28,14 @@ class FallbackContext( fallback: Callable[_P, AbstractContextManager[_T_co]] | None fb_args: tuple[Any, ...] fb_kwargs: dict[str, Any] + + def __init__( + self, + provided: _T_co | None, + fallback: Callable[_P, AbstractContextManager[_T_co]] | None, + *fb_args: Any, + **fb_kwargs: Any, + ) -> None: ... @overload def __new__( cls, diff --git a/celery-stubs/utils/quorum_queues.pyi b/celery-stubs/utils/quorum_queues.pyi new file mode 100644 index 0000000..d1ea134 --- /dev/null +++ b/celery-stubs/utils/quorum_queues.pyi @@ -0,0 +1,3 @@ +from celery.app.base import Celery + +def detect_quorum_queues(app: Celery, driver_type: str) -> tuple[bool, str]: ... diff --git a/celery-stubs/utils/saferepr.pyi b/celery-stubs/utils/saferepr.pyi index 276425c..35b4dc6 100644 --- a/celery-stubs/utils/saferepr.pyi +++ b/celery-stubs/utils/saferepr.pyi @@ -2,7 +2,7 @@ from collections import deque from collections.abc import Callable, Iterator from typing import Any -__all__ = ["reprstream", "saferepr"] +__all__ = ("reprstream", "saferepr") def saferepr( o: Any, maxlen: int | None = ..., maxlevels: int = ..., seen: set[int] | None = ... diff --git a/celery-stubs/utils/serialization.pyi b/celery-stubs/utils/serialization.pyi new file mode 100644 index 0000000..1af7bcf --- /dev/null +++ b/celery-stubs/utils/serialization.pyi @@ -0,0 +1,70 @@ +from collections.abc import Callable +from typing import Any + +__all__ = ( + "UnpickleableExceptionWrapper", + "create_exception_cls", + "find_pickleable_exception", + "get_pickleable_etype", + "get_pickleable_exception", + "get_pickled_exception", + "strtobool", + "subclass_exception", +) + +STRTOBOOL_DEFAULT_TABLE: dict[str, bool] + +class UnpickleableExceptionWrapper(Exception): + exc_module: str | None + exc_cls_name: str | None + exc_args: tuple[Any, ...] | None + + def __init__( + self, + exc_module: str, + exc_cls_name: str, + exc_args: tuple[Any, ...], + text: str | None = None, + ) -> None: ... + @classmethod + def from_exception(cls, exc: Exception) -> UnpickleableExceptionWrapper: ... + def restore(self) -> Exception: ... + +def b64encode(s: bytes) -> bytes: ... +def b64decode(s: bytes) -> bytes: ... +def base64encode(s: bytes, altchars: bytes | None = None) -> bytes: ... +def base64decode( + s: bytes, altchars: bytes | None = None, validate: bool = False +) -> bytes: ... +def bytes_to_str(s: bytes | str) -> str: ... +def str_to_bytes(s: str | bytes) -> bytes: ... +def strtobool( + term: str | bool | int | None, table: dict[str, bool] | None = None +) -> bool: ... +def get_pickleable_exception(exc: Exception) -> Exception: ... +def get_pickleable_etype( + cls: type[Exception], loads: Any = ..., dumps: Any = ... +) -> type[Exception]: ... +def get_pickled_exception(exc: Exception) -> Exception: ... +def jsonify( + obj: Any, + builtin_types: tuple[type, ...] = ..., + key: Any = None, + keyfilter: Callable[[str], bool] | None = None, + unknown_type_filter: Callable[[Any], Any] | None = None, +) -> Any: ... +def raise_with_context(exc: Exception) -> None: ... +def find_pickleable_exception( + exc: Exception, + loads: Any = ..., + dumps: Any = ..., +) -> Exception | None: ... +def ensure_serializable(items: list[Any], encoder: Any) -> list[Any]: ... +def create_exception_cls( + name: str, module: str, parent: type | None = None +) -> type[Exception]: ... +def subclass_exception( + name: str, parent: type[Exception], module: str +) -> type[Exception]: ... +def itermro(cls: type, stop: type) -> Any: ... +def safe_repr(o: Any, errors: str = "replace") -> str: ... diff --git a/celery-stubs/utils/static.pyi b/celery-stubs/utils/static.pyi new file mode 100644 index 0000000..3f59c85 --- /dev/null +++ b/celery-stubs/utils/static.pyi @@ -0,0 +1,2 @@ +def get_file(filename: str) -> str: ... +def logo() -> str: ... diff --git a/celery-stubs/utils/sysinfo.pyi b/celery-stubs/utils/sysinfo.pyi new file mode 100644 index 0000000..9682044 --- /dev/null +++ b/celery-stubs/utils/sysinfo.pyi @@ -0,0 +1,17 @@ +import os +from typing import Any + +__all__ = ("df", "load_average") + +class df: + def __init__(self, path: str | bytes | os.PathLike[Any]) -> None: ... + @property + def available(self) -> float: ... + @property + def capacity(self) -> int: ... + @property + def stat(self) -> os.statvfs_result: ... + @property + def total_blocks(self) -> float: ... + +def load_average() -> tuple[float, float, float] | None: ... diff --git a/celery-stubs/utils/term.pyi b/celery-stubs/utils/term.pyi index 0dc48ee..e5b61b1 100644 --- a/celery-stubs/utils/term.pyi +++ b/celery-stubs/utils/term.pyi @@ -1 +1,31 @@ -class colored: ... +from typing import Any + +__all__ = ("colored",) + +class colored: + def __init__(self, *s: object, **kwargs: Any) -> None: ... + def __add__(self, other: object) -> str: ... + def embed(self) -> str: ... + def no_color(self) -> str: ... + def node(self, s: tuple[object, ...], op: str) -> colored: ... + def reset(self, *s: object) -> colored: ... + def black(self, *s: object) -> colored: ... + def blink(self, *s: object) -> colored: ... + def blue(self, *s: object) -> colored: ... + def bold(self, *s: object) -> colored: ... + def bright(self, *s: object) -> colored: ... + def cyan(self, *s: object) -> colored: ... + def green(self, *s: object) -> colored: ... + def iblue(self, *s: object) -> colored: ... + def icyan(self, *s: object) -> colored: ... + def igreen(self, *s: object) -> colored: ... + def imagenta(self, *s: object) -> colored: ... + def ired(self, *s: object) -> colored: ... + def iwhite(self, *s: object) -> colored: ... + def iyellow(self, *s: object) -> colored: ... + def magenta(self, *s: object) -> colored: ... + def red(self, *s: object) -> colored: ... + def reverse(self, *s: object) -> colored: ... + def underline(self, *s: object) -> colored: ... + def white(self, *s: object) -> colored: ... + def yellow(self, *s: object) -> colored: ... diff --git a/celery-stubs/utils/text.pyi b/celery-stubs/utils/text.pyi new file mode 100644 index 0000000..4faa215 --- /dev/null +++ b/celery-stubs/utils/text.pyi @@ -0,0 +1,45 @@ +from collections.abc import Callable, Iterable +from functools import partial +from re import Pattern +from typing import Any + +__all__ = ( + "abbr", + "abbrtask", + "dedent", + "dedent_initial", + "ensure_newlines", + "ensure_sep", + "fill_paragraphs", + "indent", + "join", + "pluralize", + "pretty", + "simple_format", + "str_to_list", + "truncate", +) + +def abbr(S: str, max: int, ellipsis: str = "...") -> str: ... +def abbrtask(S: str, max: int) -> str: ... +def dedent(s: str, sep: str = "\n") -> str: ... +def dedent_initial(s: str, n: int = 4) -> str: ... +def ensure_sep(sep: str, s: str, n: int = 2) -> str: ... + +ensure_newlines: partial[str] + +def fill_paragraphs(s: str, width: int, sep: str = "\n") -> str: ... +def indent(t: str, indent: int = 0, sep: str = "\n") -> str: ... +def join(l: Iterable[str], sep: str = "\n") -> str: ... +def pluralize(n: int, text: str, suffix: str = "s") -> str: ... +def pretty( + value: Any, width: int = 80, nl_width: int = 80, sep: str = "\n", **kw: Any +) -> str: ... +def simple_format( + s: str, + keys: dict[str, str | Callable[..., Any]], + pattern: Pattern[str] = ..., + expand: str = ..., +) -> str: ... +def str_to_list(s: str) -> list[str]: ... +def truncate(s: str, maxlen: int = 128, suffix: str = "...") -> str: ... diff --git a/celery-stubs/utils/threads.pyi b/celery-stubs/utils/threads.pyi index 791e170..84d0531 100644 --- a/celery-stubs/utils/threads.pyi +++ b/celery-stubs/utils/threads.pyi @@ -1,12 +1,22 @@ import threading -from collections.abc import Generator, Iterator +from collections.abc import Callable, Generator, Iterator from threading import Thread from typing import Any, Generic, TypeVar from typing_extensions import override +__all__ = ( + "Local", + "LocalManager", + "LocalStack", + "bgThread", + "default_socket_timeout", + "get_ident", +) + _T = TypeVar("_T") +def get_ident() -> int: ... def default_socket_timeout(timeout: float | None) -> Generator[None, None, None]: ... class bgThread(Thread): @@ -20,6 +30,9 @@ class bgThread(Thread): def stop(self) -> None: ... class Local: + __storage__: dict[int, dict[str, Any]] + __ident_func__: Callable[[], int] + def __init__(self) -> None: ... def __iter__(self) -> Iterator[tuple[str, Any]]: ... def __call__(self, proxy: Any) -> Any: ... @@ -31,6 +44,8 @@ class Local: def __delattr__(self, name: str) -> None: ... class _LocalStack(Generic[_T]): + @property + def __ident_func__(self) -> Callable[[], int]: ... def __init__(self) -> None: ... def __release_local__(self) -> None: ... def __call__(self) -> Any: ... @@ -53,11 +68,9 @@ class LocalManager: class _FastLocalStack(threading.local, Generic[_T]): stack: list[_T] - def push(self, obj: _T) -> None: ... - def pop(self) -> _T: ... def __init__(self) -> None: ... + def __len__(self) -> int: ... @property def top(self) -> _T: ... - def __len__(self) -> int: ... LocalStack: type[_FastLocalStack[Any] | _LocalStack[Any]] diff --git a/celery-stubs/utils/time.pyi b/celery-stubs/utils/time.pyi index e351ac5..0f8e6f9 100644 --- a/celery-stubs/utils/time.pyi +++ b/celery-stubs/utils/time.pyi @@ -1,8 +1,115 @@ -class ffwd: ... +from collections.abc import Callable +from datetime import datetime, timedelta, tzinfo +from time import struct_time +from types import ModuleType +from typing import Any +from typing_extensions import override + +__all__ = ( + "LocalTimezone", + "adjust_timestamp", + "delta_resolution", + "ffwd", + "get_exponential_backoff_interval", + "humanize_seconds", + "is_naive", + "localize", + "make_aware", + "maybe_iso8601", + "maybe_make_aware", + "maybe_timedelta", + "rate", + "remaining", + "timezone", + "to_utc", + "utcoffset", + "weekday", +) + +class LocalTimezone(tzinfo): + @override + def utcoffset(self, dt: datetime | None) -> timedelta: ... + @override + def dst(self, dt: datetime | None) -> timedelta: ... + @override + def tzname(self, dt: datetime | None) -> str: ... + @override + def fromutc(self, dt: datetime) -> datetime: ... + +class _Zone: + @property + def local(self) -> tzinfo: ... + @property + def utc(self) -> tzinfo: ... + def get_timezone(self, zone: str | tzinfo) -> tzinfo: ... + def to_local( + self, + dt: datetime, + local: tzinfo | None = None, + orig: tzinfo | None = None, + ) -> datetime: ... + def to_local_fallback(self, dt: datetime) -> datetime: ... + def to_system(self, dt: datetime) -> datetime: ... + def tz_or_local(self, tzinfo: tzinfo | None = None) -> tzinfo: ... + +timezone: _Zone + +class ffwd: + def __init__( + self, + year: int | None = None, + month: int | None = None, + weeks: int = 0, + weekday: int | None = None, + day: int | None = None, + hour: int | None = None, + minute: int | None = None, + second: int | None = None, + microsecond: int | None = None, + **kwargs: Any, + ) -> None: ... + def __radd__(self, other: Any) -> timedelta: ... + +def adjust_timestamp( + ts: float, + offset: int, + here: Callable[..., float] = ..., +) -> float: ... +def delta_resolution(dt: datetime, delta: timedelta) -> datetime: ... def get_exponential_backoff_interval( factor: int, retries: int, maximum: int, - full_jitter: bool | None, + full_jitter: bool = False, ) -> int: ... +def humanize_seconds( + secs: int, + prefix: str = "", + sep: str = "", + now: str = "now", + microseconds: bool = False, +) -> str: ... +def is_naive(dt: datetime) -> bool: ... +def localize(dt: datetime, tz: tzinfo) -> datetime: ... +def make_aware(dt: datetime, tz: tzinfo) -> datetime: ... +def maybe_iso8601(dt: datetime | str | None) -> datetime | None: ... +def maybe_make_aware( + dt: datetime, + tz: tzinfo | None = None, + naive_as_utc: bool = True, +) -> datetime: ... +def maybe_timedelta(delta: int) -> timedelta: ... +def rate(r: str) -> float: ... +def remaining( + start: datetime, + ends_in: timedelta, + now: datetime | None = None, + relative: bool = False, +) -> timedelta: ... +def to_utc(dt: datetime) -> datetime: ... +def utcoffset( + time: ModuleType = ..., + localtime: Callable[..., struct_time] = ..., +) -> float: ... +def weekday(name: str) -> int: ... diff --git a/celery-stubs/utils/timer2.pyi b/celery-stubs/utils/timer2.pyi new file mode 100644 index 0000000..2760d99 --- /dev/null +++ b/celery-stubs/utils/timer2.pyi @@ -0,0 +1,185 @@ +from collections.abc import Callable +from threading import Thread +from types import TracebackType +from typing import Any +from zoneinfo import ZoneInfo + +from typing_extensions import Self, override + +__all__ = ("Entry", "Schedule", "Timer", "to_timestamp") + +def to_timestamp( + d: Any, + default_timezone: ZoneInfo = ..., + time: Callable[[], float] = ..., +) -> float: ... + +class Entry: + fun: Callable[..., Any] + args: tuple[Any, ...] | None + kwargs: dict[str, Any] | None + tref: Any + canceled: bool + + def __init__( + self, + fun: Callable[..., Any], + args: tuple[Any, ...] | None = None, + kwargs: dict[str, Any] | None = None, + ) -> None: ... + def __call__(self) -> Any: ... + def __lt__(self, other: Entry) -> bool: ... + def __gt__(self, other: Entry) -> bool: ... + def __le__(self, other: Entry) -> bool: ... + def __ge__(self, other: Entry) -> bool: ... + def cancel(self) -> None: ... + @property + def cancelled(self) -> bool: ... + +_Entry = Entry + +class Schedule: + Entry: type[_Entry] + on_error: Callable[[Exception], None] | None + + def __init__( + self, + max_interval: float | None = None, + on_error: Callable[[Exception], None] | None = None, + ) -> None: ... + def __enter__(self) -> Self: ... + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: ... + def __iter__( + self, + min: Callable[..., Any] = ..., + nowfun: Callable[[], float] = ..., + pop: Callable[..., Any] = ..., + push: Callable[..., Any] = ..., + ) -> Self: ... + def __len__(self) -> int: ... + def apply_entry(self, entry: _Entry) -> Any: ... + def call_after( + self, + secs: float, + fun: Callable[..., Any], + args: tuple[Any, ...] = (), + kwargs: dict[str, Any] | None = None, + priority: int = 0, + ) -> _Entry: ... + def call_at( + self, + eta: float, + fun: Callable[..., Any], + args: tuple[Any, ...] = (), + kwargs: dict[str, Any] | None = None, + priority: int = 0, + ) -> _Entry: ... + def call_repeatedly( + self, + secs: float, + fun: Callable[..., Any], + args: tuple[Any, ...] = (), + kwargs: dict[str, Any] | None = None, + priority: int = 0, + ) -> _Entry: ... + def cancel(self, tref: Any) -> None: ... + def clear(self) -> None: ... + def enter_at( + self, + entry: _Entry, + eta: float | None = None, + priority: int = 0, + time: Callable[[], float] = ..., + ) -> _Entry: ... + def enter_after( + self, + secs: float, + entry: _Entry, + priority: int = 0, + time: Callable[[], float] = ..., + ) -> _Entry: ... + def handle_error( + self, exc_info: tuple[type[BaseException], BaseException, TracebackType | None] + ) -> None: ... + @property + def queue(self) -> list[_Entry]: ... + @property + def schedule(self) -> Any: ... + def stop(self) -> None: ... + +_Schedule = Schedule + +class Timer(Thread): + Entry: type[_Entry] + Schedule: type[_Schedule] + running: bool + on_tick: Callable[[float], None] | None + + def __init__( + self, + schedule: Any | None = None, + on_error: Callable[[Exception], None] | None = None, + on_tick: Callable[[float], None] | None = None, + on_start: Callable[[Timer], None] | None = None, + max_interval: float | None = None, + **kwargs: Any, + ) -> None: ... + def __bool__(self) -> bool: ... + def __len__(self) -> int: ... + def __next__(self) -> _Entry: ... + def call_after( + self, + secs: float, + fun: Callable[..., Any], + args: tuple[Any, ...] = (), + kwargs: dict[str, Any] | None = None, + priority: int = 0, + ) -> _Entry: ... + def call_at( + self, + eta: float, + fun: Callable[..., Any], + args: tuple[Any, ...] = (), + kwargs: dict[str, Any] | None = None, + priority: int = 0, + ) -> _Entry: ... + def call_repeatedly( + self, + secs: float, + fun: Callable[..., Any], + args: tuple[Any, ...] = (), + kwargs: dict[str, Any] | None = None, + priority: int = 0, + ) -> _Entry: ... + def enter( + self, + entry: _Entry, + eta: float, + priority: int | None = None, + ) -> _Entry: ... + def enter_after( + self, + secs: float, + entry: _Entry, + priority: int = 0, + ) -> _Entry: ... + def exit_after( + self, + secs: float, + priority: int = 10, + ) -> None: ... + def cancel(self, tref: Any) -> None: ... + def clear(self) -> None: ... + def empty(self) -> bool: ... + def next(self) -> _Entry | None: ... + @override + def run(self) -> None: ... + def stop(self) -> None: ... + def ensure_started(self) -> None: ... + @property + def queue(self) -> list[Any]: ... diff --git a/celery-stubs/worker/__init__.pyi b/celery-stubs/worker/__init__.pyi index 95519f6..bf6fcc2 100644 --- a/celery-stubs/worker/__init__.pyi +++ b/celery-stubs/worker/__init__.pyi @@ -1 +1,3 @@ from celery.worker.worker import WorkController as WorkController + +__all__ = ("WorkController",) diff --git a/celery-stubs/worker/autoscale.pyi b/celery-stubs/worker/autoscale.pyi index 69c1823..abdb879 100644 --- a/celery-stubs/worker/autoscale.pyi +++ b/celery-stubs/worker/autoscale.pyi @@ -1,5 +1,7 @@ from typing import Any +__all__ = ("Autoscaler", "WorkerComponent") + from celery.bootsteps import StartStopStep from celery.concurrency.base import BasePool from celery.utils.threads import bgThread @@ -9,12 +11,12 @@ class WorkerComponent(StartStopStep): enabled: Any def __init__(self, w: Any, **kwargs: Any) -> None: ... @override - def create( # pyright: ignore[reportIncompatibleMethodOverride] + def create( # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] self, w: Any ) -> Any: ... def register_with_event_loop(self, w: Any, hub: Any) -> None: ... @override - def info( # pyright: ignore[reportIncompatibleMethodOverride] + def info( # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] self, w: Any ) -> Any: ... diff --git a/celery-stubs/worker/components.pyi b/celery-stubs/worker/components.pyi index 35aff10..87646e4 100644 --- a/celery-stubs/worker/components.pyi +++ b/celery-stubs/worker/components.pyi @@ -1,8 +1,55 @@ +from typing import Any + from celery import bootsteps +from typing_extensions import override + +__all__ = ("Beat", "Consumer", "Hub", "Pool", "StateDB", "Timer") + +class Timer(bootsteps.Step): + def __init__(self, parent: Any, **kwargs: Any) -> None: ... + @override + def create(self, w: Any) -> Any: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + def on_timer_error(self, exc: Exception) -> None: ... + def on_timer_tick(self, delay: float) -> None: ... + +class Hub(bootsteps.StartStopStep): + def __init__(self, w: Any, **kwargs: Any) -> None: ... + @override + def create(self, w: Any) -> Any: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + @override + def include_if(self, w: Any) -> bool: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + @override + def start(self, w: Any) -> None: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + @override + def stop(self, w: Any) -> None: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + @override + def terminate(self, w: Any) -> None: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + +class Pool(bootsteps.StartStopStep): + def __init__( + self, w: Any, autoscale: tuple[int, int] | None = None, **kwargs: Any + ) -> None: ... + @override + def close(self, w: Any) -> None: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + @override + def create(self, w: Any) -> Any: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + @override + def info(self, w: Any) -> dict[str, Any]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def register_with_event_loop(self, w: Any, hub: Any) -> None: ... + @override + def terminate(self, w: Any) -> None: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + +class Beat(bootsteps.StartStopStep): + def __init__(self, w: Any, beat: bool = False, **kwargs: Any) -> None: ... + @override + def create(self, w: Any) -> Any: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + +class StateDB(bootsteps.Step): + def __init__(self, w: Any, **kwargs: Any) -> None: ... + @override + def create(self, w: Any) -> Any: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] -class Timer(bootsteps.Step): ... -class Hub(bootsteps.StartStopStep): ... -class Pool(bootsteps.StartStopStep): ... -class Beat(bootsteps.StartStopStep): ... -class StateDB(bootsteps.Step): ... -class Consumer(bootsteps.StartStopStep): ... +class Consumer(bootsteps.StartStopStep): + def __init__(self, parent: Any, **kwargs: Any) -> None: ... + @override + def create(self, w: Any) -> Any: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] diff --git a/celery-stubs/worker/consumer/__init__.pyi b/celery-stubs/worker/consumer/__init__.pyi new file mode 100644 index 0000000..b46514e --- /dev/null +++ b/celery-stubs/worker/consumer/__init__.pyi @@ -0,0 +1,21 @@ +from celery.worker.consumer.agent import Agent as Agent +from celery.worker.consumer.connection import Connection as Connection +from celery.worker.consumer.consumer import Consumer as Consumer +from celery.worker.consumer.control import Control as Control +from celery.worker.consumer.events import Events as Events +from celery.worker.consumer.gossip import Gossip as Gossip +from celery.worker.consumer.heart import Heart as Heart +from celery.worker.consumer.mingle import Mingle as Mingle +from celery.worker.consumer.tasks import Tasks as Tasks + +__all__ = ( + "Agent", + "Connection", + "Consumer", + "Control", + "Events", + "Gossip", + "Heart", + "Mingle", + "Tasks", +) diff --git a/celery-stubs/worker/consumer/agent.pyi b/celery-stubs/worker/consumer/agent.pyi new file mode 100644 index 0000000..bf34933 --- /dev/null +++ b/celery-stubs/worker/consumer/agent.pyi @@ -0,0 +1,13 @@ +from typing import Any, ClassVar + +from celery.bootsteps import Step +from typing_extensions import override + +__all__ = ("Agent",) + +class Agent(Step): + name: ClassVar[str] # pyright: ignore[reportIncompatibleVariableOverride] + + def __init__(self, c: Any, **kwargs: Any) -> None: ... + @override + def create(self, c: Any) -> Any: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] diff --git a/celery-stubs/worker/consumer/connection.pyi b/celery-stubs/worker/consumer/connection.pyi new file mode 100644 index 0000000..cdf2f77 --- /dev/null +++ b/celery-stubs/worker/consumer/connection.pyi @@ -0,0 +1,15 @@ +from typing import Any, ClassVar + +from celery.bootsteps import Step +from typing_extensions import override + +__all__ = ("Connection",) + +class Connection(Step): + name: ClassVar[str] # pyright: ignore[reportIncompatibleVariableOverride] + + def __init__(self, c: Any, **kwargs: Any) -> None: ... + @override + def info(self, c: Any) -> dict[str, Any]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def start(self, c: Any) -> None: ... + def shutdown(self, c: Any) -> None: ... diff --git a/celery-stubs/worker/consumer/consumer.pyi b/celery-stubs/worker/consumer/consumer.pyi new file mode 100644 index 0000000..a63f523 --- /dev/null +++ b/celery-stubs/worker/consumer/consumer.pyi @@ -0,0 +1,101 @@ +from collections.abc import Callable +from typing import Any, ClassVar + +import kombu +from celery.app.base import Celery +from celery.bootsteps import Blueprint, StartStopStep +from typing_extensions import override +from vine.promises import promise + +__all__ = ("Consumer", "Evloop", "dump_body") + +class Evloop(StartStopStep): + name: ClassVar[str] # pyright: ignore[reportIncompatibleVariableOverride] + label: ClassVar[str] # pyright: ignore[reportIncompatibleVariableOverride] + + def patch_all(self, c: Any) -> None: ... + @override + def start(self, c: Any) -> None: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + +def dump_body(m: Any, body: Any) -> str: ... + +class Consumer: + app: Celery + hostname: str + pool: Any + connection: kombu.Connection | None + blueprint: Blueprint + Blueprint: type[Blueprint] + Strategies: type[dict[Any, Any]] + restart_count: int + broker_connection_retry_attempt: int + first_connection_attempt: bool + init_callback: Callable[..., Any] | None + + def __init__( + self, + on_task_request: Callable[..., Any], + init_callback: Callable[..., Any] = ..., + hostname: str | None = None, + pool: Any = None, + app: Celery | None = None, + timer: Any = None, + controller: Any = None, + hub: Any = None, + amqheartbeat: float | None = None, + worker_options: dict[str, Any] | None = None, + disable_rate_limits: bool = False, + initial_prefetch_count: int = 2, + prefetch_multiplier: int = 1, + **kwargs: Any, + ) -> None: ... + def bucket_for_task(self, type: Any) -> Any: ... + def reset_rate_limits(self) -> None: ... + def add_task_queue( + self, + queue: str | kombu.Queue, + exchange: str | kombu.Exchange | None = None, + exchange_type: str | None = None, + routing_key: str | None = None, + **options: Any, + ) -> kombu.Queue: ... + def cancel_task_queue(self, queue: str | kombu.Queue) -> None: ... + def apply_eta_task(self, task: Any) -> None: ... + def call_soon( + self, + p: Callable[..., Any], + *args: Any, + **kwargs: Any, + ) -> None: ... + def cancel_active_requests(self) -> None: ... + def connect(self) -> kombu.Connection: ... + def connection_for_read( + self, heartbeat: float | None = None + ) -> kombu.Connection: ... + def connection_for_write( + self, url: str | None = None, heartbeat: float | None = None + ) -> kombu.Connection: ... + def create_task_handler( + self, promise: type[promise] = ... + ) -> Callable[..., Any]: ... + def ensure_connected(self, conn: kombu.Connection) -> kombu.Connection: ... + def loop_args(self) -> tuple[Any, ...]: ... + @property + def max_prefetch_count(self) -> int: ... + def on_close(self) -> None: ... + def on_connection_error_after_connected(self, exc: Exception) -> None: ... + def on_connection_error_before_connected(self, exc: Exception) -> None: ... + def on_decode_error(self, message: Any, exc: Exception) -> None: ... + def on_invalid_task(self, body: Any, message: Any, exc: Exception) -> None: ... + def on_ready(self) -> None: ... + def on_send_event_buffered(self) -> Callable[..., Any]: ... + def on_unknown_message(self, body: Any, message: Any) -> None: ... + def on_unknown_task(self, body: Any, message: Any, exc: Exception) -> None: ... + def perform_pending_operations(self) -> None: ... + def register_with_event_loop(self, hub: Any) -> None: ... + def stop(self) -> None: ... + def start(self) -> None: ... + def shutdown(self) -> None: ... + @property + def timer(self) -> Any: ... + def update_strategies(self) -> None: ... diff --git a/celery-stubs/worker/consumer/control.pyi b/celery-stubs/worker/consumer/control.pyi new file mode 100644 index 0000000..8d86d38 --- /dev/null +++ b/celery-stubs/worker/consumer/control.pyi @@ -0,0 +1,19 @@ +from typing import Any, ClassVar + +from celery.bootsteps import Step +from typing_extensions import override + +__all__ = ("Control",) + +class Control(Step): + name: ClassVar[str] # pyright: ignore[reportIncompatibleVariableOverride] + + def __init__(self, c: Any, **kwargs: Any) -> None: ... + @override + def create(self, parent: Any) -> Any: ... + def start(self, parent: Any) -> None: ... + def stop(self, parent: Any) -> None: ... + @override + def include_if(self, c: Any) -> bool: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + @override + def info(self, obj: Any) -> dict[str, Any]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] diff --git a/celery-stubs/worker/consumer/delayed_delivery.pyi b/celery-stubs/worker/consumer/delayed_delivery.pyi new file mode 100644 index 0000000..7d61fac --- /dev/null +++ b/celery-stubs/worker/consumer/delayed_delivery.pyi @@ -0,0 +1,13 @@ +from typing import Any, ClassVar + +from celery.bootsteps import Step +from typing_extensions import override + +__all__ = ("DelayedDelivery",) + +class DelayedDelivery(Step): + name: ClassVar[str] # pyright: ignore[reportIncompatibleVariableOverride] + + @override + def include_if(self, c: Any) -> bool: ... # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override] + def start(self, c: Any) -> None: ... diff --git a/celery-stubs/worker/consumer/events.pyi b/celery-stubs/worker/consumer/events.pyi new file mode 100644 index 0000000..dc6efc9 --- /dev/null +++ b/celery-stubs/worker/consumer/events.pyi @@ -0,0 +1,27 @@ +from typing import Any, ClassVar + +from celery.bootsteps import Step +from typing_extensions import override + +__all__ = ("Events",) + +class Events(Step): + name: ClassVar[str] # pyright: ignore[reportIncompatibleVariableOverride] + + def __init__( + self, + c: Any, + task_events: bool = True, + without_heartbeat: bool = False, + without_gossip: bool = False, + **kwargs: Any, + ) -> None: ... + @override + def create(self, parent: Any) -> Any: ... + def start(self, c: Any) -> None: ... + def stop(self, c: Any) -> None: ... + def shutdown(self, c: Any) -> None: ... + @override + def include_if(self, parent: Any) -> bool: ... + @override + def info(self, obj: Any) -> dict[str, Any]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] diff --git a/celery-stubs/worker/consumer/gossip.pyi b/celery-stubs/worker/consumer/gossip.pyi new file mode 100644 index 0000000..dab3fcb --- /dev/null +++ b/celery-stubs/worker/consumer/gossip.pyi @@ -0,0 +1,47 @@ +from collections.abc import Callable +from typing import Any, ClassVar + +from celery.bootsteps import ConsumerStep +from typing_extensions import override + +__all__ = ("Gossip",) + +class Gossip(ConsumerStep): + name: ClassVar[str] # pyright: ignore[reportIncompatibleVariableOverride] + compatible_transports: set[str] + + def __init__( + self, + c: Any, + without_gossip: bool = False, + interval: float = 5.0, + heartbeat_interval: float = 2.0, + **kwargs: Any, + ) -> None: ... + @override + def create(self, parent: Any) -> Any: ... + @override + def start(self, c: Any) -> None: ... # ty: ignore[invalid-method-override] + @override + def stop(self, c: Any) -> None: ... # ty: ignore[invalid-method-override] + @override + def shutdown(self, c: Any) -> None: ... + @override + def include_if(self, parent: Any) -> bool: ... + @override + def info(self, obj: Any) -> dict[str, Any]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def call_task(self, task: Any) -> Any: ... + def compatible_transport(self, app: Any) -> bool: ... + def election( + self, id: str, topic: str, action: Callable[..., Any] | None = None + ) -> None: ... + @override + def get_consumers(self, channel: Any) -> list[Any]: ... + def on_elect(self, event: Any) -> None: ... + def on_elect_ack(self, event: Any) -> None: ... + def on_message(self, prepare: Any, message: Any) -> None: ... + def on_node_join(self, worker: Any) -> None: ... + def on_node_leave(self, worker: Any) -> None: ... + def on_node_lost(self, worker: Any) -> None: ... + def periodic(self) -> None: ... + def register_timer(self) -> None: ... diff --git a/celery-stubs/worker/consumer/heart.pyi b/celery-stubs/worker/consumer/heart.pyi new file mode 100644 index 0000000..e6be58c --- /dev/null +++ b/celery-stubs/worker/consumer/heart.pyi @@ -0,0 +1,26 @@ +from typing import Any, ClassVar + +from celery.bootsteps import Step +from typing_extensions import override + +__all__ = ("Heart",) + +class Heart(Step): + name: ClassVar[str] # pyright: ignore[reportIncompatibleVariableOverride] + + def __init__( + self, + c: Any, + without_heartbeat: bool = False, + heartbeat_interval: float | None = None, + **kwargs: Any, + ) -> None: ... + @override + def create(self, parent: Any) -> Any: ... + def start(self, c: Any) -> None: ... + def stop(self, c: Any) -> None: ... + def shutdown(self, c: Any) -> None: ... + @override + def include_if(self, parent: Any) -> bool: ... + @override + def info(self, obj: Any) -> dict[str, Any]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] diff --git a/celery-stubs/worker/consumer/mingle.pyi b/celery-stubs/worker/consumer/mingle.pyi new file mode 100644 index 0000000..0e04923 --- /dev/null +++ b/celery-stubs/worker/consumer/mingle.pyi @@ -0,0 +1,29 @@ +from typing import Any, ClassVar + +from celery.bootsteps import Step +from typing_extensions import override + +__all__ = ("Mingle",) + +class Mingle(Step): + name: ClassVar[str] # pyright: ignore[reportIncompatibleVariableOverride] + compatible_transports: set[str] + + def __init__(self, c: Any, without_mingle: bool = False, **kwargs: Any) -> None: ... + @override + def create(self, parent: Any) -> Any: ... + def start(self, c: Any) -> None: ... + def stop(self, parent: Any) -> None: ... + @override + def include_if(self, parent: Any) -> bool: ... + @override + def info(self, obj: Any) -> dict[str, Any]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def compatible_transport(self, app: Any) -> bool: ... + def on_clock_event(self, c: Any, clock: Any) -> None: ... + def on_node_reply(self, c: Any, nodename: str, reply: Any) -> None: ... + def on_revoked_received(self, c: Any, revoked: Any) -> None: ... + def send_hello(self, c: Any) -> None: ... + def sync(self, c: Any) -> None: ... + def sync_with_node( + self, c: Any, clock: Any = None, revoked: Any = None, **kwargs: Any + ) -> None: ... diff --git a/celery-stubs/worker/consumer/tasks.pyi b/celery-stubs/worker/consumer/tasks.pyi new file mode 100644 index 0000000..70a6de1 --- /dev/null +++ b/celery-stubs/worker/consumer/tasks.pyi @@ -0,0 +1,21 @@ +from typing import Any, ClassVar + +from celery.bootsteps import Step +from typing_extensions import override + +__all__ = ("Tasks",) + +class Tasks(Step): + name: ClassVar[str] # pyright: ignore[reportIncompatibleVariableOverride] + + def __init__(self, c: Any, **kwargs: Any) -> None: ... + @override + def create(self, parent: Any) -> Any: ... + def start(self, c: Any) -> None: ... + def stop(self, c: Any) -> None: ... + def shutdown(self, c: Any) -> None: ... + @override + def include_if(self, parent: Any) -> bool: ... + @override + def info(self, c: Any) -> dict[str, Any]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def qos_global(self, c: Any) -> bool: ... diff --git a/celery-stubs/worker/control.pyi b/celery-stubs/worker/control.pyi new file mode 100644 index 0000000..89f4330 --- /dev/null +++ b/celery-stubs/worker/control.pyi @@ -0,0 +1,33 @@ +from abc import ABCMeta +from collections.abc import Callable +from typing import Any, NamedTuple + +__all__ = ("Panel",) + +class controller_info_t(NamedTuple): + alias: str | None + type: str + visible: bool + default_timeout: float + help: str + signature: str | None + args: list[tuple[str, type]] | None # type: ignore[valid-type] + variadic: str | None + +class Panel(metaclass=ABCMeta): + data: dict[str, Callable[..., Any]] + meta: dict[str, controller_info_t] + + @classmethod + def register( + cls, + method: Callable[..., Any], + name: str | None = None, + ) -> Callable[..., Any]: ... + +def control_command( + **kwargs: Any, +) -> Callable[[Callable[..., Any]], Callable[..., Any]]: ... +def inspect_command( + **kwargs: Any, +) -> Callable[[Callable[..., Any]], Callable[..., Any]]: ... diff --git a/celery-stubs/worker/heartbeat.pyi b/celery-stubs/worker/heartbeat.pyi new file mode 100644 index 0000000..977b6f9 --- /dev/null +++ b/celery-stubs/worker/heartbeat.pyi @@ -0,0 +1,13 @@ +from typing import Any + +__all__ = ("Heart",) + +class Heart: + def __init__( + self, + timer: Any, + eventer: Any, + interval: float | None = None, + ) -> None: ... + def start(self) -> None: ... + def stop(self) -> None: ... diff --git a/celery-stubs/worker/loops.pyi b/celery-stubs/worker/loops.pyi new file mode 100644 index 0000000..bf86697 --- /dev/null +++ b/celery-stubs/worker/loops.pyi @@ -0,0 +1,27 @@ +from typing import Any + +__all__ = ("asynloop", "synloop") + +def asynloop( + obj: Any, + connection: Any, + consumer: Any, + blueprint: Any, + hub: Any, + qos: Any, + heartbeat: float, + clock: Any, + hbrate: float = 2.0, +) -> None: ... +def synloop( + obj: Any, + connection: Any, + consumer: Any, + blueprint: Any, + hub: Any, + qos: Any, + heartbeat: float, + clock: Any, + hbrate: float = 2.0, + **kwargs: Any, +) -> None: ... diff --git a/celery-stubs/worker/pidbox.pyi b/celery-stubs/worker/pidbox.pyi new file mode 100644 index 0000000..a1a2e34 --- /dev/null +++ b/celery-stubs/worker/pidbox.pyi @@ -0,0 +1,20 @@ +from typing import Any + +__all__ = ("Pidbox", "gPidbox") + +class Pidbox: + consumer: Any + connection: Any + node: Any + + def __init__(self, c: Any) -> None: ... + def on_stop(self) -> None: ... + def start(self, c: Any) -> None: ... + def stop(self, c: Any) -> None: ... + def reset(self) -> None: ... + def shutdown(self, c: Any) -> None: ... + def on_message(self, body: Any, message: Any) -> None: ... + +class gPidbox(Pidbox): + def __init__(self, c: Any) -> None: ... + def loop(self, c: Any) -> None: ... diff --git a/celery-stubs/worker/request.pyi b/celery-stubs/worker/request.pyi index 8c1b826..34188b2 100644 --- a/celery-stubs/worker/request.pyi +++ b/celery-stubs/worker/request.pyi @@ -2,6 +2,8 @@ import datetime from collections.abc import Callable, Sequence from typing import Any, Literal, TypedDict +__all__ = ("Request",) + from celery.app.base import Celery from celery.app.task import Task from celery.canvas import chord as chord_type @@ -119,7 +121,20 @@ class Request: @property def correlation_id(self) -> Any: ... @property - def retries(self) -> int: ... + def name(self) -> str: ... + @property + def ignore_result(self) -> bool: ... + @property + def stamped_headers(self) -> list[str] | None: ... + @property + def stamps(self) -> dict[str, Any]: ... + @property + def groups(self) -> list[str] | None: ... + @property + def replaced_task_nesting(self) -> int: ... + def cancel( + self, pool: BasePool, signal: int | None = ..., emit_retry: bool = True + ) -> None: ... def execute_using_pool(self, pool: BasePool, **kwargs: Any) -> AsyncResult[Any]: ... def execute(self, loglevel: int | None = ..., logfile: str | None = ...) -> Any: ... def maybe_expire(self) -> None | Literal[True]: ... @@ -139,7 +154,11 @@ class Request: def reject(self, requeue: bool = ...) -> None: ... def info(self, safe: bool = ...) -> _InfoDict: ... def humaninfo(self) -> str: ... + @property def chord(self) -> chord_type | None: ... + @property def errbacks(self) -> Any | None: ... + @property def group(self) -> Any | None: ... + @property def group_index(self) -> Any | None: ... diff --git a/celery-stubs/worker/state.pyi b/celery-stubs/worker/state.pyi new file mode 100644 index 0000000..46798f8 --- /dev/null +++ b/celery-stubs/worker/state.pyi @@ -0,0 +1,75 @@ +from collections.abc import Callable, MutableSet +from types import ModuleType +from typing import Any + +from celery.utils.collections import LimitedSet + +__all__ = ( + "SOFTWARE_INFO", + "Persistent", + "active_requests", + "maybe_shutdown", + "reserved_requests", + "revoked", + "task_accepted", + "task_ready", + "task_reserved", + "total_count", +) + +class Persistent: + db: Any + merge: Callable[..., Any] + open: Callable[..., Any] + protocol: int + storage: ModuleType + # These are zlib.compress and zlib.decompress functions assigned as class attributes + compress: Callable[..., bytes] + decompress: Callable[..., bytes] + + def __init__(self, state: Any, filename: str, clock: Any | None = None) -> None: ... + def save(self) -> None: ... + def close(self) -> None: ... + def sync(self) -> None: ... + +C_BENCH: None +C_BENCH_EVERY: int +REVOKES_MAX: int +REVOKE_EXPIRES: float +SUCCESSFUL_EXPIRES: float +SUCCESSFUL_MAX: int +SOFTWARE_INFO: dict[str, str] + +revoked: LimitedSet +revoked_stamps: dict[str, set[str]] +active_requests: MutableSet[Any] +reserved_requests: MutableSet[Any] +successful_requests: LimitedSet +requests: dict[str, Any] +total_count: dict[str, int] +all_total_count: list[int] + +should_stop: None +should_terminate: None + +def maybe_shutdown() -> None: ... +def reset_state() -> None: ... +def task_accepted( + request: Any, + _all_total_count: list[int] | None = None, + add_request: Callable[..., Any] = ..., + add_active_request: Callable[..., Any] = ..., + add_to_total_count: Callable[..., Any] = ..., +) -> None: ... +def task_reserved( + request: Any, + add_request: Callable[..., Any] = ..., + add_reserved_request: Callable[..., Any] = ..., +) -> None: ... +def task_ready( + request: Any, + successful: bool = False, + remove_request: Callable[..., Any] = ..., + discard_active_request: Callable[..., Any] = ..., + discard_reserved_request: Callable[..., Any] = ..., +) -> None: ... diff --git a/celery-stubs/worker/strategy.pyi b/celery-stubs/worker/strategy.pyi index e1de0b3..29f1908 100644 --- a/celery-stubs/worker/strategy.pyi +++ b/celery-stubs/worker/strategy.pyi @@ -1,3 +1,19 @@ import logging +from collections.abc import Callable +from typing import Any + +__all__ = ("default",) logger: logging.Logger + +def default( + task: Any, + app: Any, + consumer: Any, + info: Callable[..., None] = ..., + error: Callable[..., None] = ..., + task_reserved: Callable[..., Any] = ..., + to_system_tz: Callable[..., Any] = ..., + bytes: type[bytes] = ..., + proto1_to_proto2: Callable[..., Any] = ..., +) -> Callable[..., Any]: ... diff --git a/celery-stubs/worker/worker.pyi b/celery-stubs/worker/worker.pyi index 2c8e497..071a0f5 100644 --- a/celery-stubs/worker/worker.pyi +++ b/celery-stubs/worker/worker.pyi @@ -1,6 +1,96 @@ +from collections.abc import Callable, Sequence +from typing import Any + +from celery import bootsteps from celery.worker.components import Hub, Pool, Timer +__all__ = ("WorkController",) + class WorkController: + class Blueprint(bootsteps.Blueprint): ... + app: Any + blueprint: bootsteps.Blueprint | None + exitcode: int | None hub: Hub | None + pidlock: Any pool: Pool | None + semaphore: Any timer: Timer | None + + def rusage(self) -> Any: ... + @property + def state(self) -> str: ... + def __init__( + self, app: Any = None, hostname: str | None = None, **kwargs: Any + ) -> None: ... + def info(self) -> dict[str, Any]: ... + def on_after_init(self, **kwargs: Any) -> None: ... + def on_before_init(self, **kwargs: Any) -> None: ... + def on_close(self) -> None: ... + def on_consumer_ready(self, consumer: Any) -> None: ... + def on_init_blueprint(self) -> None: ... + def on_start(self) -> None: ... + def on_stopped(self) -> None: ... + def prepare_args(self, **kwargs: Any) -> dict[str, Any]: ... + def register_with_event_loop(self, hub: Any) -> None: ... + def reload( + self, + modules: Sequence[str] | None = None, + reload: bool = False, + reloader: Any | None = None, + ) -> None: ... + def setup_defaults( + self, + concurrency: int | None = None, + loglevel: str | int = "WARN", + logfile: str | None = None, + task_events: bool | None = None, + pool: Any | None = None, + consumer_cls: Any | None = None, + timer_cls: Any | None = None, + timer_precision: float | None = None, + autoscaler_cls: Any | None = None, + pool_putlocks: bool | None = None, + pool_restarts: bool | None = None, + optimization: str | None = None, + O: str | None = None, + statedb: str | None = None, + time_limit: float | None = None, + soft_time_limit: float | None = None, + scheduler: str | None = None, + pool_cls: Any | None = None, + state_db: str | None = None, + task_time_limit: float | None = None, + task_soft_time_limit: float | None = None, + scheduler_cls: Any | None = None, + schedule_filename: str | None = None, + max_tasks_per_child: int | None = None, + prefetch_multiplier: int | None = None, + disable_rate_limits: bool | None = None, + worker_lost_wait: float | None = None, + max_memory_per_child: int | None = None, + **_kw: Any, + ) -> dict[str, Any]: ... + def setup_includes(self, includes: Sequence[str]) -> None: ... + def setup_instance( + self, + queues: Sequence[str] | None = None, + ready_callback: Callable[[], None] | None = None, + pidfile: str | None = None, + include: Sequence[str] | None = None, + use_eventloop: bool | None = None, + exclude_queues: Sequence[str] | None = None, + **kwargs: Any, + ) -> None: ... + def setup_queues( + self, include: Sequence[str], exclude: Sequence[str] | None = None + ) -> None: ... + def should_use_eventloop(self) -> bool: ... + def signal_consumer_close(self) -> None: ... + def start(self) -> None: ... + def stats(self) -> dict[str, Any]: ... + def stop( + self, in_sighandler: bool = False, exitcode: int | None = None + ) -> None: ... + def terminate(self, in_sighandler: bool = False) -> None: ... + def wait_for_soft_shutdown(self) -> bool: ...