From d8ce0f4bccbf591013f36f3cebeb2816f14e4911 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Fri, 8 May 2026 16:57:48 +0200 Subject: [PATCH 1/2] [gunicorn] Update to 26.0.0 Closes: #15702 --- stubs/gunicorn/METADATA.toml | 11 +++++++-- stubs/gunicorn/gunicorn/asgi/parser.pyi | 1 + stubs/gunicorn/gunicorn/asgi/protocol.pyi | 11 ++++++++- stubs/gunicorn/gunicorn/dirty/tlv.pyi | 2 +- stubs/gunicorn/gunicorn/http/message.pyi | 1 + stubs/gunicorn/gunicorn/http/parser.pyi | 2 +- stubs/gunicorn/gunicorn/util.pyi | 1 + stubs/gunicorn/gunicorn/workers/geventlet.pyi | 23 ------------------- stubs/gunicorn/gunicorn/workers/gthread.pyi | 2 +- 9 files changed, 25 insertions(+), 29 deletions(-) delete mode 100644 stubs/gunicorn/gunicorn/workers/geventlet.pyi diff --git a/stubs/gunicorn/METADATA.toml b/stubs/gunicorn/METADATA.toml index 6f6a8c4a4ed8..f080ece8c618 100644 --- a/stubs/gunicorn/METADATA.toml +++ b/stubs/gunicorn/METADATA.toml @@ -1,8 +1,15 @@ -version = "25.3.0" +version = "26.0.0" upstream-repository = "https://github.com/benoitc/gunicorn" dependencies = ["types-gevent"] [tool.stubtest] supported-platforms = ["linux", "darwin"] ci-platforms = ["linux", "darwin"] -stubtest-dependencies = ["gevent>=1.4.0", "eventlet>=0.24.1,!=0.36.0", "tornado>=0.2", "setproctitle", "PasteDeploy", "inotify"] +stubtest-dependencies = [ + "gevent>=1.4.0", + "eventlet>=0.24.1,!=0.36.0", + "tornado>=0.2", + "setproctitle", + "PasteDeploy", + "inotify", +] diff --git a/stubs/gunicorn/gunicorn/asgi/parser.pyi b/stubs/gunicorn/gunicorn/asgi/parser.pyi index aa3387bf65a6..69606932ee00 100644 --- a/stubs/gunicorn/gunicorn/asgi/parser.pyi +++ b/stubs/gunicorn/gunicorn/asgi/parser.pyi @@ -10,6 +10,7 @@ class InvalidProxyLine(ParseError): ... class InvalidProxyHeader(ParseError): ... PP_V2_SIGNATURE: Final[bytes] +RFC9110_6_5_1_FORBIDDEN_TRAILER: Final[frozenset[bytes]] class PPCommand(IntEnum): LOCAL = 0x0 diff --git a/stubs/gunicorn/gunicorn/asgi/protocol.pyi b/stubs/gunicorn/gunicorn/asgi/protocol.pyi index 664c64d68db1..069603d3be53 100644 --- a/stubs/gunicorn/gunicorn/asgi/protocol.pyi +++ b/stubs/gunicorn/gunicorn/asgi/protocol.pyi @@ -38,7 +38,16 @@ class _BodyReceieverReceiveReturnType(TypedDict): more_body: NotRequired[bool] class BodyReceiver: - __slots__ = ("_chunks", "_complete", "_body_finished", "_closed", "_waiter", "request", "protocol") + __slots__ = ( + "_chunks", + "_complete", + "_body_finished", + "_closed", + "_body_wait_expired", + "_waiter", + "request", + "protocol", + ) request: CallbackRequest protocol: ASGIProtocol diff --git a/stubs/gunicorn/gunicorn/dirty/tlv.pyi b/stubs/gunicorn/gunicorn/dirty/tlv.pyi index abc9f1432a34..460e87c0b1d5 100644 --- a/stubs/gunicorn/gunicorn/dirty/tlv.pyi +++ b/stubs/gunicorn/gunicorn/dirty/tlv.pyi @@ -17,7 +17,7 @@ MAX_DICT_SIZE: Final = 1048576 class TLVEncoder: @staticmethod def encode( - value: bool | float | str | bytes | list[Incomplete] | tuple[Incomplete, ...] | dict[object, Incomplete] | None, + value: bool | float | str | bytes | list[Incomplete] | tuple[Incomplete, ...] | dict[object, Incomplete] | None ) -> bytes: ... # dict key passed to `str()` function @staticmethod def decode(data: bytes, offset: int = 0) -> tuple[Incomplete, int]: ... diff --git a/stubs/gunicorn/gunicorn/http/message.pyi b/stubs/gunicorn/gunicorn/http/message.pyi index dfa351423ef0..4243ef9eb75a 100644 --- a/stubs/gunicorn/gunicorn/http/message.pyi +++ b/stubs/gunicorn/gunicorn/http/message.pyi @@ -34,6 +34,7 @@ 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]] +RFC9110_6_5_1_FORBIDDEN_TRAILER: Final[frozenset[str]] class Message: cfg: Config diff --git a/stubs/gunicorn/gunicorn/http/parser.pyi b/stubs/gunicorn/gunicorn/http/parser.pyi index 7d0006b3ddbc..5da5625d7d67 100644 --- a/stubs/gunicorn/gunicorn/http/parser.pyi +++ b/stubs/gunicorn/gunicorn/http/parser.pyi @@ -19,7 +19,7 @@ class Parser: def __init__(self, cfg: Config, source: socket.socket | Iterable[bytes], source_addr: _AddressType) -> None: ... def __iter__(self) -> Iterator[Request]: ... - def finish_body(self) -> None: ... + def finish_body(self, deadline: float | None = None, max_bytes: int | None = None) -> None: ... def __next__(self) -> Request: ... next: Callable[[Parser], Request] diff --git a/stubs/gunicorn/gunicorn/util.pyi b/stubs/gunicorn/gunicorn/util.pyi index 2f21a00eba19..5bec0621ad15 100644 --- a/stubs/gunicorn/gunicorn/util.pyi +++ b/stubs/gunicorn/gunicorn/util.pyi @@ -27,6 +27,7 @@ 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 close_graceful(sock: socket, timeout: float = 2.0, max_drain: int = 65536) -> 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: ... diff --git a/stubs/gunicorn/gunicorn/workers/geventlet.pyi b/stubs/gunicorn/gunicorn/workers/geventlet.pyi deleted file mode 100644 index c0a53550ceae..000000000000 --- a/stubs/gunicorn/gunicorn/workers/geventlet.pyi +++ /dev/null @@ -1,23 +0,0 @@ -from types import FrameType -from typing import Any, TypeAlias - -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: ... - def is_already_handled(self, respiter: object) -> bool: ... - def init_process(self) -> None: ... - def handle_quit(self, sig: int, frame: FrameType | None) -> None: ... - def handle_usr1(self, sig: int, frame: FrameType | None) -> None: ... - def timeout_ctx(self) -> None: ... - def handle(self, listener: GreenSocket, client: GreenSocket, addr: _AddressType) -> None: ... - def run(self) -> None: ... diff --git a/stubs/gunicorn/gunicorn/workers/gthread.pyi b/stubs/gunicorn/gunicorn/workers/gthread.pyi index 26d30dfb3c48..51fab72f4e07 100644 --- a/stubs/gunicorn/gunicorn/workers/gthread.pyi +++ b/stubs/gunicorn/gunicorn/workers/gthread.pyi @@ -33,7 +33,7 @@ class TConn: def init(self) -> None: ... def set_timeout(self) -> None: ... def wait_for_data(self, timeout: float | None) -> bool: ... - def close(self) -> None: ... + def close(self, graceful: bool = False) -> None: ... class PollableMethodQueue: def __init__(self) -> None: ... From 77d2375755489ce7b621b43ad55571589bd15435 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 15:03:27 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stubs/gunicorn/gunicorn/asgi/protocol.pyi | 11 +---------- stubs/gunicorn/gunicorn/dirty/tlv.pyi | 2 +- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/stubs/gunicorn/gunicorn/asgi/protocol.pyi b/stubs/gunicorn/gunicorn/asgi/protocol.pyi index 069603d3be53..376851ee89ab 100644 --- a/stubs/gunicorn/gunicorn/asgi/protocol.pyi +++ b/stubs/gunicorn/gunicorn/asgi/protocol.pyi @@ -38,16 +38,7 @@ class _BodyReceieverReceiveReturnType(TypedDict): more_body: NotRequired[bool] class BodyReceiver: - __slots__ = ( - "_chunks", - "_complete", - "_body_finished", - "_closed", - "_body_wait_expired", - "_waiter", - "request", - "protocol", - ) + __slots__ = ("_chunks", "_complete", "_body_finished", "_closed", "_body_wait_expired", "_waiter", "request", "protocol") request: CallbackRequest protocol: ASGIProtocol diff --git a/stubs/gunicorn/gunicorn/dirty/tlv.pyi b/stubs/gunicorn/gunicorn/dirty/tlv.pyi index 460e87c0b1d5..abc9f1432a34 100644 --- a/stubs/gunicorn/gunicorn/dirty/tlv.pyi +++ b/stubs/gunicorn/gunicorn/dirty/tlv.pyi @@ -17,7 +17,7 @@ MAX_DICT_SIZE: Final = 1048576 class TLVEncoder: @staticmethod def encode( - value: bool | float | str | bytes | list[Incomplete] | tuple[Incomplete, ...] | dict[object, Incomplete] | None + value: bool | float | str | bytes | list[Incomplete] | tuple[Incomplete, ...] | dict[object, Incomplete] | None, ) -> bytes: ... # dict key passed to `str()` function @staticmethod def decode(data: bytes, offset: int = 0) -> tuple[Incomplete, int]: ...