Skip to content

Commit 9bba8a4

Browse files
authored
Correct annotation of headers parameter of HTTP event handlers (#5854)
* Use HTTPMessage for the headers parameter of HTTP event handlers While the documentation of `BaseHandler.http_error_default()` describes the `hdrs` (`headers` in most other handlers) as "a mapping object with the headers of the error", the implementation that is located in `URLopener._open_generic_http()` will pass `response.msg` instead, which is of type `http.client.HTTPMessage`. * Use Message for the headers parameter of HTTPError When the standard library constructs `HTTPError`, it will pass an `http.client.HTTPMessage`, which is a subclass of `email.message.Message`. Picking the superclass for the annotations gives users the flexibility to for example the result of the `email.message_from_X()` functions. The only thing unique to `HTTPMessage` is the undocumented `getallmatchingheaders()` method, which is only called by `http.server.CGIHTTPRequestHandler.run_cgi()`. That class gets its headers from `http.client.parse_headers()` and not from `HTTPError`, so I think it's safe to use `Message` as the annotation.
1 parent 59624ff commit 9bba8a4

File tree

2 files changed

+24
-40
lines changed

2 files changed

+24
-40
lines changed

stdlib/urllib/error.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from email.message import Message
2-
from typing import IO, Mapping, Optional, Tuple, Union
2+
from typing import IO, Optional, Tuple, Union
33
from urllib.response import addinfourl
44

55
# Stubs for urllib.error
@@ -10,7 +10,7 @@ class URLError(IOError):
1010

1111
class HTTPError(URLError, addinfourl):
1212
code: int
13-
def __init__(self, url: str, code: int, msg: str, hdrs: Mapping[str, str], fp: Optional[IO[bytes]]) -> None: ...
13+
def __init__(self, url: str, code: int, msg: str, hdrs: Message, fp: Optional[IO[bytes]]) -> None: ...
1414

1515
class ContentTooShortError(URLError):
1616
content: Tuple[str, Message]

stdlib/urllib/request.pyi

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -111,28 +111,20 @@ class BaseHandler:
111111

112112
class HTTPDefaultErrorHandler(BaseHandler):
113113
def http_error_default(
114-
self, req: Request, fp: IO[bytes], code: int, msg: str, hdrs: Mapping[str, str]
114+
self, req: Request, fp: IO[bytes], code: int, msg: str, hdrs: HTTPMessage
115115
) -> HTTPError: ... # undocumented
116116

117117
class HTTPRedirectHandler(BaseHandler):
118118
max_redirections: ClassVar[int] # undocumented
119119
max_repeats: ClassVar[int] # undocumented
120120
inf_msg: ClassVar[str] # undocumented
121121
def redirect_request(
122-
self, req: Request, fp: IO[bytes], code: int, msg: str, headers: Mapping[str, str], newurl: str
122+
self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage, newurl: str
123123
) -> Optional[Request]: ...
124-
def http_error_301(
125-
self, req: Request, fp: IO[bytes], code: int, msg: str, headers: Mapping[str, str]
126-
) -> Optional[_UrlopenRet]: ...
127-
def http_error_302(
128-
self, req: Request, fp: IO[bytes], code: int, msg: str, headers: Mapping[str, str]
129-
) -> Optional[_UrlopenRet]: ...
130-
def http_error_303(
131-
self, req: Request, fp: IO[bytes], code: int, msg: str, headers: Mapping[str, str]
132-
) -> Optional[_UrlopenRet]: ...
133-
def http_error_307(
134-
self, req: Request, fp: IO[bytes], code: int, msg: str, headers: Mapping[str, str]
135-
) -> Optional[_UrlopenRet]: ...
124+
def http_error_301(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> Optional[_UrlopenRet]: ...
125+
def http_error_302(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> Optional[_UrlopenRet]: ...
126+
def http_error_303(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> Optional[_UrlopenRet]: ...
127+
def http_error_307(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> Optional[_UrlopenRet]: ...
136128

137129
class HTTPCookieProcessor(BaseHandler):
138130
cookiejar: CookieJar
@@ -169,7 +161,7 @@ class AbstractBasicAuthHandler:
169161
passwd: HTTPPasswordMgr
170162
add_password: Callable[[str, Union[str, Sequence[str]], str, str], None]
171163
def __init__(self, password_mgr: Optional[HTTPPasswordMgr] = ...) -> None: ...
172-
def http_error_auth_reqed(self, authreq: str, host: str, req: Request, headers: Mapping[str, str]) -> None: ...
164+
def http_error_auth_reqed(self, authreq: str, host: str, req: Request, headers: HTTPMessage) -> None: ...
173165
def http_request(self, req: Request) -> Request: ... # undocumented
174166
def http_response(self, req: Request, response: HTTPResponse) -> HTTPResponse: ... # undocumented
175167
def https_request(self, req: Request) -> Request: ... # undocumented
@@ -178,20 +170,16 @@ class AbstractBasicAuthHandler:
178170

179171
class HTTPBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
180172
auth_header: ClassVar[str] # undocumented
181-
def http_error_401(
182-
self, req: Request, fp: IO[bytes], code: int, msg: str, headers: Mapping[str, str]
183-
) -> Optional[_UrlopenRet]: ...
173+
def http_error_401(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> Optional[_UrlopenRet]: ...
184174

185175
class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
186176
auth_header: ClassVar[str]
187-
def http_error_407(
188-
self, req: Request, fp: IO[bytes], code: int, msg: str, headers: Mapping[str, str]
189-
) -> Optional[_UrlopenRet]: ...
177+
def http_error_407(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> Optional[_UrlopenRet]: ...
190178

191179
class AbstractDigestAuthHandler:
192180
def __init__(self, passwd: Optional[HTTPPasswordMgr] = ...) -> None: ...
193181
def reset_retry_count(self) -> None: ...
194-
def http_error_auth_reqed(self, auth_header: str, host: str, req: Request, headers: Mapping[str, str]) -> None: ...
182+
def http_error_auth_reqed(self, auth_header: str, host: str, req: Request, headers: HTTPMessage) -> None: ...
195183
def retry_http_digest_auth(self, req: Request, auth: str) -> Optional[_UrlopenRet]: ...
196184
def get_cnonce(self, nonce: str) -> str: ...
197185
def get_authorization(self, req: Request, chal: Mapping[str, str]) -> str: ...
@@ -200,15 +188,11 @@ class AbstractDigestAuthHandler:
200188

201189
class HTTPDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler):
202190
auth_header: ClassVar[str] # undocumented
203-
def http_error_401(
204-
self, req: Request, fp: IO[bytes], code: int, msg: str, headers: Mapping[str, str]
205-
) -> Optional[_UrlopenRet]: ...
191+
def http_error_401(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> Optional[_UrlopenRet]: ...
206192

207193
class ProxyDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler):
208194
auth_header: ClassVar[str] # undocumented
209-
def http_error_407(
210-
self, req: Request, fp: IO[bytes], code: int, msg: str, headers: Mapping[str, str]
211-
) -> Optional[_UrlopenRet]: ...
195+
def http_error_407(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> Optional[_UrlopenRet]: ...
212196

213197
class AbstractHTTPHandler(BaseHandler): # undocumented
214198
def __init__(self, debuglevel: int = ...) -> None: ...
@@ -293,10 +277,10 @@ class URLopener:
293277
def cleanup(self) -> None: ... # undocumented
294278
def close(self) -> None: ... # undocumented
295279
def http_error(
296-
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: Mapping[str, str], data: Optional[bytes] = ...
280+
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: Optional[bytes] = ...
297281
) -> _UrlopenRet: ... # undocumented
298282
def http_error_default(
299-
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: Mapping[str, str]
283+
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage
300284
) -> _UrlopenRet: ... # undocumented
301285
def open_data(self, url: str, data: Optional[bytes] = ...) -> addinfourl: ... # undocumented
302286
def open_file(self, url: str) -> addinfourl: ... # undocumented
@@ -310,24 +294,24 @@ class FancyURLopener(URLopener):
310294
def prompt_user_passwd(self, host: str, realm: str) -> Tuple[str, str]: ...
311295
def get_user_passwd(self, host: str, realm: str, clear_cache: int = ...) -> Tuple[str, str]: ... # undocumented
312296
def http_error_301(
313-
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: Mapping[str, str], data: Optional[bytes] = ...
297+
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: Optional[bytes] = ...
314298
) -> Optional[Union[_UrlopenRet, addinfourl]]: ... # undocumented
315299
def http_error_302(
316-
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: Mapping[str, str], data: Optional[bytes] = ...
300+
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: Optional[bytes] = ...
317301
) -> Optional[Union[_UrlopenRet, addinfourl]]: ... # undocumented
318302
def http_error_303(
319-
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: Mapping[str, str], data: Optional[bytes] = ...
303+
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: Optional[bytes] = ...
320304
) -> Optional[Union[_UrlopenRet, addinfourl]]: ... # undocumented
321305
def http_error_307(
322-
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: Mapping[str, str], data: Optional[bytes] = ...
306+
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: Optional[bytes] = ...
323307
) -> Optional[Union[_UrlopenRet, addinfourl]]: ... # undocumented
324308
def http_error_401(
325309
self,
326310
url: str,
327311
fp: IO[bytes],
328312
errcode: int,
329313
errmsg: str,
330-
headers: Mapping[str, str],
314+
headers: HTTPMessage,
331315
data: Optional[bytes] = ...,
332316
retry: bool = ...,
333317
) -> Optional[_UrlopenRet]: ... # undocumented
@@ -337,15 +321,15 @@ class FancyURLopener(URLopener):
337321
fp: IO[bytes],
338322
errcode: int,
339323
errmsg: str,
340-
headers: Mapping[str, str],
324+
headers: HTTPMessage,
341325
data: Optional[bytes] = ...,
342326
retry: bool = ...,
343327
) -> Optional[_UrlopenRet]: ... # undocumented
344328
def http_error_default(
345-
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: Mapping[str, str]
329+
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage
346330
) -> addinfourl: ... # undocumented
347331
def redirect_internal(
348-
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: Mapping[str, str], data: Optional[bytes]
332+
self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: Optional[bytes]
349333
) -> Optional[_UrlopenRet]: ... # undocumented
350334
def retry_http_basic_auth(
351335
self, url: str, realm: str, data: Optional[bytes] = ...

0 commit comments

Comments
 (0)