Skip to content

Commit c3b4a7a

Browse files
authored
Add HttpResponse.text (#2622)
* Add HttpResponse.text * Remove corresponding allowlist entries * Since HttpResponse.text uses @cached_property, add it in allowlist.txt It was previously in allowlist_todo_django52.txt because it is a Django 5.2 addition, and was not implemented in django-stubs yet. It is now in allowlist.txt because it uses @cached_property, which stubtest currently doesn't handle (details: #1771)
1 parent ee8e8b1 commit c3b4a7a

File tree

6 files changed

+19
-8
lines changed

6 files changed

+19
-8
lines changed

django-stubs/http/response.pyi

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ from json import JSONEncoder
66
from typing import Any, Literal, TypeVar, overload, type_check_only
77

88
from django.utils.datastructures import CaseInsensitiveMapping, _PropertyDescriptor
9+
from django.utils.functional import cached_property
910

1011
class BadHeaderError(ValueError): ...
1112

@@ -102,6 +103,8 @@ class HttpResponse(HttpResponseBase, Iterable[bytes]):
102103
__bytes__ = serialize
103104
def __iter__(self) -> Iterator[bytes]: ...
104105
def getvalue(self) -> bytes: ...
106+
@cached_property
107+
def text(self) -> str: ...
105108

106109
class StreamingHttpResponse(HttpResponseBase, Iterable[bytes], AsyncIterable[bytes]):
107110
is_async: bool

django-stubs/test/client.pyi

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ from django.http.response import HttpResponseBase
1818
from django.template.base import Template
1919
from django.test.utils import ContextList
2020
from django.urls import ResolverMatch
21+
from django.utils.functional import cached_property
2122

2223
BOUNDARY: str
2324
MULTIPART_CONTENT: str
@@ -227,6 +228,8 @@ class _MonkeyPatchedWSGIResponse(_WSGIResponse):
227228
content: bytes
228229
resolver_match: ResolverMatch
229230
redirect_chain: list[tuple[str, int]]
231+
@cached_property
232+
def text(self) -> str: ...
230233

231234
@type_check_only
232235
class _MonkeyPatchedASGIResponse(_ASGIResponse):

scripts/stubtest/allowlist.txt

+2
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,10 @@ django.forms.renderers.Jinja2.backend
395395
django.forms.renderers.Jinja2DivFormRenderer.__init__
396396
django.http.HttpRequest.accepted_types
397397
django.http.HttpRequest.headers
398+
django.http.HttpResponse.text
398399
django.http.request.HttpRequest.accepted_types
399400
django.http.request.HttpRequest.headers
401+
django.http.response.HttpResponse.text
400402
django.middleware.csrf.CsrfViewMiddleware.allowed_origin_subdomains
401403
django.middleware.csrf.CsrfViewMiddleware.allowed_origins_exact
402404
django.middleware.csrf.CsrfViewMiddleware.csrf_trusted_origins_hosts

scripts/stubtest/allowlist_todo_django52.txt

-2
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@ django.forms.renderers.BaseRenderer.bound_field_class
186186
django.forms.utils.ErrorList.__init__
187187
django.http.HttpRequest.accepted_type
188188
django.http.HttpRequest.get_preferred_type
189-
django.http.HttpResponse.text
190189
django.http.HttpResponsePermanentRedirect.status_code_preserve_request
191190
django.http.HttpResponseRedirect.status_code_preserve_request
192191
django.http.QueryDict.pop
@@ -197,7 +196,6 @@ django.http.request.MediaType.quality
197196
django.http.request.MediaType.specificity
198197
django.http.request.QueryDict.pop
199198
django.http.request.parse_accept_header
200-
django.http.response.HttpResponse.text
201199
django.http.response.HttpResponsePermanentRedirect.status_code_preserve_request
202200
django.http.response.HttpResponseRedirect.status_code_preserve_request
203201
django.http.response.HttpResponseRedirectBase.__init__
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- case: response_object_has_text_of_type_str
2+
main: |
3+
from django.http.response import HttpResponse
4+
reveal_type(HttpResponse().text) # N: Revealed type is "builtins.str"

tests/typecheck/test/test_client.yml

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
- case: client_methods
2-
main: |
1+
- case: client_methods
2+
main: |
33
from django.test.client import Client
44
client = Client()
55
response = client.get('foo')
@@ -11,9 +11,10 @@
1111
reveal_type(response.context_data) # N: Revealed type is "Union[django.test.utils.ContextList, builtins.dict[builtins.str, Any]]"
1212
reveal_type(response.content) # N: Revealed type is "builtins.bytes"
1313
reveal_type(response.redirect_chain) # N: Revealed type is "builtins.list[Tuple[builtins.str, builtins.int]]"
14+
reveal_type(response.text) # N: Revealed type is "builtins.str"
1415
response.json()
15-
- case: async_client_methods
16-
main: |
16+
- case: async_client_methods
17+
main: |
1718
from django.test.client import AsyncClient
1819
async def main() -> None:
1920
client = AsyncClient()
@@ -27,8 +28,8 @@
2728
reveal_type(response.content) # N: Revealed type is "builtins.bytes"
2829
reveal_type(response.redirect_chain) # N: Revealed type is "builtins.list[Tuple[builtins.str, builtins.int]]"
2930
response.json()
30-
- case: request_factories
31-
main: |
31+
- case: request_factories
32+
main: |
3233
from django.test.client import RequestFactory, AsyncRequestFactory
3334
factory = RequestFactory()
3435
request = factory.get('foo')

0 commit comments

Comments
 (0)