diff --git a/stubs/gunicorn/METADATA.toml b/stubs/gunicorn/METADATA.toml index bb712638260e..ef9dc009f948 100644 --- a/stubs/gunicorn/METADATA.toml +++ b/stubs/gunicorn/METADATA.toml @@ -1,4 +1,4 @@ -version = "25.2.0" +version = "25.3.0" upstream_repository = "https://github.com/benoitc/gunicorn" requires = ["types-gevent"] diff --git a/stubs/gunicorn/gunicorn/asgi/__init__.pyi b/stubs/gunicorn/gunicorn/asgi/__init__.pyi index 7469610eac93..0e635cb1217d 100644 --- a/stubs/gunicorn/gunicorn/asgi/__init__.pyi +++ b/stubs/gunicorn/gunicorn/asgi/__init__.pyi @@ -1,5 +1,4 @@ from gunicorn.asgi.lifespan import LifespanManager as LifespanManager -from gunicorn.asgi.message import AsyncRequest as AsyncRequest from gunicorn.asgi.unreader import AsyncUnreader as AsyncUnreader -__all__ = ["AsyncUnreader", "AsyncRequest", "LifespanManager"] +__all__ = ["AsyncUnreader", "LifespanManager"] diff --git a/stubs/gunicorn/gunicorn/asgi/message.pyi b/stubs/gunicorn/gunicorn/asgi/message.pyi deleted file mode 100644 index a279e34cdd91..000000000000 --- a/stubs/gunicorn/gunicorn/asgi/message.pyi +++ /dev/null @@ -1,50 +0,0 @@ -import re -from typing import Final, Literal -from typing_extensions import Self - -from gunicorn.asgi.unreader import AsyncUnreader -from gunicorn.config import Config - -from .._types import _AddressType - -MAX_REQUEST_LINE: Final = 8190 -MAX_HEADERS: Final = 32768 -DEFAULT_MAX_HEADERFIELD_SIZE: Final = 8190 -RFC9110_5_6_2_TOKEN_SPECIALS: Final = r"!#$%&'*+-.^_`|~" -TOKEN_RE: Final[re.Pattern[str]] -METHOD_BADCHAR_RE: Final[re.Pattern[str]] -VERSION_RE: Final[re.Pattern[str]] -RFC9110_5_5_INVALID_AND_DANGEROUS: Final[re.Pattern[str]] - -class AsyncRequest: - cfg: Config - unreader: AsyncUnreader - peer_addr: _AddressType - remote_addr: _AddressType - req_number: int - version: tuple[int, int] | None - method: str | None - uri: str | None - path: str | None - query: str | None - fragment: str | None - headers: list[tuple[str, str]] - trailers: list[tuple[str, str]] - scheme: Literal["https", "http"] - must_close: bool - proxy_protocol_info: dict[str, str | int | None] | None # TODO: Use TypedDict - limit_request_line: int - limit_request_fields: int - limit_request_field_size: int - max_buffer_headers: int - content_length: int | None - 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: ... - def force_close(self) -> None: ... - def should_close(self) -> bool: ... - def get_header(self, name: str) -> str | None: ... - async def read_body(self, size: int = 8192) -> bytes: ... - async def drain_body(self) -> None: ... diff --git a/stubs/gunicorn/gunicorn/asgi/parser.pyi b/stubs/gunicorn/gunicorn/asgi/parser.pyi index 4ef818bdbf53..f36970b1c8a5 100644 --- a/stubs/gunicorn/gunicorn/asgi/parser.pyi +++ b/stubs/gunicorn/gunicorn/asgi/parser.pyi @@ -1,16 +1,57 @@ from collections.abc import Callable, Iterable -from typing import Any, Literal, SupportsIndex +from enum import IntEnum +from typing import Any, Final, Literal, SupportsIndex, TypedDict, type_check_only from typing_extensions import Self, TypeAlias _H1CProtocol: TypeAlias = Any # gunicorn_h1c H1CProtocol class class ParseError(Exception): ... +class InvalidProxyLine(ParseError): ... +class InvalidProxyHeader(ParseError): ... + +PP_V2_SIGNATURE: Final[bytes] + +class PPCommand(IntEnum): + LOCAL = 0x0 + PROXY = 0x1 + +class PPFamily(IntEnum): + UNSPEC = 0x0 + INET = 0x1 + INET6 = 0x2 + UNIX = 0x3 + +class PPProtocol(IntEnum): + UNSPEC = 0x0 + STREAM = 0x1 + DGRAM = 0x2 + class LimitRequestLine(ParseError): ... +class InvalidRequestLine(ParseError): ... class LimitRequestHeaders(ParseError): ... class InvalidRequestMethod(ParseError): ... class InvalidHTTPVersion(ParseError): ... class InvalidHeaderName(ParseError): ... class InvalidHeader(ParseError): ... +class UnsupportedTransferCoding(ParseError): ... +class InvalidChunkSize(ParseError): ... +class InvalidChunkExtension(ParseError): ... + +@type_check_only +class _ProxyProtocolInfo(TypedDict): + proxy_protocol: Literal["TCP4", "TCP6", "UDP4", "UDP6"] + client_addr: str + client_port: int + proxy_addr: str + proxy_port: int + +@type_check_only +class _ProxyProtocolInfoUnknown(TypedDict): + proxy_protocol: Literal["UNKNOWN", "LOCAL", "UNSPEC"] + client_addr: None + client_port: None + proxy_addr: None + proxy_port: None class PythonProtocol: __slots__ = ( @@ -42,6 +83,9 @@ class PythonProtocol: "_permit_unconventional_http_method", "_permit_unconventional_http_version", "_header_count", + "_proxy_protocol", + "_proxy_protocol_info", + "_proxy_protocol_done", ) method: bytes | None path: bytes | None @@ -65,9 +109,13 @@ class PythonProtocol: limit_request_field_size: int = 8190, permit_unconventional_http_method: bool = False, permit_unconventional_http_version: bool = False, + proxy_protocol: Literal["off", "v1", "v2", "auto"] = "off", ) -> None: ... def feed(self, data: Iterable[SupportsIndex]) -> None: ... + @property + def proxy_protocol_info(self) -> _ProxyProtocolInfo | _ProxyProtocolInfoUnknown | None: ... def reset(self) -> None: ... + def finish(self) -> None: ... class CallbackRequest: __slots__ = ( diff --git a/stubs/gunicorn/gunicorn/http/errors.pyi b/stubs/gunicorn/gunicorn/http/errors.pyi index 22a57d6087e1..a7698a0973bc 100644 --- a/stubs/gunicorn/gunicorn/http/errors.pyi +++ b/stubs/gunicorn/gunicorn/http/errors.pyi @@ -68,6 +68,10 @@ class ChunkMissingTerminator(IOError): def __init__(self, term: bytes) -> None: ... +class InvalidChunkExtension(IOError): + reason: str + def __init__(self, reason: str) -> None: ... + class LimitRequestLine(ParseException): size: int max_size: int | None