Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyrightconfig.stricter.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"stubs/grpcio-reflection/grpc_reflection/v1alpha",
"stubs/grpcio-status/grpc_status",
"stubs/grpcio/grpc/__init__.pyi",
"stubs/gunicorn/gunicorn/dirty",
"stubs/hdbcli/hdbcli/dbapi.pyi",
"stubs/html5lib",
"stubs/httplib2",
Expand Down
2 changes: 1 addition & 1 deletion stubs/gunicorn/METADATA.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version = "24.1.*"
version = "25.0.*"
upstream_repository = "https://github.com/benoitc/gunicorn"
requires = ["types-gevent"]

Expand Down
8 changes: 8 additions & 0 deletions stubs/gunicorn/gunicorn/arbiter.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ from typing import ClassVar

from gunicorn.app.base import BaseApplication
from gunicorn.config import Config
from gunicorn.dirty import DirtyArbiter
from gunicorn.glogging import Logger as GLogger
from gunicorn.sock import BaseSocket
from gunicorn.workers.base import Worker
Expand All @@ -28,6 +29,9 @@ class Arbiter:
reexec_pid: int
master_pid: int
master_name: str
dirty_arbiter_pid: int
dirty_arbiter: DirtyArbiter | None
dirty_pidfile: str | None
pid: int
app: BaseApplication
cfg: Config
Expand Down Expand Up @@ -69,3 +73,7 @@ class Arbiter:
def spawn_workers(self) -> None: ...
def kill_workers(self, sig: int) -> None: ...
def kill_worker(self, pid: int, sig: int) -> None: ...
def spawn_dirty_arbiter(self) -> int | None: ...
def kill_dirty_arbiter(self, sig: int) -> None: ...
def reap_dirty_arbiter(self) -> None: ...
def manage_dirty_arbiter(self) -> None: ...
2 changes: 1 addition & 1 deletion stubs/gunicorn/gunicorn/asgi/message.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ class AsyncRequest:
async def parse(cls, cfg: Config, unreader: AsyncUnreader, peer_addr: _AddressType, req_number: int = 1) -> Self: ...
def force_close(self) -> None: ...
def should_close(self) -> bool: ...
def get_header(self, name: str) -> str: ...
def get_header(self, name: str) -> str | None: ...
async def read_body(self, size: int = 8192) -> bytes: ...
async def drain_body(self) -> None: ...
38 changes: 38 additions & 0 deletions stubs/gunicorn/gunicorn/asgi/uwsgi.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from typing import Literal
from typing_extensions import Self

from gunicorn.asgi.unreader import AsyncUnreader
from gunicorn.config import Config
from gunicorn.uwsgi.message import UWSGIRequest

from .._types import _AddressType

class AsyncUWSGIRequest(UWSGIRequest):
cfg: Config
unreader: AsyncUnreader # type: ignore[assignment]
peer_addr: _AddressType
remote_addr: _AddressType
req_number: int
method: str | None
uri: str | None
path: str | None
query: str | None
fragment: str | None
version: tuple[int, int]
headers: list[tuple[str, str]]
trailers: list[tuple[str, str]]
scheme: Literal["https", "http"]
must_close: bool
uwsgi_vars: dict[str, str]
modifier1: int
modifier2: int
proxy_protocol_info: dict[str, str | int | None] | None # TODO: Use TypedDict
content_length: int
chunked: bool

def __init__(self, cfg: Config, unreader: AsyncUnreader, peer_addr: _AddressType, req_number: int = 1) -> None: ...
@classmethod
async def parse(cls, cfg: Config, unreader: AsyncUnreader, peer_addr: _AddressType, req_number: int = 1) -> Self: ... # type: ignore[override]
async def read_body(self, size: int = 8192) -> bytes: ...
async def drain_body(self) -> None: ...
def get_header(self, name: str) -> str | None: ...
180 changes: 162 additions & 18 deletions stubs/gunicorn/gunicorn/config.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ 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 import Annotated, Any, ClassVar, Final, overload
from typing_extensions import TypeAlias

