Skip to content

Commit 7f3862e

Browse files
committed
Clean up email message types
* Unify the `_MessageT` type var in `email._policybase`. * Use explicit type arguments for `Message` type in `_MessageT` type var. In particular, change bound from `Message[str, str]` to `Message[Any, Any]`. * Change `__init__()` overloads of `Parser` and `BytesParser` to accept `Message` objects that are not `Message[str, str]` if `_class` is not also given. Closes: python#13531
1 parent c27e41c commit 7f3862e

File tree

11 files changed

+41
-24
lines changed

11 files changed

+41
-24
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from email.message import Message, EmailMessage
2+
from email.parser import BytesParser, Parser
3+
import email.policy
4+
from typing import assert_type
5+
6+
p1 = Parser()
7+
p2 = Parser(policy=email.policy.default)
8+
9+
assert_type(p1, Parser[Message[str, str]])
10+
assert_type(p2, Parser[EmailMessage])
11+
12+
bp1 = BytesParser()
13+
bp2 = BytesParser(policy=email.policy.default)
14+
15+
assert_type(bp1, BytesParser[Message[str, str]])
16+
assert_type(bp2, BytesParser[EmailMessage])

stdlib/email/__init__.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from collections.abc import Callable
2+
from email._policybase import _MessageT
23
from email.message import Message
3-
from email.policy import Policy, _MessageT
4+
from email.policy import Policy
45
from typing import IO, overload
56
from typing_extensions import TypeAlias
67

stdlib/email/_policybase.pyi

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ from abc import ABCMeta, abstractmethod
22
from email.errors import MessageDefect
33
from email.header import Header
44
from email.message import Message
5-
from typing import Generic, Protocol, TypeVar, type_check_only
5+
from typing import Any, Generic, Protocol, TypeVar, type_check_only
66
from typing_extensions import Self
77

88
__all__ = ["Policy", "Compat32", "compat32"]
99

10-
_MessageT = TypeVar("_MessageT", bound=Message, default=Message)
10+
_MessageT = TypeVar("_MessageT", bound=Message[Any, Any], default=Message[str, str])
1111

1212
@type_check_only
1313
class _MessageFactory(Protocol[_MessageT]):

stdlib/email/feedparser.pyi

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
from collections.abc import Callable
2+
from email._policybase import _MessageT
23
from email.message import Message
34
from email.policy import Policy
4-
from typing import Generic, TypeVar, overload
5+
from typing import Generic, overload
56

67
__all__ = ["FeedParser", "BytesFeedParser"]
78

8-
_MessageT = TypeVar("_MessageT", bound=Message, default=Message)
9-
109
class FeedParser(Generic[_MessageT]):
1110
@overload
1211
def __init__(self: FeedParser[Message], _factory: None = None, *, policy: Policy[Message] = ...) -> None: ...

stdlib/email/generator.pyi

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ from typing_extensions import Self
77
__all__ = ["Generator", "DecodedGenerator", "BytesGenerator"]
88

99
# By default, generators do not have a message policy.
10-
_MessageT = TypeVar("_MessageT", bound=Message, default=Any)
10+
_MessageT = TypeVar("_MessageT", bound=Message[Any, Any], default=Any)
1111

1212
class Generator(Generic[_MessageT]):
1313
maxheaderlen: int | None

stdlib/email/mime/message.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
from email._policybase import _MessageT
12
from email.mime.nonmultipart import MIMENonMultipart
2-
from email.policy import Policy, _MessageT
3+
from email.policy import Policy
34

45
__all__ = ["MIMEMessage"]
56

stdlib/email/mime/multipart.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from collections.abc import Sequence
22
from email import _ParamsType
3+
from email._policybase import _MessageT
34
from email.mime.base import MIMEBase
4-
from email.policy import Policy, _MessageT
5+
from email.policy import Policy
56

67
__all__ = ["MIMEMultipart"]
78

stdlib/email/parser.pyi

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
from _typeshed import SupportsRead
22
from collections.abc import Callable
3+
from email._policybase import _MessageT
34
from email.feedparser import BytesFeedParser as BytesFeedParser, FeedParser as FeedParser
45
from email.message import Message
56
from email.policy import Policy
67
from io import _WrappedBuffer
7-
from typing import Generic, TypeVar, overload
8+
from typing import Generic, overload
89

910
__all__ = ["Parser", "HeaderParser", "BytesParser", "BytesHeaderParser", "FeedParser", "BytesFeedParser"]
1011

