From f10dd551a8c7fe4bb6bc65d2ba26d6a85c34e3da Mon Sep 17 00:00:00 2001 From: Avasam Date: Wed, 6 Dec 2023 17:39:06 -0500 Subject: [PATCH 1/5] HTTPMessage str override --- stdlib/http/client.pyi | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/stdlib/http/client.pyi b/stdlib/http/client.pyi index 20223695a1a8..7c8ed18df796 100644 --- a/stdlib/http/client.pyi +++ b/stdlib/http/client.pyi @@ -99,6 +99,23 @@ responses: dict[int, str] class HTTPMessage(email.message.Message): def getallmatchingheaders(self, name: str) -> list[str]: ... # undocumented + # override below all of Message's methods that use `_HeaderType` / `_HeaderTypeParam` with `str` + # avoiding having to make Message generic + def __getitem__(self, name: str) -> str: ... # AnyOf[str, None] + def __setitem__(self, name: str, val: str) -> None: ... + def values(self) -> list[str]: ... + def items(self) -> list[tuple[str, str]]: ... + @overload + def get(self, name: str, failobj: None = None) -> str | None: ... + @overload + def get(self, name: str, failobj: _T) -> str | _T: ... + @overload + def get_all(self, name: str, failobj: None = None) -> list[str] | None: ... + @overload + def get_all(self, name: str, failobj: _T) -> list[str] | _T: ... + def replace_header(self, _name: str, _value: str) -> None: ... + def set_raw(self, name: str, value: str) -> None: ... + def raw_items(self) -> Iterator[tuple[str, str]]: ... def parse_headers(fp: io.BufferedIOBase, _class: Callable[[], email.message.Message] = ...) -> HTTPMessage: ... From 5ad636ae494e2eeaa5876c2cf9c861b949a51182 Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 7 Dec 2023 05:06:25 -0500 Subject: [PATCH 2/5] Update stdlib/http/client.pyi --- stdlib/http/client.pyi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/http/client.pyi b/stdlib/http/client.pyi index 7c8ed18df796..b3689796d19b 100644 --- a/stdlib/http/client.pyi +++ b/stdlib/http/client.pyi @@ -100,7 +100,8 @@ responses: dict[int, str] class HTTPMessage(email.message.Message): def getallmatchingheaders(self, name: str) -> list[str]: ... # undocumented # override below all of Message's methods that use `_HeaderType` / `_HeaderTypeParam` with `str` - # avoiding having to make Message generic + # `HTTPMessage` breaks the Liskov substitution principle by only intending for `str` headers + # This is easier than making `Message` generic def __getitem__(self, name: str) -> str: ... # AnyOf[str, None] def __setitem__(self, name: str, val: str) -> None: ... def values(self) -> list[str]: ... From cf667cfc453deaa45abc28dde971810932b9b5a4 Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 7 Dec 2023 13:53:25 -0500 Subject: [PATCH 3/5] Use Any trick on `HttpMessage.__getitem__` --- stdlib/http/client.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/http/client.pyi b/stdlib/http/client.pyi index b3689796d19b..ec9c96d339d6 100644 --- a/stdlib/http/client.pyi +++ b/stdlib/http/client.pyi @@ -102,7 +102,7 @@ class HTTPMessage(email.message.Message): # override below all of Message's methods that use `_HeaderType` / `_HeaderTypeParam` with `str` # `HTTPMessage` breaks the Liskov substitution principle by only intending for `str` headers # This is easier than making `Message` generic - def __getitem__(self, name: str) -> str: ... # AnyOf[str, None] + def __getitem__(self, name: str) -> str | Any: ... # See comment on `Message.__getitem__` def __setitem__(self, name: str, val: str) -> None: ... def values(self) -> list[str]: ... def items(self) -> list[tuple[str, str]]: ... From df109000193df0b011dd0cdbfd5a231ab662b1d6 Mon Sep 17 00:00:00 2001 From: Avasam Date: Mon, 18 Dec 2023 22:58:55 -0500 Subject: [PATCH 4/5] Make __getitem__ return potentially None --- stdlib/http/client.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/http/client.pyi b/stdlib/http/client.pyi index ec9c96d339d6..7595eb611e72 100644 --- a/stdlib/http/client.pyi +++ b/stdlib/http/client.pyi @@ -102,7 +102,7 @@ class HTTPMessage(email.message.Message): # override below all of Message's methods that use `_HeaderType` / `_HeaderTypeParam` with `str` # `HTTPMessage` breaks the Liskov substitution principle by only intending for `str` headers # This is easier than making `Message` generic - def __getitem__(self, name: str) -> str | Any: ... # See comment on `Message.__getitem__` + def __getitem__(self, name: str) -> str | None: ... def __setitem__(self, name: str, val: str) -> None: ... def values(self) -> list[str]: ... def items(self) -> list[tuple[str, str]]: ... From 89739772dce717d3adc77a5b278b81e165c8594b Mon Sep 17 00:00:00 2001 From: Avasam Date: Mon, 18 Dec 2023 23:02:07 -0500 Subject: [PATCH 5/5] new override type: ignore needed --- stdlib/http/client.pyi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/http/client.pyi b/stdlib/http/client.pyi index 7595eb611e72..fb5450730f60 100644 --- a/stdlib/http/client.pyi +++ b/stdlib/http/client.pyi @@ -103,7 +103,7 @@ class HTTPMessage(email.message.Message): # `HTTPMessage` breaks the Liskov substitution principle by only intending for `str` headers # This is easier than making `Message` generic def __getitem__(self, name: str) -> str | None: ... - def __setitem__(self, name: str, val: str) -> None: ... + def __setitem__(self, name: str, val: str) -> None: ... # type: ignore[override] def values(self) -> list[str]: ... def items(self) -> list[tuple[str, str]]: ... @overload @@ -114,8 +114,8 @@ class HTTPMessage(email.message.Message): def get_all(self, name: str, failobj: None = None) -> list[str] | None: ... @overload def get_all(self, name: str, failobj: _T) -> list[str] | _T: ... - def replace_header(self, _name: str, _value: str) -> None: ... - def set_raw(self, name: str, value: str) -> None: ... + def replace_header(self, _name: str, _value: str) -> None: ... # type: ignore[override] + def set_raw(self, name: str, value: str) -> None: ... # type: ignore[override] def raw_items(self) -> Iterator[tuple[str, str]]: ... def parse_headers(fp: io.BufferedIOBase, _class: Callable[[], email.message.Message] = ...) -> HTTPMessage: ...