from gunicorn.arbiter import Arbiter
Expand Down Expand Up @@ -34,6 +34,10 @@ _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]
_OnDirtyStartingHookType: TypeAlias = Callable[[Arbiter], object]
_DirtyPostForkHookType: TypeAlias = Callable[[Arbiter, Worker], object]
_DirtyWorkerInitHookType: TypeAlias = Callable[[Worker], object]
_DirtyWorkerExitHookType: TypeAlias = Callable[[Arbiter, Worker], object]

_HookType: TypeAlias = (
_OnStartingHookType
Expand All @@ -52,12 +56,16 @@ _HookType: TypeAlias = (
| _NumWorkersChangedHookType
| _OnExitHookType
| _SSLContextHookType
| _OnDirtyStartingHookType
| _DirtyPostForkHookType
| _DirtyWorkerInitHookType
| _DirtyWorkerExitHookType
)
# 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]
_IntValidatorType: TypeAlias = Callable[[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]
Expand All @@ -66,6 +74,8 @@ _CallableValidatorType: TypeAlias = Callable[[str | _HookType], _HookType]
_ProxyProtocolValidatorType: TypeAlias = Callable[[str | bool | None], str]
_ASGILoopValidatorType: TypeAlias = Callable[[str | None], str]
_ASGILifespanValidatorType: TypeAlias = Callable[[str | None], str]
_HTTP2FrameSizeValidatorType: TypeAlias = Callable[[ConvertibleToInt], int]
_HTTPProtocolsValidatorType: TypeAlias = Callable[[str | None], list[str]]

_ValidatorType: TypeAlias = ( # noqa: Y047
_BoolValidatorType
Expand All @@ -80,6 +90,8 @@ _ValidatorType: TypeAlias = ( # noqa: Y047
| _ProxyProtocolValidatorType
| _ASGILoopValidatorType
| _ASGILifespanValidatorType
| _HTTP2FrameSizeValidatorType
| _HTTPProtocolsValidatorType
)

KNOWN_SETTINGS: list[Setting]
Expand Down Expand Up @@ -163,10 +175,8 @@ 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_http2_frame_size(val: ConvertibleToInt) -> int: ...
def validate_ssl_version(val: _SSLMethod) -> _SSLMethod: ...
@overload
def validate_string(val: str) -> str: ...
Expand All @@ -176,18 +186,8 @@ def validate_string(val: None) -> None: ...
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_list_string(val: str | list[str] | None) -> list[str]: ...
def validate_list_of_existing_files(val: str | list[str] | 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
Expand Down Expand Up @@ -766,7 +766,7 @@ class Paste(Setting):
class OnStarting(Setting):
name: ClassVar[str]
section: ClassVar[str]
validator: ClassVar[_CallableValidatorType] = ...
validator: ClassVar[_CallableValidatorType]
type: ClassVar[Callable[..., Any]]
default: ClassVar[_OnStartingHookType]
desc: ClassVar[str]
Expand Down Expand Up @@ -1029,6 +1029,60 @@ class Ciphers(Setting):
default: ClassVar[None]
desc: ClassVar[str]

VALID_HTTP_PROTOCOLS: Final[frozenset[str]]
ALPN_PROTOCOL_MAP: Final[dict[str, str]]

def validate_http_protocols(val: str | None) -> list[str]: ...

class HTTPProtocols(Setting):
name: ClassVar[str]
section: ClassVar[str]
cli: ClassVar[list[str]]
meta: ClassVar[str]
validator: ClassVar[_HTTPProtocolsValidatorType]
default: ClassVar[str]
desc: ClassVar[str]

class HTTP2MaxConcurrentStreams(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 HTTP2InitialWindowSize(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 HTTP2MaxFrameSize(Setting):
name: ClassVar[str]
section: ClassVar[str]
cli: ClassVar[list[str]]
meta: ClassVar[str]
validator: ClassVar[_HTTP2FrameSizeValidatorType]
type: ClassVar[type[int]]
default: ClassVar[int]
desc: ClassVar[str]

class HTTP2MaxHeaderListSize(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 PasteGlobalConf(Setting):
name: ClassVar[str]
action: ClassVar[str]
Expand Down Expand Up @@ -1129,3 +1183,93 @@ class RootPath(Setting):
validator: ClassVar[_StringValidatorType]
default: ClassVar[str]
desc: ClassVar[str]

class DirtyApps(Setting):
name: ClassVar[str]
section: ClassVar[str]
cli: ClassVar[list[str]]
action: ClassVar[str]
meta: ClassVar[str]
validator: ClassVar[_ListStringValidatorType]
default: ClassVar[list[str]]
desc: ClassVar[str]

class DirtyWorkers(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 DirtyTimeout(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 DirtyThreads(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 DirtyGracefulTimeout(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 OnDirtyStarting(Setting):
name: ClassVar[str]
section: ClassVar[str]
validator: ClassVar[_CallableValidatorType]
type: ClassVar[Callable[..., Any]]
default: ClassVar[_OnDirtyStartingHookType]
desc: ClassVar[str]

def on_dirty_starting(arbiter: Arbiter) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]

class DirtyPostFork(Setting):
name: ClassVar[str]
section: ClassVar[str]
validator: ClassVar[_CallableValidatorType]
type: ClassVar[Callable[..., Any]]
default: ClassVar[_DirtyPostForkHookType]
desc: ClassVar[str]

def dirty_post_fork(arbiter: Arbiter, worker: Worker) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]

class DirtyWorkerInit(Setting):
name: ClassVar[str]
section: ClassVar[str]
validator: ClassVar[_CallableValidatorType]
type: ClassVar[Callable[..., Any]]
default: ClassVar[_DirtyWorkerInitHookType]
desc: ClassVar[str]

def dirty_worker_init(worker: Worker) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]

class DirtyWorkerExit(Setting):
name: ClassVar[str]
section: ClassVar[str]
validator: ClassVar[_CallableValidatorType]
type: ClassVar[Callable[..., Any]]
default: ClassVar[_DirtyWorkerExitHookType]
desc: ClassVar[str]

def dirty_worker_exit(arbiter: Arbiter, worker: Worker) -> None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
37 changes: 37 additions & 0 deletions stubs/gunicorn/gunicorn/dirty/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from .app import DirtyApp as DirtyApp
from .arbiter import DirtyArbiter as DirtyArbiter
from .client import (
DirtyClient as DirtyClient,
close_dirty_client as close_dirty_client,
close_dirty_client_async as close_dirty_client_async,
get_dirty_client as get_dirty_client,
get_dirty_client_async as get_dirty_client_async,
set_dirty_socket_path as set_dirty_socket_path,
)
from .errors import (
DirtyAppError as DirtyAppError,
DirtyAppNotFoundError as DirtyAppNotFoundError,
DirtyConnectionError as DirtyConnectionError,
DirtyError as DirtyError,
DirtyProtocolError as DirtyProtocolError,
DirtyTimeoutError as DirtyTimeoutError,
DirtyWorkerError as DirtyWorkerError,
)

__all__ = [
"DirtyError",
"DirtyTimeoutError",
"DirtyConnectionError",
"DirtyWorkerError",
"DirtyAppError",
"DirtyAppNotFoundError",
"DirtyProtocolError",
"DirtyApp",
"DirtyClient",
"get_dirty_client",
"get_dirty_client_async",
"close_dirty_client",
"close_dirty_client_async",
"DirtyArbiter",
"set_dirty_socket_path",
]
17 changes: 17 additions & 0 deletions stubs/gunicorn/gunicorn/dirty/app.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from _typeshed import Incomplete
from collections.abc import Iterable
from typing import Any

class DirtyApp:
workers: Incomplete | None

def init(self) -> None: ...
def __call__(
self, action: str, *args: Any, **kwargs: Any
) -> Any: ... # Arguments and result depend on method name passed to action
def close(self) -> None: ...

def parse_dirty_app_spec(spec: str) -> tuple[str, int | None]: ...
def load_dirty_app(import_path: str): ...
def load_dirty_apps(import_paths: Iterable[str]) -> dict[str, Incomplete]: ...
def get_app_workers_attribute(import_path: str) -> int | None: ...
Loading