diff --git a/stdlib/@tests/test_cases/email/check_parser.py b/stdlib/@tests/test_cases/email/check_parser.py new file mode 100644 index 000000000..fd5c24a9f --- /dev/null +++ b/stdlib/@tests/test_cases/email/check_parser.py @@ -0,0 +1,16 @@ +import email.policy +from email.message import EmailMessage, Message +from email.parser import BytesParser, Parser +from typing_extensions import assert_type + +p1 = Parser() +p2 = Parser(policy=email.policy.default) + +assert_type(p1, Parser[Message[str, str]]) +assert_type(p2, Parser[EmailMessage]) + +bp1 = BytesParser() +bp2 = BytesParser(policy=email.policy.default) + +assert_type(bp1, BytesParser[Message[str, str]]) +assert_type(bp2, BytesParser[EmailMessage]) diff --git a/stdlib/email/__init__.pyi b/stdlib/email/__init__.pyi index 628ffb2b7..53f8c350b 100644 --- a/stdlib/email/__init__.pyi +++ b/stdlib/email/__init__.pyi @@ -1,6 +1,7 @@ from collections.abc import Callable +from email._policybase import _MessageT from email.message import Message -from email.policy import Policy, _MessageT +from email.policy import Policy from typing import IO, overload from typing_extensions import TypeAlias diff --git a/stdlib/email/_policybase.pyi b/stdlib/email/_policybase.pyi index 5266609e5..b345c84a9 100644 --- a/stdlib/email/_policybase.pyi +++ b/stdlib/email/_policybase.pyi @@ -2,12 +2,12 @@ from abc import ABCMeta, abstractmethod from email.errors import MessageDefect from email.header import Header from email.message import Message -from typing import Generic, Protocol, TypeVar, type_check_only +from typing import Any, Generic, Protocol, TypeVar, type_check_only from typing_extensions import Self __all__ = ["Policy", "Compat32", "compat32"] -_MessageT = TypeVar("_MessageT", bound=Message, default=Message) +_MessageT = TypeVar("_MessageT", bound=Message[Any, Any], default=Message[str, str]) @type_check_only class _MessageFactory(Protocol[_MessageT]): @@ -74,4 +74,4 @@ class Compat32(Policy[_MessageT]): def fold(self, name: str, value: str) -> str: ... def fold_binary(self, name: str, value: str) -> bytes: ... -compat32: Compat32[Message] +compat32: Compat32[Message[str, str]] diff --git a/stdlib/email/feedparser.pyi b/stdlib/email/feedparser.pyi index 8c268ca1a..d9279e9cd 100644 --- a/stdlib/email/feedparser.pyi +++ b/stdlib/email/feedparser.pyi @@ -1,12 +1,11 @@ from collections.abc import Callable +from email._policybase import _MessageT from email.message import Message from email.policy import Policy -from typing import Generic, TypeVar, overload +from typing import Generic, overload __all__ = ["FeedParser", "BytesFeedParser"] -_MessageT = TypeVar("_MessageT", bound=Message, default=Message) - class FeedParser(Generic[_MessageT]): @overload def __init__(self: FeedParser[Message], _factory: None = None, *, policy: Policy[Message] = ...) -> None: ... diff --git a/stdlib/email/generator.pyi b/stdlib/email/generator.pyi index dfa0604a2..d30e68629 100644 --- a/stdlib/email/generator.pyi +++ b/stdlib/email/generator.pyi @@ -7,7 +7,7 @@ from typing_extensions import Self __all__ = ["Generator", "DecodedGenerator", "BytesGenerator"] # By default, generators do not have a message policy. -_MessageT = TypeVar("_MessageT", bound=Message, default=Any) +_MessageT = TypeVar("_MessageT", bound=Message[Any, Any], default=Any) class Generator(Generic[_MessageT]): maxheaderlen: int | None diff --git a/stdlib/email/mime/message.pyi b/stdlib/email/mime/message.pyi index 2a5f46296..a1e370e2e 100644 --- a/stdlib/email/mime/message.pyi +++ b/stdlib/email/mime/message.pyi @@ -1,5 +1,6 @@ +from email._policybase import _MessageT from email.mime.nonmultipart import MIMENonMultipart -from email.policy import Policy, _MessageT +from email.policy import Policy __all__ = ["MIMEMessage"] diff --git a/stdlib/email/mime/multipart.pyi b/stdlib/email/mime/multipart.pyi index 1c229f743..fb9599edb 100644 --- a/stdlib/email/mime/multipart.pyi +++ b/stdlib/email/mime/multipart.pyi @@ -1,7 +1,8 @@ from collections.abc import Sequence from email import _ParamsType +from email._policybase import _MessageT from email.mime.base import MIMEBase -from email.policy import Policy, _MessageT +from email.policy import Policy __all__ = ["MIMEMultipart"] diff --git a/stdlib/email/parser.pyi b/stdlib/email/parser.pyi index a1a57b4ee..a4924a6cb 100644 --- a/stdlib/email/parser.pyi +++ b/stdlib/email/parser.pyi @@ -1,20 +1,21 @@ from _typeshed import SupportsRead from collections.abc import Callable +from email._policybase import _MessageT from email.feedparser import BytesFeedParser as BytesFeedParser, FeedParser as FeedParser from email.message import Message from email.policy import Policy from io import _WrappedBuffer -from typing import Generic, TypeVar, overload +from typing import Generic, overload __all__ = ["Parser", "HeaderParser", "BytesParser", "BytesHeaderParser", "FeedParser", "BytesFeedParser"] -_MessageT = TypeVar("_MessageT", bound=Message, default=Message) - class Parser(Generic[_MessageT]): @overload - def __init__(self: Parser[Message[str, str]], _class: None = None, *, policy: Policy[Message[str, str]] = ...) -> None: ... + def __init__(self: Parser[Message[str, str]], _class: None = None) -> None: ... @overload - def __init__(self, _class: Callable[[], _MessageT], *, policy: Policy[_MessageT] = ...) -> None: ... + def __init__(self, _class: None = None, *, policy: Policy[_MessageT]) -> None: ... + @overload + def __init__(self, _class: Callable[[], _MessageT] | None, *, policy: Policy[_MessageT] = ...) -> None: ... def parse(self, fp: SupportsRead[str], headersonly: bool = False) -> _MessageT: ... def parsestr(self, text: str, headersonly: bool = False) -> _MessageT: ... @@ -25,9 +26,9 @@ class HeaderParser(Parser[_MessageT]): class BytesParser(Generic[_MessageT]): parser: Parser[_MessageT] @overload - def __init__( - self: BytesParser[Message[str, str]], _class: None = None, *, policy: Policy[Message[str, str]] = ... - ) -> None: ... + def __init__(self: BytesParser[Message[str, str]], _class: None = None) -> None: ... + @overload + def __init__(self, _class: None = None, *, policy: Policy[_MessageT]) -> None: ... @overload def __init__(self, _class: Callable[[], _MessageT], *, policy: Policy[_MessageT] = ...) -> None: ... def parse(self, fp: _WrappedBuffer, headersonly: bool = False) -> _MessageT: ... diff --git a/stdlib/email/policy.pyi b/stdlib/email/policy.pyi index 5005483ed..35c999919 100644 --- a/stdlib/email/policy.pyi +++ b/stdlib/email/policy.pyi @@ -1,14 +1,12 @@ from collections.abc import Callable -from email._policybase import Compat32 as Compat32, Policy as Policy, _MessageFactory, compat32 as compat32 +from email._policybase import Compat32 as Compat32, Policy as Policy, _MessageFactory, _MessageT, compat32 as compat32 from email.contentmanager import ContentManager -from email.message import EmailMessage, Message -from typing import Any, TypeVar, overload +from email.message import EmailMessage +from typing import Any, overload from typing_extensions import Self __all__ = ["Compat32", "compat32", "Policy", "EmailPolicy", "default", "strict", "SMTP", "HTTP"] -_MessageT = TypeVar("_MessageT", bound=Message, default=Message) - class EmailPolicy(Policy[_MessageT]): utf8: bool refold_source: str diff --git a/stdlib/http/client.pyi b/stdlib/http/client.pyi index 9e0f61598..5c35dff28 100644 --- a/stdlib/http/client.pyi +++ b/stdlib/http/client.pyi @@ -5,6 +5,7 @@ import sys import types from _typeshed import MaybeNone, ReadableBuffer, SupportsRead, SupportsReadline, WriteableBuffer from collections.abc import Callable, Iterable, Iterator, Mapping +from email._policybase import _MessageT from socket import socket from typing import BinaryIO, Literal, TypeVar, overload from typing_extensions import Self, TypeAlias @@ -33,7 +34,6 @@ __all__ = [ _DataType: TypeAlias = SupportsRead[bytes] | Iterable[ReadableBuffer] | ReadableBuffer _T = TypeVar("_T") -_MessageT = TypeVar("_MessageT", bound=email.message.Message) _HeaderValue: TypeAlias = ReadableBuffer | str | int HTTP_PORT: int diff --git a/stdlib/mailbox.pyi b/stdlib/mailbox.pyi index dc2fbd593..ff605c066 100644 --- a/stdlib/mailbox.pyi +++ b/stdlib/mailbox.pyi @@ -4,6 +4,7 @@ import sys from _typeshed import StrPath, SupportsNoArgReadline, SupportsRead from abc import ABCMeta, abstractmethod from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence +from email._policybase import _MessageT from types import GenericAlias, TracebackType from typing import IO, Any, AnyStr, Generic, Literal, Protocol, TypeVar, overload from typing_extensions import Self, TypeAlias @@ -29,7 +30,6 @@ __all__ = [ ] _T = TypeVar("_T") -_MessageT = TypeVar("_MessageT", bound=Message) class _SupportsReadAndReadline(SupportsRead[bytes], SupportsNoArgReadline[bytes], Protocol): ...