1
1
import datetime
2
- from collections .abc import Awaitable , Callable , Iterable , Mapping , Sequence
3
- from io import BytesIO
2
+ from collections .abc import Awaitable , Callable , Iterable , Iterator , Mapping , Sequence
4
3
from re import Pattern
5
4
from typing import Any , BinaryIO , Literal , NoReturn , TypeAlias , TypeVar , overload , type_check_only
6
5
@@ -36,7 +35,7 @@ class HttpHeaders(CaseInsensitiveMapping[str]):
36
35
@classmethod
37
36
def to_asgi_names (cls , headers : Mapping [str , Any ]) -> dict [str , Any ]: ...
38
37
39
- class HttpRequest ( BytesIO ) :
38
+ class HttpRequest :
40
39
GET : _ImmutableQueryDict
41
40
POST : _ImmutableQueryDict
42
41
COOKIES : dict [str , str ]
@@ -104,7 +103,12 @@ class HttpRequest(BytesIO):
104
103
def body (self ) -> bytes : ...
105
104
def _load_post_and_files (self ) -> None : ...
106
105
def accepts (self , media_type : str ) -> bool : ...
107
- def readlines (self ) -> list [bytes ]: ... # type: ignore[override]
106
+ def close (self ) -> None : ...
107
+ # File-like and iterator interface, a minimal subset of BytesIO.
108
+ def read (self , n : int = - 1 , / ) -> bytes : ...
109
+ def readline (self , limit : int = - 1 , / ) -> bytes : ...
110
+ def __iter__ (self ) -> Iterator [bytes ]: ...
111
+ def readlines (self ) -> list [bytes ]: ...
108
112
109
113
@type_check_only
110
114
class _MutableHttpRequest (HttpRequest ):
@@ -113,36 +117,49 @@ class _MutableHttpRequest(HttpRequest):
113
117
114
118
_Z = TypeVar ("_Z" )
115
119
116
- class QueryDict (MultiValueDict [str , str ]):
120
+ # mypy uses mro to pick between `__init__` and `__new__` for return types and will prefers `__init__` over `__new__`
121
+ # in case of a tie. So to be able to specialize type via `__new__` (which is required for pyright to work),
122
+ # we need to use an intermediary class for the `__init__` method.
123
+ # See https://github.com/python/mypy/issues/17251
124
+ # https://github.com/python/mypy/blob/c724a6a806655f94d0c705a7121e3d671eced96d/mypy/typeops.py#L148-L149
125
+ class _QueryDictMixin :
126
+ def __init__ (
127
+ self ,
128
+ query_string : str | bytes | None = ...,
129
+ mutable : bool = ...,
130
+ encoding : str | None = ...,
131
+ ) -> None : ...
132
+
133
+ class QueryDict (_QueryDictMixin , MultiValueDict [str , str ]):
117
134
_mutable : bool
118
135
# We can make it mutable only by specifying `mutable=True`.
119
136
# It can be done a) with kwarg and b) with pos. arg. `overload` has
120
137
# some problems with args/kwargs + Literal, so two signatures are required.
121
138
# ('querystring', True, [...])
122
139
@overload
123
- def __init__ (
124
- self : QueryDict ,
140
+ def __new__ (
141
+ cls ,
125
142
query_string : str | bytes | None ,
126
143
mutable : Literal [True ],
127
144
encoding : str | None = ...,
128
- ) -> None : ...
145
+ ) -> QueryDict : ...
129
146
# ([querystring='string',] mutable=True, [...])
130
147
@overload
131
- def __init__ (
132
- self : QueryDict ,
148
+ def __new__ (
149
+ cls ,
133
150
* ,
134
- mutable : Literal [True ],
135
151
query_string : str | bytes | None = ...,
152
+ mutable : Literal [True ],
136
153
encoding : str | None = ...,
137
- ) -> None : ...
154
+ ) -> QueryDict : ...
138
155
# Otherwise it's immutable
139
156
@overload
140
- def __init__ ( # type: ignore[misc]
141
- self : _ImmutableQueryDict ,
157
+ def __new__ (
158
+ cls ,
142
159
query_string : str | bytes | None = ...,
143
- mutable : bool = ...,
160
+ mutable : Literal [ False ] = ...,
144
161
encoding : str | None = ...,
145
- ) -> None : ...
162
+ ) -> _ImmutableQueryDict : ...
146
163
@classmethod
147
164
def fromkeys ( # type: ignore[override]
148
165
cls ,
@@ -161,11 +178,11 @@ class QueryDict(MultiValueDict[str, str]):
161
178
def setlistdefault (self , key : str | bytes , default_list : list [str ] | None = ...) -> list [str ]: ...
162
179
def appendlist (self , key : str | bytes , value : str | bytes ) -> None : ...
163
180
# Fake signature (because *args is used in source, but it fails with more that 1 argument)
181
+ @overload # type:ignore[override]
182
+ def pop (self , key : str | bytes , / ) -> list [str ]: ...
164
183
@overload
165
- def pop (self , key : str | bytes , / ) -> str : ...
166
- @overload
167
- def pop (self , key : str | bytes , default : str | _Z = ..., / ) -> str | _Z : ...
168
- def popitem (self ) -> tuple [str , str ]: ...
184
+ def pop (self , key : str | bytes , default : str | _Z = ..., / ) -> list [str ] | _Z : ...
185
+ def popitem (self ) -> tuple [str , list [str ]]: ... # type:ignore[override]
169
186
def clear (self ) -> None : ...
170
187
def setdefault (self , key : str | bytes , default : str | bytes | None = ...) -> str : ...
171
188
def copy (self ) -> QueryDict : ...
0 commit comments