From 39ffbac1dd5ce12b4a3713e2b50068e6185e83a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandru=20M=C4=83r=C4=83=C8=99teanu?= Date: Tue, 24 Mar 2026 08:46:47 +0000 Subject: [PATCH 1/3] feat: annotate HttpRequest as readable, HttpResponse as writable --- django-stubs/http/request.pyi | 8 +++++++- django-stubs/http/response.pyi | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/django-stubs/http/request.pyi b/django-stubs/http/request.pyi index f92e651e3..243894f77 100644 --- a/django-stubs/http/request.pyi +++ b/django-stubs/http/request.pyi @@ -1,4 +1,5 @@ import datetime +import sys from collections.abc import Awaitable, Callable, Iterable, Iterator, Mapping, Sequence from re import Pattern from typing import Any, BinaryIO, Literal, NoReturn, Protocol, TypeAlias, TypeVar, overload, type_check_only @@ -12,6 +13,11 @@ from django.utils.datastructures import CaseInsensitiveMapping, ImmutableList, M from django.utils.functional import cached_property from typing_extensions import Self, override +if sys.version_info >= (3, 14): + from io import Reader +else: + from typing_extensions import Reader + RAISE_ERROR: object host_validation_re: Pattern[str] @@ -42,7 +48,7 @@ class HttpHeaders(CaseInsensitiveMapping[str]): @classmethod def to_asgi_names(cls, headers: Mapping[str, Any]) -> dict[str, Any]: ... -class HttpRequest: +class HttpRequest(Reader): GET: _ImmutableQueryDict POST: _ImmutableQueryDict COOKIES: dict[str, str] diff --git a/django-stubs/http/response.pyi b/django-stubs/http/response.pyi index 4d9bfcf72..1fe544117 100644 --- a/django-stubs/http/response.pyi +++ b/django-stubs/http/response.pyi @@ -1,4 +1,5 @@ import datetime +import sys from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator, Mapping from http.cookies import SimpleCookie from io import BytesIO @@ -9,6 +10,11 @@ from django.utils.datastructures import CaseInsensitiveMapping, _PropertyDescrip from django.utils.functional import _StrOrPromise, cached_property from typing_extensions import override +if sys.version_info >= (3, 14): + from io import Writer +else: + from typing_extensions import Writer + class BadHeaderError(ValueError): ... _Z = TypeVar("_Z") @@ -21,7 +27,7 @@ class ResponseHeaders(CaseInsensitiveMapping[str]): def pop(self, key: str, default: _Z = ...) -> _Z | tuple[str, str]: ... def setdefault(self, key: str, value: str | bytes | int) -> None: ... -class HttpResponseBase: +class HttpResponseBase(Writer): status_code: int streaming: bool cookies: SimpleCookie From 6ca88ebcab727a5e551f49fe5bce69292da1be30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandru=20M=C4=83r=C4=83=C8=99teanu?= Date: Fri, 10 Apr 2026 11:44:40 +0100 Subject: [PATCH 2/3] fix: types --- django-stubs/http/request.pyi | 9 ++------- django-stubs/http/response.pyi | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/django-stubs/http/request.pyi b/django-stubs/http/request.pyi index 243894f77..feba4e970 100644 --- a/django-stubs/http/request.pyi +++ b/django-stubs/http/request.pyi @@ -1,5 +1,4 @@ import datetime -import sys from collections.abc import Awaitable, Callable, Iterable, Iterator, Mapping, Sequence from re import Pattern from typing import Any, BinaryIO, Literal, NoReturn, Protocol, TypeAlias, TypeVar, overload, type_check_only @@ -11,12 +10,8 @@ from django.core.files import uploadedfile, uploadhandler from django.urls import ResolverMatch from django.utils.datastructures import CaseInsensitiveMapping, ImmutableList, MultiValueDict from django.utils.functional import cached_property -from typing_extensions import Self, override +from typing_extensions import Reader, Self, override -if sys.version_info >= (3, 14): - from io import Reader -else: - from typing_extensions import Reader RAISE_ERROR: object host_validation_re: Pattern[str] @@ -48,7 +43,7 @@ class HttpHeaders(CaseInsensitiveMapping[str]): @classmethod def to_asgi_names(cls, headers: Mapping[str, Any]) -> dict[str, Any]: ... -class HttpRequest(Reader): +class HttpRequest(Reader[bytes]): GET: _ImmutableQueryDict POST: _ImmutableQueryDict COOKIES: dict[str, str] diff --git a/django-stubs/http/response.pyi b/django-stubs/http/response.pyi index 1fe544117..57f048e11 100644 --- a/django-stubs/http/response.pyi +++ b/django-stubs/http/response.pyi @@ -1,5 +1,4 @@ import datetime -import sys from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator, Mapping from http.cookies import SimpleCookie from io import BytesIO @@ -8,12 +7,8 @@ from typing import Any, Literal, NoReturn, TypeVar, overload, type_check_only from django.utils.datastructures import CaseInsensitiveMapping, _PropertyDescriptor from django.utils.functional import _StrOrPromise, cached_property -from typing_extensions import override +from typing_extensions import override, Writer -if sys.version_info >= (3, 14): - from io import Writer -else: - from typing_extensions import Writer class BadHeaderError(ValueError): ... @@ -27,7 +22,7 @@ class ResponseHeaders(CaseInsensitiveMapping[str]): def pop(self, key: str, default: _Z = ...) -> _Z | tuple[str, str]: ... def setdefault(self, key: str, value: str | bytes | int) -> None: ... -class HttpResponseBase(Writer): +class HttpResponseBase(Writer[str | bytes]): status_code: int streaming: bool cookies: SimpleCookie From ccad8cf4db6eb4bab355102d614e989f1916a16c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 10:44:50 +0000 Subject: [PATCH 3/3] [pre-commit.ci] auto fixes from pre-commit.com hooks --- django-stubs/http/request.pyi | 1 - django-stubs/http/response.pyi | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/django-stubs/http/request.pyi b/django-stubs/http/request.pyi index feba4e970..1fbe7df72 100644 --- a/django-stubs/http/request.pyi +++ b/django-stubs/http/request.pyi @@ -12,7 +12,6 @@ from django.utils.datastructures import CaseInsensitiveMapping, ImmutableList, M from django.utils.functional import cached_property from typing_extensions import Reader, Self, override - RAISE_ERROR: object host_validation_re: Pattern[str] diff --git a/django-stubs/http/response.pyi b/django-stubs/http/response.pyi index 57f048e11..51ca5122a 100644 --- a/django-stubs/http/response.pyi +++ b/django-stubs/http/response.pyi @@ -7,8 +7,7 @@ from typing import Any, Literal, NoReturn, TypeVar, overload, type_check_only from django.utils.datastructures import CaseInsensitiveMapping, _PropertyDescriptor from django.utils.functional import _StrOrPromise, cached_property -from typing_extensions import override, Writer - +from typing_extensions import Writer, override class BadHeaderError(ValueError): ...