diff --git a/stdlib/email/headerregistry.pyi b/stdlib/email/headerregistry.pyi index 69e7bf315..6a3d6ca5b 100644 --- a/stdlib/email/headerregistry.pyi +++ b/stdlib/email/headerregistry.pyi @@ -1,5 +1,6 @@ import sys import types +from collections.abc import Iterable, Mapping from datetime import datetime as _datetime from email._header_value_parser import ( AddressList, @@ -12,28 +13,33 @@ from email._header_value_parser import ( ) from email.errors import MessageDefect from email.policy import Policy -from typing import Any, Iterable, Tuple, Type +from typing import Any, ClassVar, Tuple, Type +from typing_extensions import Literal class BaseHeader(str): + # max_count is actually more of an abstract ClassVar (not defined on the base class, but expected to be defined in subclasses) + max_count: ClassVar[Literal[1] | None] @property def name(self) -> str: ... @property def defects(self) -> Tuple[MessageDefect, ...]: ... - @property - def max_count(self) -> int | None: ... def __new__(cls, name: str, value: Any) -> BaseHeader: ... def init(self, name: str, *, parse_tree: TokenList, defects: Iterable[MessageDefect]) -> None: ... def fold(self, *, policy: Policy) -> str: ... class UnstructuredHeader: + max_count: ClassVar[Literal[1] | None] @staticmethod def value_parser(value: str) -> UnstructuredTokenList: ... @classmethod def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... -class UniqueUnstructuredHeader(UnstructuredHeader): ... +class UniqueUnstructuredHeader(UnstructuredHeader): + max_count: ClassVar[Literal[1]] class DateHeader: + max_count: ClassVar[Literal[1] | None] + def init(self, name: str, *, parse_tree: TokenList, defects: Iterable[MessageDefect], datetime: _datetime) -> None: ... @property def datetime(self) -> _datetime: ... @staticmethod @@ -41,9 +47,12 @@ class DateHeader: @classmethod def parse(cls, value: str | _datetime, kwds: dict[str, Any]) -> None: ... -class UniqueDateHeader(DateHeader): ... +class UniqueDateHeader(DateHeader): + max_count: ClassVar[Literal[1]] class AddressHeader: + max_count: ClassVar[Literal[1] | None] + def init(self, name: str, *, parse_tree: TokenList, defects: Iterable[MessageDefect], groups: Iterable[Group]) -> None: ... @property def groups(self) -> Tuple[Group, ...]: ... @property @@ -53,15 +62,28 @@ class AddressHeader: @classmethod def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... -class UniqueAddressHeader(AddressHeader): ... +class UniqueAddressHeader(AddressHeader): + max_count: ClassVar[Literal[1]] class SingleAddressHeader(AddressHeader): @property def address(self) -> Address: ... -class UniqueSingleAddressHeader(SingleAddressHeader): ... +class UniqueSingleAddressHeader(SingleAddressHeader): + max_count: ClassVar[Literal[1]] class MIMEVersionHeader: + max_count: ClassVar[Literal[1]] + def init( + self, + name: str, + *, + parse_tree: TokenList, + defects: Iterable[MessageDefect], + version: str | None, + major: int | None, + minor: int | None, + ) -> None: ... @property def version(self) -> str | None: ... @property @@ -74,6 +96,8 @@ class MIMEVersionHeader: def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... class ParameterizedMIMEHeader: + max_count: ClassVar[Literal[1]] + def init(self, name: str, *, parse_tree: TokenList, defects: Iterable[MessageDefect], params: Mapping[str, Any]) -> None: ... @property def params(self) -> types.MappingProxyType[str, Any]: ... @classmethod @@ -90,12 +114,15 @@ class ContentTypeHeader(ParameterizedMIMEHeader): def value_parser(value: str) -> ContentType: ... class ContentDispositionHeader(ParameterizedMIMEHeader): + # init is redefined but has the same signature as parent class, so is omitted from the stub @property - def content_disposition(self) -> str: ... + def content_disposition(self) -> str | None: ... @staticmethod def value_parser(value: str) -> ContentDisposition: ... class ContentTransferEncodingHeader: + max_count: ClassVar[Literal[1]] + def init(self, name: str, *, parse_tree: TokenList, defects: Iterable[MessageDefect]) -> None: ... @property def cte(self) -> str: ... @classmethod @@ -106,6 +133,7 @@ class ContentTransferEncodingHeader: if sys.version_info >= (3, 8): from email._header_value_parser import MessageID class MessageIDHeader: + max_count: ClassVar[Literal[1]] @classmethod def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... @staticmethod diff --git a/tests/stubtest_allowlists/py310.txt b/tests/stubtest_allowlists/py310.txt index abcec51eb..8da3570ba 100644 --- a/tests/stubtest_allowlists/py310.txt +++ b/tests/stubtest_allowlists/py310.txt @@ -153,7 +153,6 @@ distutils.dist.DistributionMetadata.set_classifiers distutils.dist.DistributionMetadata.set_keywords distutils.dist.DistributionMetadata.set_platforms distutils.util.get_host_platform -email.headerregistry.MessageIDHeader.max_count lib2to3.pgen2.tokenize.COLONEQUAL multiprocessing.managers.SharedMemoryServer.create multiprocessing.managers.SharedMemoryServer.list_segments diff --git a/tests/stubtest_allowlists/py38.txt b/tests/stubtest_allowlists/py38.txt index 45deb7ecd..6b5aef577 100644 --- a/tests/stubtest_allowlists/py38.txt +++ b/tests/stubtest_allowlists/py38.txt @@ -133,7 +133,6 @@ dummy_threading.main_thread dummy_threading.setprofile dummy_threading.settrace dummy_threading.stack_size -email.headerregistry.MessageIDHeader.max_count html.parser.HTMLParser.unescape lib2to3.pgen2.tokenize.COLONEQUAL multiprocessing.managers.SharedMemoryServer.create diff --git a/tests/stubtest_allowlists/py39.txt b/tests/stubtest_allowlists/py39.txt index 630414b83..e61cf9e7d 100644 --- a/tests/stubtest_allowlists/py39.txt +++ b/tests/stubtest_allowlists/py39.txt @@ -133,7 +133,6 @@ distutils.dist.DistributionMetadata.set_platforms distutils.sysconfig.expand_makefile_vars distutils.sysconfig.get_python_version distutils.util.get_host_platform -email.headerregistry.MessageIDHeader.max_count hmac.HMAC.digest_cons hmac.HMAC.inner hmac.HMAC.outer diff --git a/tests/stubtest_allowlists/py3_common.txt b/tests/stubtest_allowlists/py3_common.txt index 1333df1a0..d7602a8db 100644 --- a/tests/stubtest_allowlists/py3_common.txt +++ b/tests/stubtest_allowlists/py3_common.txt @@ -82,7 +82,6 @@ difflib.SequenceMatcher.__init__ # mypy default value for generic parameter iss distutils.command.bdist_packager # It exists in docs as package name but not in code except as a mention in a comment. distutils.version.Version._cmp # class should have declared this distutils.version.Version.parse # class should have declared this -email.headerregistry.BaseHeader.max_count # docs say subclasses should have this property # Enum `name` and `value` are special properties that exists at runtime, but stubtest can't detect # https://github.com/python/typeshed/pull/6576#issuecomment-992538677 enum.Enum.name @@ -562,23 +561,6 @@ email.errors email.feedparser email.generator email.header -email.headerregistry.AddressHeader.init -email.headerregistry.AddressHeader.max_count -email.headerregistry.ContentDispositionHeader.init -email.headerregistry.ContentTransferEncodingHeader.init -email.headerregistry.ContentTransferEncodingHeader.max_count -email.headerregistry.ContentTypeHeader.init -email.headerregistry.DateHeader.init -email.headerregistry.DateHeader.max_count -email.headerregistry.MIMEVersionHeader.init -email.headerregistry.MIMEVersionHeader.max_count -email.headerregistry.ParameterizedMIMEHeader.init -email.headerregistry.ParameterizedMIMEHeader.max_count -email.headerregistry.UniqueAddressHeader.max_count -email.headerregistry.UniqueDateHeader.max_count -email.headerregistry.UniqueSingleAddressHeader.max_count -email.headerregistry.UniqueUnstructuredHeader.max_count -email.headerregistry.UnstructuredHeader.max_count email.iterators email.iterators.walk email.message