11-
_MessageT = TypeVar("_MessageT", bound=Message, default=Message)
12-
1312
class Parser(Generic[_MessageT]):
1413
@overload
15-
def __init__(self: Parser[Message[str, str]], _class: None = None, *, policy: Policy[Message[str, str]] = ...) -> None: ...
14+
def __init__(self: Parser[Message[str, str]], _class: None = None) -> None: ...
1615
@overload
17-
def __init__(self, _class: Callable[[], _MessageT], *, policy: Policy[_MessageT] = ...) -> None: ...
16+
def __init__(self, _class: None = None, *, policy: Policy[_MessageT]) -> None: ...
17+
@overload
18+
def __init__(self, _class: Callable[[], _MessageT] | None, *, policy: Policy[_MessageT] = ...) -> None: ...
1819
def parse(self, fp: SupportsRead[str], headersonly: bool = False) -> _MessageT: ...
1920
def parsestr(self, text: str, headersonly: bool = False) -> _MessageT: ...
2021

@@ -25,9 +26,9 @@ class HeaderParser(Parser[_MessageT]):
2526
class BytesParser(Generic[_MessageT]):
2627
parser: Parser[_MessageT]
2728
@overload
28-
def __init__(
29-
self: BytesParser[Message[str, str]], _class: None = None, *, policy: Policy[Message[str, str]] = ...
30-
) -> None: ...
29+
def __init__(self: BytesParser[Message[str, str]], _class: None = None) -> None: ...
30+
@overload
31+
def __init__(self, _class: None = None, *, policy: Policy[_MessageT]) -> None: ...
3132
@overload
3233
def __init__(self, _class: Callable[[], _MessageT], *, policy: Policy[_MessageT] = ...) -> None: ...
3334
def parse(self, fp: _WrappedBuffer, headersonly: bool = False) -> _MessageT: ...

stdlib/email/policy.pyi

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
from collections.abc import Callable
2-
from email._policybase import Compat32 as Compat32, Policy as Policy, _MessageFactory, compat32 as compat32
2+
from email._policybase import Compat32 as Compat32, Policy as Policy, _MessageFactory, _MessageT, compat32 as compat32
33
from email.contentmanager import ContentManager
4-
from email.message import EmailMessage, Message
5-
from typing import Any, TypeVar, overload
4+
from email.message import EmailMessage
5+
from typing import Any, overload
66
from typing_extensions import Self
77

88
__all__ = ["Compat32", "compat32", "Policy", "EmailPolicy", "default", "strict", "SMTP", "HTTP"]
99

10-
_MessageT = TypeVar("_MessageT", bound=Message, default=Message)
11-
1210
class EmailPolicy(Policy[_MessageT]):
1311
utf8: bool
1412
refold_source: str

stdlib/http/client.pyi

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import sys
55
import types
66
from _typeshed import MaybeNone, ReadableBuffer, SupportsRead, SupportsReadline, WriteableBuffer
77
from collections.abc import Callable, Iterable, Iterator, Mapping
8+
from email._policybase import _MessageT
89
from socket import socket
910
from typing import BinaryIO, Literal, TypeVar, overload
1011
from typing_extensions import Self, TypeAlias
@@ -33,7 +34,6 @@ __all__ = [
3334

3435
_DataType: TypeAlias = SupportsRead[bytes] | Iterable[ReadableBuffer] | ReadableBuffer
3536
_T = TypeVar("_T")
36-
_MessageT = TypeVar("_MessageT", bound=email.message.Message)
3737
_HeaderValue: TypeAlias = ReadableBuffer | str | int
3838

3939
HTTP_PORT: int

stdlib/mailbox.pyi

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import sys
44
from _typeshed import StrPath, SupportsNoArgReadline, SupportsRead
55
from abc import ABCMeta, abstractmethod
66
from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
7+
from email._policybase import _MessageT
78
from types import TracebackType
89
from typing import IO, Any, AnyStr, Generic, Literal, Protocol, TypeVar, overload
910
from typing_extensions import Self, TypeAlias
@@ -32,7 +33,6 @@ __all__ = [
3233
]
3334

3435
_T = TypeVar("_T")
35-
_MessageT = TypeVar("_MessageT", bound=Message)
3636

3737
class _SupportsReadAndReadline(SupportsRead[bytes], SupportsNoArgReadline[bytes], Protocol): ...
3838

0 commit comments

Comments
 (0)