Fix variance of a few email-related classes (#13952)

Closes #13919
This commit is contained in:
Sebastian Rittau
2025-05-12 16:12:32 -07:00
committed by GitHub
parent 41b2f9e7b4
commit e224b28f32
4 changed files with 35 additions and 28 deletions
+19 -19
View File
@@ -12,12 +12,12 @@ __all__ = ["Message", "EmailMessage"]
_T = TypeVar("_T")
# Type returned by Policy.header_fetch_parse, often str or Header.
_HeaderT = TypeVar("_HeaderT", default=str)
_HeaderParamT = TypeVar("_HeaderParamT", default=str)
_HeaderT_co = TypeVar("_HeaderT_co", covariant=True, default=str)
_HeaderParamT_contra = TypeVar("_HeaderParamT_contra", contravariant=True, default=str)
# Represents headers constructed by HeaderRegistry. Those are sub-classes
# of BaseHeader and another header type.
_HeaderRegistryT = TypeVar("_HeaderRegistryT", default=Any)
_HeaderRegistryParamT = TypeVar("_HeaderRegistryParamT", default=Any)
_HeaderRegistryT_co = TypeVar("_HeaderRegistryT_co", covariant=True, default=Any)
_HeaderRegistryParamT_contra = TypeVar("_HeaderRegistryParamT_contra", contravariant=True, default=Any)
_PayloadType: TypeAlias = Message | str
_EncodedPayloadType: TypeAlias = Message | bytes
@@ -30,7 +30,7 @@ class _SupportsEncodeToPayload(Protocol):
class _SupportsDecodeToPayload(Protocol):
def decode(self, encoding: str, errors: str, /) -> _PayloadType | _MultipartPayloadType: ...
class Message(Generic[_HeaderT, _HeaderParamT]):
class Message(Generic[_HeaderT_co, _HeaderParamT_contra]):
# The policy attributes and arguments in this class and its subclasses
# would ideally use Policy[Self], but this is not possible.
policy: Policy[Any] # undocumented
@@ -76,22 +76,22 @@ class Message(Generic[_HeaderT, _HeaderParamT]):
# This is important for protocols using __getitem__, like SupportsKeysAndGetItem
# Morally, the return type should be `AnyOf[_HeaderType, None]`,
# so using "the Any trick" instead.
def __getitem__(self, name: str) -> _HeaderT | MaybeNone: ...
def __setitem__(self, name: str, val: _HeaderParamT) -> None: ...
def __getitem__(self, name: str) -> _HeaderT_co | MaybeNone: ...
def __setitem__(self, name: str, val: _HeaderParamT_contra) -> None: ...
def __delitem__(self, name: str) -> None: ...
def keys(self) -> list[str]: ...
def values(self) -> list[_HeaderT]: ...
def items(self) -> list[tuple[str, _HeaderT]]: ...
def values(self) -> list[_HeaderT_co]: ...
def items(self) -> list[tuple[str, _HeaderT_co]]: ...
@overload
def get(self, name: str, failobj: None = None) -> _HeaderT | None: ...
def get(self, name: str, failobj: None = None) -> _HeaderT_co | None: ...
@overload
def get(self, name: str, failobj: _T) -> _HeaderT | _T: ...
def get(self, name: str, failobj: _T) -> _HeaderT_co | _T: ...
@overload
def get_all(self, name: str, failobj: None = None) -> list[_HeaderT] | None: ...
def get_all(self, name: str, failobj: None = None) -> list[_HeaderT_co] | None: ...
@overload
def get_all(self, name: str, failobj: _T) -> list[_HeaderT] | _T: ...
def get_all(self, name: str, failobj: _T) -> list[_HeaderT_co] | _T: ...
def add_header(self, _name: str, _value: str, **_params: _ParamsType) -> None: ...
def replace_header(self, _name: str, _value: _HeaderParamT) -> None: ...
def replace_header(self, _name: str, _value: _HeaderParamT_contra) -> None: ...
def get_content_type(self) -> str: ...
def get_content_maintype(self) -> str: ...
def get_content_subtype(self) -> str: ...
@@ -144,18 +144,18 @@ class Message(Generic[_HeaderT, _HeaderParamT]):
replace: bool = False,
) -> None: ...
# The following two methods are undocumented, but a source code comment states that they are public API
def set_raw(self, name: str, value: _HeaderParamT) -> None: ...
def raw_items(self) -> Iterator[tuple[str, _HeaderT]]: ...
def set_raw(self, name: str, value: _HeaderParamT_contra) -> None: ...
def raw_items(self) -> Iterator[tuple[str, _HeaderT_co]]: ...
class MIMEPart(Message[_HeaderRegistryT, _HeaderRegistryParamT]):
class MIMEPart(Message[_HeaderRegistryT_co, _HeaderRegistryParamT_contra]):
def __init__(self, policy: Policy[Any] | None = None) -> None: ...
def get_body(self, preferencelist: Sequence[str] = ("related", "html", "plain")) -> MIMEPart[_HeaderRegistryT] | None: ...
def get_body(self, preferencelist: Sequence[str] = ("related", "html", "plain")) -> MIMEPart[_HeaderRegistryT_co] | None: ...
def attach(self, payload: Self) -> None: ... # type: ignore[override]
# The attachments are created via type(self) in the attach method. It's theoretically
# possible to sneak other attachment types into a MIMEPart instance, but could cause
# cause unforseen consequences.
def iter_attachments(self) -> Iterator[Self]: ...
def iter_parts(self) -> Iterator[MIMEPart[_HeaderRegistryT]]: ...
def iter_parts(self) -> Iterator[MIMEPart[_HeaderRegistryT_co]]: ...
def get_content(self, *args: Any, content_manager: ContentManager | None = None, **kw: Any) -> Any: ...
def set_content(self, *args: Any, content_manager: ContentManager | None = None, **kw: Any) -> None: ...
def make_related(self, boundary: str | None = None) -> None: ...