diff --git a/pyrightconfig.stricter.json b/pyrightconfig.stricter.json index cd4331e8bf0b..35f600bb3aa2 100644 --- a/pyrightconfig.stricter.json +++ b/pyrightconfig.stricter.json @@ -44,6 +44,7 @@ "stubs/grpcio-reflection/grpc_reflection/v1alpha", "stubs/grpcio-status/grpc_status", "stubs/grpcio/grpc/__init__.pyi", + "stubs/gunicorn", "stubs/hdbcli/hdbcli/dbapi.pyi", "stubs/html5lib", "stubs/httplib2", diff --git a/stubs/gunicorn/@tests/stubtest_allowlist.txt b/stubs/gunicorn/@tests/stubtest_allowlist.txt new file mode 100644 index 000000000000..47e466ac9ec9 --- /dev/null +++ b/stubs/gunicorn/@tests/stubtest_allowlist.txt @@ -0,0 +1,5 @@ +# Is not present in runtime. For more details, see the file itself. +gunicorn._types + +# .pyi file doesn't exist +gunicorn.__main__ diff --git a/stubs/gunicorn/METADATA.toml b/stubs/gunicorn/METADATA.toml new file mode 100644 index 000000000000..f79a6d707ad7 --- /dev/null +++ b/stubs/gunicorn/METADATA.toml @@ -0,0 +1,8 @@ +version = "23.0.*" +upstream_repository = "https://github.com/benoitc/gunicorn" +requires = ["types-gevent"] + +[tool.stubtest] +supported_platforms = ["linux", "darwin"] +ci_platforms = ["linux", "darwin"] +stubtest_requirements = ["gevent>=1.4.0", "eventlet>=0.24.1,!=0.36.0", "tornado>=0.2", "setproctitle", "PasteDeploy", "inotify"] diff --git a/stubs/gunicorn/gunicorn/__init__.pyi b/stubs/gunicorn/gunicorn/__init__.pyi new file mode 100644 index 000000000000..dff515c23298 --- /dev/null +++ b/stubs/gunicorn/gunicorn/__init__.pyi @@ -0,0 +1,4 @@ +version_info: tuple[int, int, int] +__version__: str +SERVER: str +SERVER_SOFTWARE: str diff --git a/stubs/gunicorn/gunicorn/_types.pyi b/stubs/gunicorn/gunicorn/_types.pyi new file mode 100644 index 000000000000..cbe38ddfd655 --- /dev/null +++ b/stubs/gunicorn/gunicorn/_types.pyi @@ -0,0 +1,23 @@ +### This .pyi file is a helper for centralized storage types that are reused across different runtime modules. ### +from _typeshed import FileDescriptor +from collections.abc import Awaitable, Callable, Iterable, MutableMapping +from typing import Any +from typing_extensions import LiteralString, TypeAlias + +_StatusType: TypeAlias = str +_HeadersType: TypeAlias = Iterable[tuple[str, str]] + +_EnvironType: TypeAlias = MutableMapping[str, Any] # See https://peps.python.org/pep-0333/ +_StartResponseType: TypeAlias = Callable[[_StatusType, _HeadersType], None] +_ResponseBodyType: TypeAlias = Iterable[bytes] +_WSGIAppType: TypeAlias = Callable[[_EnvironType, _StartResponseType], _ResponseBodyType] # noqa: Y047 + +_ScopeType: TypeAlias = MutableMapping[str, Any] +_MessageType: TypeAlias = MutableMapping[str, Any] +_ReceiveType: TypeAlias = Callable[[], Awaitable[_MessageType]] +_SendType: TypeAlias = Callable[[_MessageType], Awaitable[None]] +_ASGIAppType: TypeAlias = Callable[[_ScopeType, _ReceiveType, _SendType], Awaitable[None]] # noqa: Y047 + +_UnixSocketPathType: TypeAlias = str +_TcpAddressType: TypeAlias = tuple[LiteralString, int] # noqa: Y047 +_AddressType: TypeAlias = _UnixSocketPathType | FileDescriptor | _TcpAddressType # noqa: Y047 diff --git a/stubs/gunicorn/gunicorn/app/__init__.pyi b/stubs/gunicorn/gunicorn/app/__init__.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/stubs/gunicorn/gunicorn/app/base.pyi b/stubs/gunicorn/gunicorn/app/base.pyi new file mode 100644 index 000000000000..e23a7bae71f1 --- /dev/null +++ b/stubs/gunicorn/gunicorn/app/base.pyi @@ -0,0 +1,36 @@ +from argparse import ArgumentParser, Namespace +from typing import Any +from typing_extensions import override + +from gunicorn.config import Config +from gunicorn.glogging import Logger as GLogger + +from .._types import _ASGIAppType, _WSGIAppType + +class BaseApplication: + usage: str | None + cfg: Config + callable: _WSGIAppType | _ASGIAppType | None + prog: str | None + logger: GLogger + + def __init__(self, usage: str | None = None, prog: str | None = None) -> None: ... + def do_load_config(self) -> None: ... + def load_default_config(self) -> None: ... + def init(self, parser: ArgumentParser, opts: Namespace, args: list[str]) -> dict[str, Any] | None: ... + def load(self) -> _WSGIAppType | _ASGIAppType: ... + def load_config(self) -> None: ... + def reload(self) -> None: ... + def wsgi(self) -> _WSGIAppType | _ASGIAppType: ... + def run(self) -> None: ... + +class Application(BaseApplication): + def chdir(self) -> None: ... + def get_config_from_filename(self, filename: str) -> dict[str, Any]: ... + def get_config_from_module_name(self, module_name: str) -> dict[str, Any]: ... + def load_config_from_module_name_or_filename(self, location: str) -> dict[str, Any]: ... + def load_config_from_file(self, filename: str) -> dict[str, Any]: ... + @override + def load_config(self) -> None: ... + @override + def run(self) -> None: ... diff --git a/stubs/gunicorn/gunicorn/app/pasterapp.pyi b/stubs/gunicorn/gunicorn/app/pasterapp.pyi new file mode 100644 index 000000000000..ab94b4872f49 --- /dev/null +++ b/stubs/gunicorn/gunicorn/app/pasterapp.pyi @@ -0,0 +1,7 @@ +from typing import Any + +from .._types import _WSGIAppType + +def get_wsgi_app(config_uri: str, name: str | None = None, defaults: dict[str, Any] | None = None) -> _WSGIAppType: ... +def has_logging_config(config_file: str) -> bool: ... +def serve(app: _WSGIAppType, global_conf: dict[str, Any], **local_conf: Any) -> None: ... diff --git a/stubs/gunicorn/gunicorn/app/wsgiapp.pyi b/stubs/gunicorn/gunicorn/app/wsgiapp.pyi new file mode 100644 index 000000000000..af744d5529a7 --- /dev/null +++ b/stubs/gunicorn/gunicorn/app/wsgiapp.pyi @@ -0,0 +1,20 @@ +from argparse import ArgumentParser, Namespace +from typing_extensions import override + +from gunicorn.app.base import Application + +from .._types import _WSGIAppType + +class WSGIApplication(Application): + app_uri: str | None + + @override + def init(self, parser: ArgumentParser, opts: Namespace, args: list[str]) -> None: ... + @override + def load_config(self) -> None: ... + def load_wsgiapp(self) -> _WSGIAppType: ... + def load_pasteapp(self) -> _WSGIAppType: ... + @override + def load(self) -> _WSGIAppType: ... + +def run(prog: str | None = None) -> None: ... diff --git a/stubs/gunicorn/gunicorn/arbiter.pyi b/stubs/gunicorn/gunicorn/arbiter.pyi new file mode 100644 index 000000000000..0f7ae45f5def --- /dev/null +++ b/stubs/gunicorn/gunicorn/arbiter.pyi @@ -0,0 +1,68 @@ +import socket +from types import FrameType +from typing import ClassVar + +from gunicorn.app.base import BaseApplication +from gunicorn.config import Config +from gunicorn.glogging import Logger as GLogger +from gunicorn.workers.base import Worker + +from ._types import _AddressType +from .pidfile import Pidfile + +class Arbiter: + WORKER_BOOT_ERROR: ClassVar[int] + APP_LOAD_ERROR: ClassVar[int] + START_CTX: ClassVar[dict[int | str, str | list[str]]] + LISTENERS: ClassVar[list[socket.socket]] + WORKERS: ClassVar[dict[int, Worker]] + PIPE: ClassVar[list[int]] + SIG_QUEUE: ClassVar[list[int]] + SIGNALS: ClassVar[list[int]] + SIG_NAMES: ClassVar[dict[int, str]] + log: GLogger | None + pidfile: Pidfile | None + systemd: bool + worker_age: int + reexec_pid: int + master_pid: int + master_name: str + pid: int + app: BaseApplication + cfg: Config + worker_class: type[Worker] + address: list[_AddressType] + timeout: int + proc_name: str + num_workers: int + + def __init__(self, app: BaseApplication) -> None: ... + def setup(self, app: BaseApplication) -> None: ... + def start(self) -> None: ... + def init_signals(self) -> None: ... + def signal(self, sig: int, frame: FrameType | None) -> None: ... + def run(self) -> None: ... + def handle_chld(self, sig: int, frame: FrameType | None) -> None: ... + def handle_hup(self) -> None: ... + def handle_term(self) -> None: ... + def handle_int(self) -> None: ... + def handle_quit(self) -> None: ... + def handle_ttin(self) -> None: ... + def handle_ttou(self) -> None: ... + def handle_usr1(self) -> None: ... + def handle_usr2(self) -> None: ... + def handle_winch(self) -> None: ... + def maybe_promote_master(self) -> None: ... + def wakeup(self) -> None: ... + def halt(self, reason: str | None = None, exit_status: int = 0) -> None: ... + def sleep(self) -> None: ... + def stop(self, graceful: bool = True) -> None: ... + def reexec(self) -> None: ... + def reload(self) -> None: ... + def murder_workers(self) -> None: ... + def reap_workers(self) -> None: ... + def manage_workers(self) -> None: ... + def spawn_worker(self) -> int: ... + def spawn_workers(self) -> None: ... + def kill_workers(self, sig: int) -> None: ... + def kill_worker(self, pid: int, sig: int) -> None: ... diff --git a/stubs/gunicorn/gunicorn/config.pyi b/stubs/gunicorn/gunicorn/config.pyi new file mode 100644 index 000000000000..c1420b1714c4 --- /dev/null +++ b/stubs/gunicorn/gunicorn/config.pyi @@ -0,0 +1,1065 @@ +import argparse +from _typeshed import ConvertibleToInt +from collections.abc import Callable, Container +from ssl import SSLContext, _SSLMethod +from typing import Annotated, Any, ClassVar, overload +from typing_extensions import TypeAlias, override + +from gunicorn.arbiter import Arbiter +from gunicorn.glogging import Logger as GLogger +from gunicorn.http import Request +from gunicorn.http.wsgi import Response +from gunicorn.workers.base import Worker + +from ._types import _AddressType, _EnvironType + +_ConfigValueType: TypeAlias = Any +# Any: Value type depends on the setting's validator (e.g., validate_bool, validate_pos_int). +# Maybe types: bool, int, str, list[str], dict[str, Any], Callable[..., object], type[object], ssl.PROTOCOL_*. +# Validator ensures type correctness at runtime. + +_OnStartingHookType: TypeAlias = Callable[[Arbiter], object] +_OnReloadHookType: TypeAlias = Callable[[Arbiter], object] +_WhenReadyHookType: TypeAlias = Callable[[Arbiter], object] +_PreForkHookType: TypeAlias = Callable[[Arbiter, Worker], object] +_PostForkHookType: TypeAlias = Callable[[Arbiter, Worker], object] +_PostWorkerInitHookType: TypeAlias = Callable[[Worker], object] +_WorkerIntHookType: TypeAlias = Callable[[Worker], object] +_WorkerAbortHookType: TypeAlias = Callable[[Worker], object] +_PreExecHookType: TypeAlias = Callable[[Arbiter], object] +_PreRequestHookType: TypeAlias = Callable[[Worker, Request], object] +_PostRequestHookType: TypeAlias = Callable[[Worker, Request, _EnvironType, Response], object] +_ChildExitHookType: TypeAlias = Callable[[Arbiter, Worker], object] +_WorkerExitHookType: TypeAlias = Callable[[Arbiter, Worker], object] +_NumWorkersChangedHookType: TypeAlias = Callable[[Arbiter, int, int | None], object] +_OnExitHookType: TypeAlias = Callable[[Arbiter], object] +_SSLContextHookType: TypeAlias = Callable[[Config, Callable[[], SSLContext]], SSLContext] + +_HookType: TypeAlias = ( + _OnStartingHookType + | _OnReloadHookType + | _WhenReadyHookType + | _PreForkHookType + | _PostForkHookType + | _PostWorkerInitHookType + | _WorkerIntHookType + | _WorkerAbortHookType + | _PreExecHookType + | _PreRequestHookType + | _PostRequestHookType + | _ChildExitHookType + | _WorkerExitHookType + | _NumWorkersChangedHookType + | _OnExitHookType + | _SSLContextHookType +) +# Validators +_BoolValidatorType: TypeAlias = Callable[[bool | str | None], bool | None] +_StringValidatorType: TypeAlias = Callable[[str | None], str | None] +_ListStringValidatorType: TypeAlias = Callable[[str | list[str] | None], list[str]] +_IntValidatorType: TypeAlias = Callable[[int | ConvertibleToInt], int] +_DictValidatorType: TypeAlias = Callable[[dict[str, Any]], dict[str, Any]] +_ClassValidatorType: TypeAlias = Callable[[object | str | None], type[Any] | None] +_UserGroupValidatorType: TypeAlias = Callable[[str | int | None], int] +_AddressValidatorType: TypeAlias = Callable[[str | None], _AddressType | None] +_CallableValidatorType: TypeAlias = Callable[[str | _HookType], _HookType] + +_ValidatorType: TypeAlias = ( # noqa: Y047 + _BoolValidatorType + | _StringValidatorType + | _ListStringValidatorType + | _IntValidatorType + | _DictValidatorType + | _ClassValidatorType + | _UserGroupValidatorType + | _AddressValidatorType + | _CallableValidatorType +) + +KNOWN_SETTINGS: list[Setting] +PLATFORM: str + +def make_settings(ignore: Container[Setting] | None = None) -> dict[str, Setting]: ... +def auto_int(_: Any, x: str) -> int: ... + +class Config: + settings: dict[str, Setting] + usage: str | None + prog: str | None + env_orig: dict[str, str] + + def __init__(self, usage: str | None = None, prog: str | None = None) -> None: ... + def __getattr__(self, name: str) -> Any: ... + @override + def __setattr__(self, name: str, value: Any) -> None: ... + def set(self, name: str, value: _ConfigValueType) -> None: ... + def get_cmd_args_from_env(self) -> list[str]: ... + def parser(self) -> argparse.ArgumentParser: ... + @property + def worker_class_str(self) -> str: ... + @property + def worker_class(self) -> type[Worker]: ... + @property + def address(self) -> list[_AddressType]: ... + @property + def uid(self) -> int: ... + @property + def gid(self) -> int: ... + @property + def proc_name(self) -> str | None: ... + @property + def logger_class(self) -> type[GLogger]: ... + @property + def is_ssl(self) -> bool: ... + @property + def ssl_options(self) -> dict[str, Any]: ... + @property + def env(self) -> dict[str, str]: ... + @property + def sendfile(self) -> bool: ... + @property + def reuse_port(self) -> bool: ... + @property + def paste_global_conf(self) -> dict[str, str] | None: ... + +class SettingMeta(type): + def __new__(cls, name: str, bases: tuple[type, ...], attrs: dict[str, Any]) -> SettingMeta: ... + def fmt_desc(cls, desc: str) -> None: ... + +class Setting(metaclass=SettingMeta): + name: ClassVar[str | None] + value: _ConfigValueType + section: ClassVar[str | None] + cli: ClassVar[list[str] | None] + validator: ClassVar[Callable[..., Any] | None] # See `_ValidatorType` + type: ClassVar[argparse._ActionType | None] + meta: ClassVar[str | None] + action: ClassVar[str | None] + default: ClassVar[Any] + short: ClassVar[str | None] + desc: ClassVar[str | None] + nargs: ClassVar[int | str | None] + const: ClassVar[bool | None] + order: ClassVar[int] + + def __init__(self) -> None: ... + def add_option(self, parser: argparse.ArgumentParser) -> None: ... + def copy(self) -> Setting: ... + def get(self) -> _ConfigValueType: ... + def set(self, val: _ConfigValueType) -> None: ... + def __lt__(self, other: Setting) -> bool: ... + + __cmp__ = __lt__ + +@overload +def validate_bool(val: bool) -> bool: ... +@overload +def validate_bool(val: None) -> None: ... +@overload +def validate_bool(val: Annotated[str, "Case-insensitive boolean string ('true'/'false' in any case)"]) -> bool: ... +def validate_dict(val: dict[str, Any]) -> dict[str, Any]: ... +@overload +def validate_pos_int(val: int) -> int: ... +@overload +def validate_pos_int(val: ConvertibleToInt) -> int: ... +def validate_ssl_version(val: _SSLMethod) -> _SSLMethod: ... +@overload +def validate_string(val: str) -> str: ... +@overload +def validate_string(val: None) -> None: ... +@overload +def validate_file_exists(val: str) -> str: ... +@overload +def validate_file_exists(val: None) -> None: ... +@overload +def validate_list_string(val: str) -> list[str]: ... +@overload +def validate_list_string(val: list[str]) -> list[str]: ... +@overload +def validate_list_string(val: None) -> list[str]: ... +@overload +def validate_list_of_existing_files(val: str) -> list[str]: ... +@overload +def validate_list_of_existing_files(val: list[str]) -> list[str]: ... +@overload +def validate_list_of_existing_files(val: None) -> list[str]: ... +def validate_string_to_addr_list(val: str | None) -> list[str]: ... +def validate_string_to_list(val: str | None) -> list[str]: ... +@overload +def validate_class(val: str) -> str: ... +@overload +def validate_class(val: None) -> None: ... +@overload +def validate_class(val: object) -> object: ... +def validate_callable(arity: int) -> _CallableValidatorType: ... +def validate_user(val: int | str | None) -> int: ... +def validate_group(val: int | str | None) -> int: ... +def validate_post_request(val: str | _HookType) -> _PostRequestHookType: ... +def validate_chdir(val: str) -> str: ... +@overload +def validate_statsd_address(val: str) -> _AddressType: ... +@overload +def validate_statsd_address(val: None) -> None: ... +def validate_reload_engine(val: str) -> str: ... +@overload +def validate_header_map_behaviour(val: str) -> str: ... +@overload +def validate_header_map_behaviour(val: None) -> None: ... +def get_default_config_file() -> str | None: ... + +class ConfigFile(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[str] + desc: ClassVar[str] + +class WSGIApp(Setting): + name: ClassVar[str] + section: ClassVar[str] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class Bind(Setting): + name: ClassVar[str] + action: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_ListStringValidatorType] + default: ClassVar[list[str]] + desc: ClassVar[str] + +class Backlog(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[type[int]] + default: ClassVar[int] + desc: ClassVar[str] + +class Workers(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[type[int]] + default: ClassVar[int] + desc: ClassVar[str] + +class WorkerClass(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_ClassValidatorType] + default: ClassVar[str] + desc: ClassVar[str] + +class WorkerThreads(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[type[int]] + default: ClassVar[int] + desc: ClassVar[str] + +class WorkerConnections(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[type[int]] + default: ClassVar[int] + desc: ClassVar[str] + +class MaxRequests(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[type[int]] + default: ClassVar[int] + desc: ClassVar[str] + +class MaxRequestsJitter(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[type[int]] + default: ClassVar[int] + desc: ClassVar[str] + +class Timeout(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[type[int]] + default: ClassVar[int] + desc: ClassVar[str] + +class GracefulTimeout(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[type[int]] + default: ClassVar[int] + desc: ClassVar[str] + +class Keepalive(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[type[int]] + default: ClassVar[int] + desc: ClassVar[str] + +class LimitRequestLine(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[type[int]] + default: ClassVar[int] + desc: ClassVar[str] + +class LimitRequestFields(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[type[int]] + default: ClassVar[int] + desc: ClassVar[str] + +class LimitRequestFieldSize(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[type[int]] + default: ClassVar[int] + desc: ClassVar[str] + +class Reload(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class ReloadEngine(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[Callable[[str], str]] + default: ClassVar[str] + desc: ClassVar[str] + +class ReloadExtraFiles(Setting): + name: ClassVar[str] + action: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_ListStringValidatorType] + default: ClassVar[list[str]] + desc: ClassVar[str] + +class Spew(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class ConfigCheck(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class PrintConfig(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class PreloadApp(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class Sendfile(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + const: ClassVar[bool] + desc: ClassVar[str] + +class ReusePort(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class Chdir(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[Callable[[str], str]] + default: ClassVar[str] + default_doc: ClassVar[str] + desc: ClassVar[str] + +class Daemon(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class Env(Setting): + name: ClassVar[str] + action: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_ListStringValidatorType] + default: ClassVar[list[str]] + desc: ClassVar[str] + +class Pidfile(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class WorkerTmpDir(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class User(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_UserGroupValidatorType] + default: ClassVar[int] + default_doc: ClassVar[str] + desc: ClassVar[str] + +class Group(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_UserGroupValidatorType] + default: ClassVar[int] + default_doc: ClassVar[str] + desc: ClassVar[str] + +class Umask(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_IntValidatorType] + type: ClassVar[Callable[[Any, str], int]] + default: ClassVar[int] + desc: ClassVar[str] + +class Initgroups(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class TmpUploadDir(Setting): + name: ClassVar[str] + section: ClassVar[str] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class SecureSchemeHeader(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_DictValidatorType] + default: ClassVar[dict[str, str]] + desc: ClassVar[str] + +class ForwardedAllowIPS(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_ListStringValidatorType] + default: ClassVar[str] + desc: ClassVar[str] + +class AccessLog(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class DisableRedirectAccessToSyslog(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class AccessLogFormat(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[str] + desc: ClassVar[str] + +class ErrorLog(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[str] + desc: ClassVar[str] + +class Loglevel(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[str] + desc: ClassVar[str] + +class CaptureOutput(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class LoggerClass(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_ClassValidatorType] + default: ClassVar[str] + desc: ClassVar[str] + +class LogConfig(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class LogConfigDict(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_DictValidatorType] + default: ClassVar[dict[str, Any]] + desc: ClassVar[str] + +class LogConfigJson(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class SyslogTo(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[str] + desc: ClassVar[str] + +class Syslog(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class SyslogPrefix(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class SyslogFacility(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[str] + desc: ClassVar[str] + +class EnableStdioInheritance(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + default: ClassVar[bool] + action: ClassVar[str] + desc: ClassVar[str] + +class StatsdHost(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + default: ClassVar[None] + validator: ClassVar[_AddressValidatorType] + desc: ClassVar[str] + +class DogstatsdTags(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + default: ClassVar[str] + validator: ClassVar[_StringValidatorType] + desc: ClassVar[str] + +class StatsdPrefix(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + default: ClassVar[str] + validator: ClassVar[_StringValidatorType] + desc: ClassVar[str] + +class Procname(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class DefaultProcName(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[str] + desc: ClassVar[str] + +class PythonPath(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class Paste(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class OnStarting(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] = ... + type: ClassVar[Callable[..., Any]] + default: ClassVar[_OnStartingHookType] + desc: ClassVar[str] + + def on_starting(server: Arbiter) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class OnReload(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_OnReloadHookType] + desc: ClassVar[str] + + def on_reload(server: Arbiter) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class WhenReady(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_WhenReadyHookType] + desc: ClassVar[str] + + def when_ready(server: Arbiter) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class Prefork(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_PreForkHookType] + desc: ClassVar[str] + + def pre_fork(server: Arbiter, worker: Worker) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class Postfork(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_PostForkHookType] + desc: ClassVar[str] + + def post_fork(server: Arbiter, worker: Worker) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class PostWorkerInit(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_PostWorkerInitHookType] + desc: ClassVar[str] + + def post_worker_init(worker: Worker) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class WorkerInt(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_WorkerIntHookType] + desc: ClassVar[str] + + def worker_int(worker: Worker) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class WorkerAbort(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_WorkerAbortHookType] + desc: ClassVar[str] + + def worker_abort(worker: Worker) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class PreExec(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_PreExecHookType] + desc: ClassVar[str] + + def pre_exec(server: Arbiter) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class PreRequest(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_PreRequestHookType] + desc: ClassVar[str] + + def pre_request(worker: Worker, req: Request) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class PostRequest(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_PostRequestHookType] + desc: ClassVar[str] + + def post_request(worker: Worker, req: Request, environ: _EnvironType, resp: Response) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class ChildExit(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_ChildExitHookType] + desc: ClassVar[str] + + def child_exit(server: Arbiter, worker: Worker) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class WorkerExit(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_WorkerExitHookType] + desc: ClassVar[str] + + def worker_exit(server: Arbiter, worker: Worker) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class NumWorkersChanged(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_NumWorkersChangedHookType] + desc: ClassVar[str] + + def nworkers_changed(server: Arbiter, new_value: int, old_value: int | None) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class OnExit(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + default: ClassVar[_OnExitHookType] + desc: ClassVar[str] + + def on_exit(server: Arbiter) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class NewSSLContext(Setting): + name: ClassVar[str] + section: ClassVar[str] + validator: ClassVar[_CallableValidatorType] + type: ClassVar[Callable[..., Any]] + default: ClassVar[_SSLContextHookType] + desc: ClassVar[str] + + def ssl_context(config: Config, default_ssl_context_factory: Callable[[], SSLContext]) -> SSLContext: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + +class ProxyProtocol(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + default: ClassVar[bool] + action: ClassVar[str] + desc: ClassVar[str] + +class ProxyAllowFrom(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_ListStringValidatorType] + default: ClassVar[str] + desc: ClassVar[str] + +class KeyFile(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class CertFile(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class SSLVersion(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[Callable[[_SSLMethod], _SSLMethod]] + default: ClassVar[_SSLMethod] + desc: ClassVar[str] + +class CertReqs(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_IntValidatorType] + default: ClassVar[int] + desc: ClassVar[str] + +class CACerts(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class SuppressRaggedEOFs(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + action: ClassVar[str] + default: ClassVar[bool] + validator: ClassVar[_BoolValidatorType] + desc: ClassVar[str] + +class DoHandshakeOnConnect(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class Ciphers(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_StringValidatorType] + default: ClassVar[None] + desc: ClassVar[str] + +class PasteGlobalConf(Setting): + name: ClassVar[str] + action: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + meta: ClassVar[str] + validator: ClassVar[_ListStringValidatorType] + default: ClassVar[list[str]] + desc: ClassVar[str] + +class PermitObsoleteFolding(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class StripHeaderSpaces(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class PermitUnconventionalHTTPMethod(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class PermitUnconventionalHTTPVersion(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class CasefoldHTTPMethod(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_BoolValidatorType] + action: ClassVar[str] + default: ClassVar[bool] + desc: ClassVar[str] + +class ForwarderHeaders(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_ListStringValidatorType] + default: ClassVar[str] + desc: ClassVar[str] + +class HeaderMap(Setting): + name: ClassVar[str] + section: ClassVar[str] + cli: ClassVar[list[str]] + validator: ClassVar[_StringValidatorType] + default: ClassVar[str] + desc: ClassVar[str] diff --git a/stubs/gunicorn/gunicorn/debug.pyi b/stubs/gunicorn/gunicorn/debug.pyi new file mode 100644 index 000000000000..8769f873c587 --- /dev/null +++ b/stubs/gunicorn/gunicorn/debug.pyi @@ -0,0 +1,18 @@ +__all__ = ["spew", "unspew"] + +from collections.abc import Container +from types import FrameType +from typing import Any +from typing_extensions import Self + +class Spew: + trace_names: Container[str] | None = None + show_values: bool + + def __init__(self, trace_names: Container[str] | None = None, show_values: bool = True) -> None: ... + def __call__( + self, frame: FrameType, event: str, arg: Any # `arg` is not used inside the function, stub is set Any + ) -> Self: ... + +def spew(trace_names: Container[str] | None = None, show_values: bool = False) -> None: ... +def unspew() -> None: ... diff --git a/stubs/gunicorn/gunicorn/errors.pyi b/stubs/gunicorn/gunicorn/errors.pyi new file mode 100644 index 000000000000..f25818c3ff07 --- /dev/null +++ b/stubs/gunicorn/gunicorn/errors.pyi @@ -0,0 +1,8 @@ +class HaltServer(BaseException): + reason: str + exit_status: int + + def __init__(self, reason: str, exit_status: int = 1) -> None: ... + +class ConfigError(Exception): ... +class AppImportError(Exception): ... diff --git a/stubs/gunicorn/gunicorn/glogging.pyi b/stubs/gunicorn/gunicorn/glogging.pyi new file mode 100644 index 000000000000..f5fde561830a --- /dev/null +++ b/stubs/gunicorn/gunicorn/glogging.pyi @@ -0,0 +1,158 @@ +import logging +import threading +from collections.abc import Mapping +from datetime import timedelta +from logging.config import _DictConfigArgs +from socket import SocketKind +from typing import Annotated, Any, ClassVar, Literal, TypedDict, type_check_only +from typing_extensions import TypeAlias, override + +from gunicorn.http import Request +from gunicorn.http.wsgi import Response + +from ._types import _EnvironType +from .config import Config + +SYSLOG_FACILITIES: dict[str, int] + +@type_check_only +class _AtomsDict(TypedDict, total=False): + h: str + l: str + u: str + t: str + r: str + s: str + m: str | None + U: str | None + q: str | None + H: str | None + b: str + B: int | None + f: str + a: str + T: int + D: int + M: int + L: str + p: str + +_CriticalIntType: TypeAlias = Annotated[int, "50"] +_ErrorIntType: TypeAlias = Annotated[int, "40"] +_WarningIntType: TypeAlias = Annotated[int, "30"] +_InfoIntType: TypeAlias = Annotated[int, "20"] +_DebugIntType: TypeAlias = Annotated[int, "10"] +_LogLevelIntType: TypeAlias = _CriticalIntType | _ErrorIntType | _WarningIntType | _InfoIntType | _DebugIntType +_LogLevelStrType: TypeAlias = Literal["critical", "error", "warning", "info", "debug"] +_LogLevelType: TypeAlias = _LogLevelIntType | _LogLevelStrType + +CONFIG_DEFAULTS: _DictConfigArgs + +def loggers() -> list[logging.Logger]: ... + +class SafeAtoms(dict[str, Any]): + def __init__(self, atoms: dict[str, Any]) -> None: ... + @override + def __getitem__(self, k: str) -> str: ... + +_SyslogAddressType: TypeAlias = ( + tuple[Literal[SocketKind.SOCK_DGRAM] | None, str] # Unix Socket + | tuple[Literal[SocketKind.SOCK_DGRAM, SocketKind.SOCK_STREAM], tuple[str, int]] # TCP/UDP Socket +) + +def parse_syslog_address(addr: str) -> _SyslogAddressType: ... +@type_check_only +class _LogLevels(TypedDict): + critical: _CriticalIntType + error: _ErrorIntType + warning: _WarningIntType + info: _InfoIntType + debug: _DebugIntType + +class Logger: + LOG_LEVELS: ClassVar[_LogLevels] + loglevel: ClassVar[_LogLevelIntType] + error_fmt: ClassVar[str] + datefmt: ClassVar[str] + access_fmt: ClassVar[str] + syslog_fmt: ClassVar[str] + atoms_wrapper_class: ClassVar[type[SafeAtoms]] + error_log: logging.Logger + access_log: logging.Logger + error_handlers: list[logging.Handler] + access_handlers: list[logging.Handler] + logfile: Any | None + lock: threading.Lock + cfg: Config + + def __init__(self, cfg: Config) -> None: ... + def setup(self, cfg: Config) -> None: ... + def critical( + self, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = None, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + def error( + self, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = None, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + def warning( + self, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = None, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + def info( + self, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = None, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + def debug( + self, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = None, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + def exception( + self, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = True, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + def log( + self, + lvl: _LogLevelType, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = None, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + def atoms(self, resp: Response, req: Request, environ: _EnvironType, request_time: timedelta) -> _AtomsDict: ... + def access(self, resp: Response, req: Request, environ: _EnvironType, request_time: timedelta) -> None: ... + def now(self) -> str: ... + def reopen_files(self) -> None: ... + def close_on_exec(self) -> None: ... diff --git a/stubs/gunicorn/gunicorn/http/__init__.pyi b/stubs/gunicorn/gunicorn/http/__init__.pyi new file mode 100644 index 000000000000..4fb87e5feebc --- /dev/null +++ b/stubs/gunicorn/gunicorn/http/__init__.pyi @@ -0,0 +1,4 @@ +from gunicorn.http.message import Message as Message, Request as Request +from gunicorn.http.parser import RequestParser as RequestParser + +__all__ = ["Message", "Request", "RequestParser"] diff --git a/stubs/gunicorn/gunicorn/http/body.pyi b/stubs/gunicorn/gunicorn/http/body.pyi new file mode 100644 index 000000000000..cc2735015b6a --- /dev/null +++ b/stubs/gunicorn/gunicorn/http/body.pyi @@ -0,0 +1,48 @@ +import io +from collections.abc import Callable, Generator, Iterator +from typing_extensions import TypeAlias + +from gunicorn.http.message import Request +from gunicorn.http.unreader import Unreader + +class ChunkedReader: + req: Request + parser: Generator[bytes, None, None] | None + buf: io.BytesIO + + def __init__(self, req: Request, unreader: Unreader) -> None: ... + def read(self, size: int) -> bytes: ... + def parse_trailers(self, unreader: Unreader, data: bytes) -> None: ... + def parse_chunked(self, unreader: Unreader) -> Generator[bytes]: ... + def parse_chunk_size(self, unreader: Unreader, data: bytes | None = None) -> tuple[int, bytes | None]: ... + def get_data(self, unreader: Unreader, buf: io.BytesIO) -> None: ... + +class LengthReader: + unreader: Unreader + length: int + + def __init__(self, unreader: Unreader, length: int) -> None: ... + def read(self, size: int) -> bytes: ... + +class EOFReader: + unreader: Unreader + buf: io.BytesIO + finished: bool + + def __init__(self, unreader: Unreader) -> None: ... + def read(self, size: int) -> bytes: ... + +_ReaderType: TypeAlias = ChunkedReader | LengthReader | EOFReader + +class Body: + reader: _ReaderType + buf: io.BytesIO + + def __init__(self, reader: _ReaderType) -> None: ... + def __iter__(self) -> Iterator[bytes]: ... + def __next__(self) -> bytes: ... + next: Callable[[Body], bytes] + def getsize(self, size: int | None) -> int: ... + def read(self, size: int | None = None) -> bytes: ... + def readline(self, size: int | None = None) -> bytes: ... + def readlines(self, size: int | None = None) -> list[bytes]: ... diff --git a/stubs/gunicorn/gunicorn/http/errors.pyi b/stubs/gunicorn/gunicorn/http/errors.pyi new file mode 100644 index 000000000000..27c3e3e12db7 --- /dev/null +++ b/stubs/gunicorn/gunicorn/http/errors.pyi @@ -0,0 +1,89 @@ +from typing_extensions import Buffer + +from gunicorn.http import Message + +class ParseException(Exception): ... + +class NoMoreData(IOError): + buf: Buffer + + def __init__(self, buf: Buffer | None = None) -> None: ... + +class ConfigurationProblem(ParseException): + info: str + code: int + + def __init__(self, info: str) -> None: ... + +class InvalidRequestLine(ParseException): + req: str + code: int + + def __init__(self, req: str) -> None: ... + +class InvalidRequestMethod(ParseException): + method: str + + def __init__(self, method: str) -> None: ... + +class InvalidHTTPVersion(ParseException): + version: str | tuple[int, int] + + def __init__(self, version: str | tuple[int, int]) -> None: ... + +class InvalidHeader(ParseException): + hdr: str + req: Message | None + + def __init__(self, hdr: str, req: Message | None = None) -> None: ... + +class ObsoleteFolding(ParseException): + hdr: str + + def __init__(self, hdr: str) -> None: ... + +class InvalidHeaderName(ParseException): + hdr: str + + def __init__(self, hdr: str) -> None: ... + +class UnsupportedTransferCoding(ParseException): + hdr: str + code: int + + def __init__(self, hdr: str) -> None: ... + +class InvalidChunkSize(IOError): + data: bytes + + def __init__(self, data: bytes) -> None: ... + +class ChunkMissingTerminator(IOError): + term: bytes + + def __init__(self, term: bytes) -> None: ... + +class LimitRequestLine(ParseException): + size: int + max_size: int + + def __init__(self, size: int, max_size: int) -> None: ... + +class LimitRequestHeaders(ParseException): + msg: str + + def __init__(self, msg: str) -> None: ... + +class InvalidProxyLine(ParseException): + line: str + code: int + + def __init__(self, line: str) -> None: ... + +class ForbiddenProxyRequest(ParseException): + host: str + code: int + + def __init__(self, host: str) -> None: ... + +class InvalidSchemeHeaders(ParseException): ... diff --git a/stubs/gunicorn/gunicorn/http/message.pyi b/stubs/gunicorn/gunicorn/http/message.pyi new file mode 100644 index 000000000000..54e6057733ba --- /dev/null +++ b/stubs/gunicorn/gunicorn/http/message.pyi @@ -0,0 +1,62 @@ +import io +import re +from typing_extensions import override + +from gunicorn.config import Config +from gunicorn.http.body import Body +from gunicorn.http.unreader import Unreader + +from .._types import _AddressType + +MAX_REQUEST_LINE: int +MAX_HEADERS: int +DEFAULT_MAX_HEADERFIELD_SIZE: int +RFC9110_5_6_2_TOKEN_SPECIALS: str +TOKEN_RE: re.Pattern[str] +METHOD_BADCHAR_RE: re.Pattern[str] +VERSION_RE: re.Pattern[str] +RFC9110_5_5_INVALID_AND_DANGEROUS: re.Pattern[str] + +class Message: + cfg: Config + unreader: Unreader + peer_addr: _AddressType + remote_addr: _AddressType + version: tuple[int, int] | None + headers: list[tuple[str, str]] + trailers: list[tuple[str, str]] + body: Body | None + scheme: str + must_close: bool + limit_request_fields: int + limit_request_field_size: int + max_buffer_headers: int + + def __init__(self, cfg: Config, unreader: Unreader, peer_addr: _AddressType) -> None: ... + def force_close(self) -> None: ... + def parse(self, unreader: Unreader) -> bytes: ... + def parse_headers(self, data: bytes, from_trailer: bool = False) -> list[tuple[str, str]]: ... + def set_body_reader(self) -> None: ... + def should_close(self) -> bool: ... + +class Request(Message): + method: str | None + uri: str | None + path: str | None + query: str | None + fragment: str | None + limit_request_line: int + req_number: int + proxy_protocol_info: dict[str, str | int] | None + + def __init__(self, cfg: Config, unreader: Unreader, peer_addr: _AddressType, req_number: int = 1) -> None: ... + def get_data(self, unreader: Unreader, buf: io.BytesIO, stop: bool = False) -> None: ... + @override + def parse(self, unreader: Unreader) -> bytes: ... + def read_line(self, unreader: Unreader, buf: io.BytesIO, limit: int = 0) -> tuple[bytes, bytes]: ... + def proxy_protocol(self, line: str) -> bool: ... + def proxy_protocol_access_check(self) -> None: ... + def parse_proxy_protocol(self, line: str) -> None: ... + def parse_request_line(self, line_bytes: bytes) -> None: ... + @override + def set_body_reader(self) -> None: ... diff --git a/stubs/gunicorn/gunicorn/http/parser.pyi b/stubs/gunicorn/gunicorn/http/parser.pyi new file mode 100644 index 000000000000..644581644b70 --- /dev/null +++ b/stubs/gunicorn/gunicorn/http/parser.pyi @@ -0,0 +1,26 @@ +import socket +from collections.abc import Callable, Iterable, Iterator +from typing import ClassVar + +from gunicorn.config import Config +from gunicorn.http.message import Request +from gunicorn.http.unreader import Unreader + +from .._types import _AddressType + +class Parser: + mesg_class: ClassVar[type[Request] | None] + cfg: Config + unreader: Unreader + mesg: Request | None + source_addr: _AddressType + req_count: int + + def __init__(self, cfg: Config, source: socket.socket | Iterable[bytes], source_addr: _AddressType) -> None: ... + def __iter__(self) -> Iterator[Request]: ... + def __next__(self) -> Request: ... + + next: Callable[[Parser], Request] + +class RequestParser(Parser): + mesg_class: ClassVar[type[Request]] diff --git a/stubs/gunicorn/gunicorn/http/unreader.pyi b/stubs/gunicorn/gunicorn/http/unreader.pyi new file mode 100644 index 000000000000..78b47b7de7c2 --- /dev/null +++ b/stubs/gunicorn/gunicorn/http/unreader.pyi @@ -0,0 +1,28 @@ +import io +import socket +from _typeshed import ReadableBuffer +from collections.abc import Iterable, Iterator +from typing_extensions import override + +class Unreader: + buf: io.BytesIO + + def __init__(self) -> None: ... + def chunk(self) -> bytes: ... + def read(self, size: int | None = None) -> bytes: ... + def unread(self, data: ReadableBuffer) -> None: ... + +class SocketUnreader(Unreader): + sock: socket.socket + mxchunk: int + + def __init__(self, sock: socket.socket, max_chunk: int = 8192) -> None: ... + @override + def chunk(self) -> bytes: ... + +class IterUnreader(Unreader): + iter: Iterator[bytes] | None + + def __init__(self, iterable: Iterable[bytes]) -> None: ... + @override + def chunk(self) -> bytes: ... diff --git a/stubs/gunicorn/gunicorn/http/wsgi.pyi b/stubs/gunicorn/gunicorn/http/wsgi.pyi new file mode 100644 index 000000000000..619cf02bd45f --- /dev/null +++ b/stubs/gunicorn/gunicorn/http/wsgi.pyi @@ -0,0 +1,70 @@ +import io +import logging +import re +import socket +from _typeshed import ReadableBuffer +from collections.abc import Callable +from typing import Any +from typing_extensions import override + +from gunicorn.config import Config +from gunicorn.http import Request + +from .._types import _AddressType, _EnvironType, _HeadersType, _StatusType + +BLKSIZE: int +HEADER_VALUE_RE: re.Pattern[str] +log: logging.Logger + +class FileWrapper: + filelike: io.IOBase + blksize: int + close: Callable[[], None] | None + + def __init__(self, filelike: io.IOBase, blksize: int = 8192) -> None: ... + def __getitem__(self, key: Any) -> bytes: ... + +class WSGIErrorsWrapper(io.RawIOBase): + streams: list[io.TextIOBase] + + def __init__(self, cfg: Config) -> None: ... + @override + def write(self, data: ReadableBuffer) -> None: ... + +def base_environ(cfg: Config) -> _EnvironType: ... +def default_environ(req: Request, sock: socket.socket, cfg: Config) -> _EnvironType: ... +def proxy_environ(req: Request) -> _EnvironType: ... +def create( + req: Request, sock: socket.socket, client: _AddressType, server: _AddressType, cfg: Config +) -> tuple[Response, _EnvironType]: ... + +class Response: + req: Request + sock: socket.socket + version: str + status: str | None + chunked: bool + must_close: bool + headers: _HeadersType + headers_sent: bool + response_length: int | None + sent: int + upgrade: bool + cfg: Config + status_code: int | None + + def __init__(self, req: Request, sock: socket.socket, cfg: Config) -> None: ... + def force_close(self) -> None: ... + def should_close(self) -> bool: ... + def start_response( + self, status: _StatusType, headers: _HeadersType, exc_info: tuple[type, BaseException, Any] | None = None + ) -> Callable[[bytes], None]: ... + def process_headers(self, headers: _HeadersType) -> None: ... + def is_chunked(self) -> bool: ... + def default_headers(self) -> list[str]: ... + def send_headers(self) -> None: ... + def write(self, arg: bytes) -> None: ... + def can_sendfile(self) -> bool: ... + def sendfile(self, respiter: FileWrapper) -> bool: ... + def write_file(self, respiter: FileWrapper) -> None: ... + def close(self) -> None: ... diff --git a/stubs/gunicorn/gunicorn/instrument/__init__.pyi b/stubs/gunicorn/gunicorn/instrument/__init__.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/stubs/gunicorn/gunicorn/instrument/statsd.pyi b/stubs/gunicorn/gunicorn/instrument/statsd.pyi new file mode 100644 index 000000000000..94b8ca80d018 --- /dev/null +++ b/stubs/gunicorn/gunicorn/instrument/statsd.pyi @@ -0,0 +1,105 @@ +import logging +import socket +from collections.abc import Mapping +from datetime import timedelta +from typing_extensions import override + +from gunicorn.config import Config +from gunicorn.glogging import Logger +from gunicorn.http import Request +from gunicorn.http.wsgi import Response + +from .._types import _EnvironType +from ..glogging import _LogLevelType + +METRIC_VAR: str +VALUE_VAR: str +MTYPE_VAR: str +GAUGE_TYPE: str +COUNTER_TYPE: str +HISTOGRAM_TYPE: str + +class Statsd(Logger): + prefix: str + sock: socket.socket | None + dogstatsd_tags: str | None + cfg: Config + + def __init__(self, cfg: Config) -> None: ... + @override + def critical( + self, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = None, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + @override + def error( + self, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = None, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + @override + def warning( + self, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = None, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + @override + def info( + self, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = None, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + @override + def debug( + self, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = None, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + @override + def exception( + self, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = True, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + @override + def log( + self, + lvl: _LogLevelType, + msg: object, + *args: object, + exc_info: logging._ExcInfoType = None, + stack_info: bool = False, + stacklevel: int = 1, + extra: Mapping[str, object] | None = None, + ) -> None: ... + @override + def access(self, resp: Response, req: Request, environ: _EnvironType, request_time: timedelta) -> None: ... + def gauge(self, name: str, value: float) -> None: ... + def increment(self, name: str, value: int, sampling_rate: float = 1.0) -> None: ... + def decrement(self, name: str, value: int, sampling_rate: float = 1.0) -> None: ... + def histogram(self, name: str, value: float) -> None: ... diff --git a/stubs/gunicorn/gunicorn/pidfile.pyi b/stubs/gunicorn/gunicorn/pidfile.pyi new file mode 100644 index 000000000000..91fc1f421efe --- /dev/null +++ b/stubs/gunicorn/gunicorn/pidfile.pyi @@ -0,0 +1,8 @@ +from _typeshed import StrOrBytesPath + +class Pidfile: + def __init__(self, fname: StrOrBytesPath) -> None: ... + def create(self, pid: int) -> None: ... + def rename(self, path: StrOrBytesPath) -> None: ... + def unlink(self) -> None: ... + def validate(self) -> None: ... diff --git a/stubs/gunicorn/gunicorn/reloader.pyi b/stubs/gunicorn/gunicorn/reloader.pyi new file mode 100644 index 000000000000..e666355e2638 --- /dev/null +++ b/stubs/gunicorn/gunicorn/reloader.pyi @@ -0,0 +1,50 @@ +import sys +import threading +from collections.abc import Callable, Iterable +from re import Pattern +from typing import NoReturn, TypedDict, type_check_only +from typing_extensions import TypeAlias, override + +COMPILED_EXT_RE: Pattern[str] + +class Reloader(threading.Thread): + daemon: bool + + def __init__( + self, extra_files: Iterable[str] | None = None, interval: int = 1, callback: Callable[[str], None] | None = None + ) -> None: ... + def add_extra_file(self, filename: str) -> None: ... + def get_files(self) -> list[str]: ... + @override + def run(self) -> None: ... + +has_inotify: bool + +if sys.platform == "linux": + class InotifyReloader(threading.Thread): + event_mask: int + daemon: bool + + def __init__(self, extra_files: Iterable[str] | None = None, callback: Callable[[str], None] | None = None) -> None: ... + def add_extra_file(self, filename: str) -> None: ... + def get_dirs(self) -> set[str]: ... + @override + def run(self) -> None: ... + +else: + class InotifyReloader: + def __init__( + self, extra_files: Iterable[str] | None = None, callback: Callable[[str], None] | None = None + ) -> NoReturn: ... + +_PreferredReloaderType: TypeAlias = type[InotifyReloader | Reloader] +_ReloaderType: TypeAlias = InotifyReloader | Reloader # noqa: Y047 + +@type_check_only +class _ReloadedEngines(TypedDict): + auto: _PreferredReloaderType + pool: type[Reloader] + inotify: type[InotifyReloader] + +preferred_reloader: _PreferredReloaderType +reloader_engines: _ReloadedEngines diff --git a/stubs/gunicorn/gunicorn/sock.pyi b/stubs/gunicorn/gunicorn/sock.pyi new file mode 100644 index 000000000000..f2e7cf8d35da --- /dev/null +++ b/stubs/gunicorn/gunicorn/sock.pyi @@ -0,0 +1,41 @@ +import socket +import sys +from collections.abc import Iterable +from ssl import SSLContext, SSLSocket +from typing import Any, ClassVar, Literal, SupportsIndex +from typing_extensions import override + +from gunicorn.glogging import Logger as GLogger + +from .config import Config + +class BaseSocket: + def __init__(self, address: str, conf: Config, log: GLogger, fd: SupportsIndex | None = None) -> None: ... + def __getattr__(self, name: str) -> Any: ... + def set_options(self, sock: socket.socket, bound: bool = False) -> socket.socket: ... + def bind(self, sock: socket.socket) -> None: ... + def close(self) -> None: ... + +class TCPSocket(BaseSocket): + FAMILY: ClassVar[Literal[socket.AddressFamily.AF_INET, socket.AddressFamily.AF_INET6]] + + @override + def set_options(self, sock: socket.socket, bound: bool = False) -> socket.socket: ... + +class TCP6Socket(TCPSocket): + FAMILY: ClassVar[Literal[socket.AddressFamily.AF_INET6]] + +class UnixSocket(BaseSocket): + if sys.platform != "win32": + FAMILY: ClassVar[Literal[socket.AddressFamily.AF_UNIX]] + else: + FAMILY: ClassVar[Literal[0]] # Stub for windows + + def __init__(self, addr: str, conf: Config, log: GLogger, fd: SupportsIndex | None = None) -> None: ... + @override + def bind(self, sock: socket.socket) -> None: ... + +def create_sockets(conf: Config, log: GLogger, fds: Iterable[SupportsIndex] | None = None) -> list[BaseSocket]: ... +def close_sockets(listeners: Iterable[socket.socket], unlink: bool = True) -> None: ... +def ssl_context(conf: Config) -> SSLContext: ... +def ssl_wrap_socket(sock: socket.socket, conf: Config) -> SSLSocket: ... diff --git a/stubs/gunicorn/gunicorn/systemd.pyi b/stubs/gunicorn/gunicorn/systemd.pyi new file mode 100644 index 000000000000..1645f0e68052 --- /dev/null +++ b/stubs/gunicorn/gunicorn/systemd.pyi @@ -0,0 +1,6 @@ +from gunicorn.glogging import Logger as GLogger + +SD_LISTEN_FDS_START: int + +def listen_fds(unset_environment: bool = True) -> int: ... +def sd_notify(state: str, logger: GLogger, unset_environment: bool = False) -> None: ... diff --git a/stubs/gunicorn/gunicorn/util.pyi b/stubs/gunicorn/gunicorn/util.pyi new file mode 100644 index 000000000000..5ec09516cb2f --- /dev/null +++ b/stubs/gunicorn/gunicorn/util.pyi @@ -0,0 +1,48 @@ +import types +from _typeshed import FileDescriptorLike, FileDescriptorOrPath, HasFileno, StrOrBytesPath +from inspect import _IntrospectableCallable, _ParameterKind +from socket import socket +from typing import Any, Literal, NoReturn +from urllib.parse import SplitResult + +from ._types import _AddressType, _WSGIAppType + +REDIRECT_TO: str +hop_headers: set[str] + +def load_entry_point(distribution: str, group: str, name: str) -> type[object]: ... +def load_class( + uri: str | object, default: str = "gunicorn.workers.sync.SyncWorker", section: str = "gunicorn.workers" +) -> type[Any]: ... + +positionals: tuple[Literal[_ParameterKind.POSITIONAL_ONLY], Literal[_ParameterKind.POSITIONAL_OR_KEYWORD]] + +def get_arity(f: _IntrospectableCallable) -> int: ... +def get_username(uid: int) -> str: ... +def set_owner_process(uid: int, gid: int, initgroups: bool = False) -> None: ... +def chown(path: FileDescriptorOrPath, uid: int, gid: int) -> None: ... +def unlink(filename: StrOrBytesPath) -> None: ... +def is_ipv6(addr: str) -> bool: ... +def parse_address(netloc: str, default_port: str = "8000") -> _AddressType: ... +def close_on_exec(fd: FileDescriptorLike) -> None: ... +def set_non_blocking(fd: FileDescriptorLike) -> None: ... +def close(sock: socket) -> None: ... +def write_chunk(sock: socket, data: bytes) -> None: ... +def write(sock: socket, data: bytes, chunked: bool = False) -> None: ... +def write_nonblock(sock: socket, data: bytes, chunked: bool = False) -> None: ... +def write_error(sock: socket, status_int: int, reason: str, mesg: str) -> None: ... +def import_app(module: str) -> _WSGIAppType: ... +def getcwd() -> str: ... +def http_date(timestamp: float | None = None) -> str: ... +def is_hoppish(header: str) -> bool: ... +def daemonize(enable_stdio_inheritance: bool = False) -> None: ... +def seed() -> None: ... +def check_is_writable(path: FileDescriptorOrPath) -> None: ... +def to_bytestring(value: str | bytes, encoding: str = "utf8") -> bytes: ... +def has_fileno(obj: HasFileno) -> bool: ... +def warn(msg: str) -> None: ... +def make_fail_app(msg: str) -> _WSGIAppType: ... +def split_request_uri(uri: str) -> SplitResult: ... +def reraise(tp: type[BaseException], value: BaseException | None, tb: types.TracebackType | None = None) -> NoReturn: ... +def bytes_to_str(b: bytes) -> str: ... +def unquote_to_wsgi_str(string: str) -> str: ... diff --git a/stubs/gunicorn/gunicorn/workers/__init__.pyi b/stubs/gunicorn/gunicorn/workers/__init__.pyi new file mode 100644 index 000000000000..b1e6ab0b1350 --- /dev/null +++ b/stubs/gunicorn/gunicorn/workers/__init__.pyi @@ -0,0 +1,13 @@ +from typing import TypedDict, type_check_only + +@type_check_only +class _SupportedWorkers(TypedDict): + sync: str + eventlet: str + gevent: str + gevent_wsgi: str + gevent_pywsgi: str + tornado: str + gthread: str + +SUPPORTED_WORKERS: _SupportedWorkers diff --git a/stubs/gunicorn/gunicorn/workers/base.pyi b/stubs/gunicorn/gunicorn/workers/base.pyi new file mode 100644 index 000000000000..aa0d5fc3a76a --- /dev/null +++ b/stubs/gunicorn/gunicorn/workers/base.pyi @@ -0,0 +1,48 @@ +import socket +from types import FrameType +from typing import ClassVar + +from gunicorn.app.base import BaseApplication +from gunicorn.config import Config +from gunicorn.glogging import Logger as GLogger +from gunicorn.http import Request +from gunicorn.workers.workertmp import WorkerTmp + +from .._types import _AddressType, _WSGIAppType +from ..reloader import _ReloaderType + +class Worker: + SIGNALS: ClassVar[list[int]] + PIPE: ClassVar[list[int]] + age: int + pid: str + ppid: int + sockets: list[socket.socket] + app: BaseApplication + timeout: int + cfg: Config + booted: bool + aborted: bool + reloader: _ReloaderType | None + nr: int + max_requests: int + alive: bool + log: GLogger + tmp: WorkerTmp + wait_fds: list[socket.socket | int] + wsgi: _WSGIAppType + + def __init__( + self, age: int, ppid: int, sockets: list[socket.socket], app: BaseApplication, timeout: int, cfg: Config, log: GLogger + ) -> None: ... + def notify(self) -> None: ... + def run(self) -> None: ... + def init_process(self) -> None: ... + def load_wsgi(self) -> None: ... + def init_signals(self) -> None: ... + def handle_usr1(self, sig: int, frame: FrameType | None) -> None: ... + def handle_exit(self, sig: int, frame: FrameType | None) -> None: ... + def handle_quit(self, sig: int, frame: FrameType | None) -> None: ... + def handle_abort(self, sig: int, frame: FrameType | None) -> None: ... + def handle_error(self, req: Request | None, client: socket.socket, addr: _AddressType, exc: BaseException) -> None: ... + def handle_winch(self, sig: int, fname: str | None) -> None: ... diff --git a/stubs/gunicorn/gunicorn/workers/base_async.pyi b/stubs/gunicorn/gunicorn/workers/base_async.pyi new file mode 100644 index 000000000000..6b8523770077 --- /dev/null +++ b/stubs/gunicorn/gunicorn/workers/base_async.pyi @@ -0,0 +1,17 @@ +import socket + +from gunicorn.http import Request +from gunicorn.workers import base + +from .._types import _AddressType + +ALREADY_HANDLED: object + +class AsyncWorker(base.Worker): + worker_connections: int + alive: bool + + def timeout_ctx(self) -> None: ... + def is_already_handled(self, respiter: object) -> bool: ... + def handle(self, listener: socket.socket, client: socket.socket, addr: _AddressType) -> None: ... + def handle_request(self, listener_name: str, req: Request, sock: socket.socket, addr: _AddressType) -> bool: ... diff --git a/stubs/gunicorn/gunicorn/workers/geventlet.pyi b/stubs/gunicorn/gunicorn/workers/geventlet.pyi new file mode 100644 index 000000000000..5bbcd54c432d --- /dev/null +++ b/stubs/gunicorn/gunicorn/workers/geventlet.pyi @@ -0,0 +1,31 @@ +from types import FrameType +from typing import Any +from typing_extensions import TypeAlias, override + +from gunicorn.workers.base_async import AsyncWorker + +from .._types import _AddressType + +GreenSocket: TypeAlias = Any # eventlet GreenSocket class + +EVENTLET_WSGI_LOCAL: Any # eventlet local instance +EVENTLET_ALREADY_HANDLED: bool | None + +def patch_sendfile() -> None: ... + +class EventletWorker(AsyncWorker): + def patch(self) -> None: ... + @override + def is_already_handled(self, respiter: object) -> bool: ... + @override + def init_process(self) -> None: ... + @override + def handle_quit(self, sig: int, frame: FrameType | None) -> None: ... + @override + def handle_usr1(self, sig: int, frame: FrameType | None) -> None: ... + @override + def timeout_ctx(self) -> None: ... + @override + def handle(self, listener: GreenSocket, client: GreenSocket, addr: _AddressType) -> None: ... + @override + def run(self) -> None: ... diff --git a/stubs/gunicorn/gunicorn/workers/ggevent.pyi b/stubs/gunicorn/gunicorn/workers/ggevent.pyi new file mode 100644 index 000000000000..3ebf48025c85 --- /dev/null +++ b/stubs/gunicorn/gunicorn/workers/ggevent.pyi @@ -0,0 +1,54 @@ +from types import FrameType +from typing import Any, ClassVar +from typing_extensions import override + +from gevent import pywsgi +from gevent.pywsgi import WSGIHandler +from gevent.server import StreamServer +from gevent.socket import socket as GeventSocket +from gunicorn.http import Request +from gunicorn.workers.base_async import AsyncWorker + +from .._types import _AddressType + +VERSION: str + +class GeventWorker(AsyncWorker): + server_class: ClassVar[type[StreamServer] | None] + wsgi_handler: ClassVar[type[WSGIHandler] | None] + sockets: list[GeventSocket] + + def patch(self) -> None: ... + @override + def notify(self) -> None: ... + @override + def timeout_ctx(self) -> None: ... + @override + def run(self) -> None: ... + @override + def handle(self, listener: GeventSocket, client: GeventSocket, addr: _AddressType) -> None: ... + @override + def handle_request(self, listener_name: str, req: Request, sock: GeventSocket, addr: _AddressType) -> bool: ... + @override + def handle_quit(self, sig: int, frame: FrameType | None) -> None: ... + @override + def handle_usr1(self, sig: int, frame: FrameType | None) -> None: ... + @override + def init_process(self) -> None: ... + +class GeventResponse: + status: ClassVar[str | None] + headers: ClassVar[dict[str, str] | None] + sent: ClassVar[int | None] + + def __init__(self, status: str, headers: dict[str, str], clength: int | None) -> None: ... + +class PyWSGIHandler(pywsgi.WSGIHandler): + def log_request(self) -> None: ... + def get_environ(self) -> dict[str, Any]: ... + +class PyWSGIServer(pywsgi.WSGIServer): ... + +class GeventPyWSGIWorker(GeventWorker): + server_class: ClassVar[type[PyWSGIServer] | None] + wsgi_handler: ClassVar[type[PyWSGIHandler] | None] diff --git a/stubs/gunicorn/gunicorn/workers/gthread.pyi b/stubs/gunicorn/gunicorn/workers/gthread.pyi new file mode 100644 index 000000000000..c3057c7e26b5 --- /dev/null +++ b/stubs/gunicorn/gunicorn/workers/gthread.pyi @@ -0,0 +1,50 @@ +import socket +from collections import deque +from concurrent.futures import Future, ThreadPoolExecutor +from selectors import DefaultSelector +from types import FrameType + +from gunicorn.config import Config +from gunicorn.glogging import Logger as GLogger +from gunicorn.http import RequestParser + +from .._types import _AddressType +from . import base + +class TConn: + cfg: Config + sock: socket.socket + client: _AddressType + server: _AddressType + timeout: float | None + parser: RequestParser | None + initialized: bool + + def __init__(self, cfg: Config, sock: socket.socket, client: _AddressType, server: _AddressType) -> None: ... + def init(self) -> None: ... + def set_timeout(self) -> None: ... + def close(self) -> None: ... + +class ThreadWorker(base.Worker): + worker_connections: int + max_keepalived: int + tpool: ThreadPoolExecutor + poller: DefaultSelector + futures: deque[Future[tuple[bool, TConn]]] + nr_conns: int + alive: bool + + @classmethod + def check_config(cls, cfg: Config, log: GLogger) -> None: ... + def init_process(self) -> None: ... + def get_thread_pool(self) -> ThreadPoolExecutor: ... + def handle_quit(self, sig: int, frame: FrameType | None) -> None: ... + def enqueue_req(self, conn: TConn) -> None: ... + def accept(self, server: _AddressType, listener: socket.socket) -> None: ... + def on_client_socket_readable(self, conn: TConn, client: socket.socket) -> None: ... + def murder_keepalived(self) -> None: ... + def is_parent_alive(self) -> bool: ... + def run(self) -> None: ... + def finish_request(self, fs: Future[tuple[bool, TConn]]) -> None: ... + def handle(self, conn: TConn) -> tuple[bool, TConn]: ... + def handle_request(self, req: RequestParser, conn: TConn) -> bool: ... diff --git a/stubs/gunicorn/gunicorn/workers/gtornado.pyi b/stubs/gunicorn/gunicorn/workers/gtornado.pyi new file mode 100644 index 000000000000..13b0a3f96a40 --- /dev/null +++ b/stubs/gunicorn/gunicorn/workers/gtornado.pyi @@ -0,0 +1,28 @@ +from types import FrameType +from typing import Any +from typing_extensions import TypeAlias, override + +from gunicorn.workers.base import Worker + +IOLoop: TypeAlias = Any # tornado IOLoop class +PeriodicCallback: TypeAlias = Any # tornado PeriodicCallback class + +TORNADO5: bool + +class TornadoWorker(Worker): + alive: bool + server_alive: bool + ioloop: IOLoop + callbacks: list[PeriodicCallback] + + @classmethod + def setup(cls) -> None: ... + @override + def handle_exit(self, sig: int, frame: FrameType | None) -> None: ... + def handle_request(self) -> None: ... + def watchdog(self) -> None: ... + def heartbeat(self) -> None: ... + @override + def init_process(self) -> None: ... + @override + def run(self) -> None: ... diff --git a/stubs/gunicorn/gunicorn/workers/sync.pyi b/stubs/gunicorn/gunicorn/workers/sync.pyi new file mode 100644 index 000000000000..061e501df0a5 --- /dev/null +++ b/stubs/gunicorn/gunicorn/workers/sync.pyi @@ -0,0 +1,22 @@ +import socket +from typing_extensions import override + +from gunicorn.http import Request +from gunicorn.workers.base import Worker + +from .._types import _AddressType + +class StopWaiting(Exception): ... + +class SyncWorker(Worker): + def accept(self, listener: socket.socket) -> None: ... + def wait(self, timeout: int) -> list[socket.socket | int] | None: ... + def is_parent_alive(self) -> bool: ... + def run_for_one(self, timeout: int) -> None: ... + def run_for_multiple(self, timeout: int) -> None: ... + @override + def run(self) -> None: ... + def handle(self, listener: socket.socket, client: socket.socket, addr: _AddressType) -> None: ... + def handle_request(self, listener: socket.socket, req: Request, client: socket.socket, addr: tuple[str, int]) -> bool: ... + @override + def handle_error(self, req: Request | None, client: socket.socket, addr: _AddressType, exc: BaseException) -> None: ... diff --git a/stubs/gunicorn/gunicorn/workers/workertmp.pyi b/stubs/gunicorn/gunicorn/workers/workertmp.pyi new file mode 100644 index 000000000000..0ee89ce3686d --- /dev/null +++ b/stubs/gunicorn/gunicorn/workers/workertmp.pyi @@ -0,0 +1,11 @@ +from gunicorn.config import Config + +PLATFORM: str +IS_CYGWIN: bool + +class WorkerTmp: + def __init__(self, cfg: Config) -> None: ... + def notify(self) -> None: ... + def last_update(self) -> float: ... + def fileno(self) -> int: ... + def close(self) -> None: ...