From 1840a0ac2b60c18e69c02b0ecdf12057e4fd57a8 Mon Sep 17 00:00:00 2001 From: Gatsik <74517072+Gatsik@users.noreply.github.com> Date: Wed, 13 Aug 2025 21:17:40 +0300 Subject: [PATCH 1/2] Add Protocols for mapping inside dictionary view objects --- stdlib/_typeshed/__init__.pyi | 4 ++++ stdlib/typing.pyi | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/stdlib/_typeshed/__init__.pyi b/stdlib/_typeshed/__init__.pyi index 98a369dfc589..02be66667a49 100644 --- a/stdlib/_typeshed/__init__.pyi +++ b/stdlib/_typeshed/__init__.pyi @@ -377,3 +377,7 @@ if sys.version_info >= (3, 14): # These return annotations, which can be arbitrary objects AnnotateFunc: TypeAlias = Callable[[Format], dict[str, AnnotationForm]] EvaluateFunc: TypeAlias = Callable[[Format], AnnotationForm] + +# Suitable for dictionary view objects +class Viewable(Sized, Iterable[_KT_co], Protocol): ... +class SupportsGetItemViewable(Viewable[_KT], SupportsGetItem[_KT, _VT_co], Protocol): ... diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi index cf81d7728fa9..ac64b7953088 100644 --- a/stdlib/typing.pyi +++ b/stdlib/typing.pyi @@ -5,7 +5,7 @@ import collections # noqa: F401 # pyright: ignore[reportUnusedImport] import sys import typing_extensions from _collections_abc import dict_items, dict_keys, dict_values -from _typeshed import IdentityFunction, ReadableBuffer, SupportsKeysAndGetItem +from _typeshed import IdentityFunction, ReadableBuffer, SupportsGetItemViewable, SupportsKeysAndGetItem, Viewable from abc import ABCMeta, abstractmethod from re import Match as Match, Pattern as Pattern from types import ( @@ -703,11 +703,11 @@ class MutableSet(AbstractSet[_T]): def __isub__(self, it: AbstractSet[Any]) -> typing_extensions.Self: ... class MappingView(Sized): - def __init__(self, mapping: Mapping[Any, Any]) -> None: ... # undocumented + def __init__(self, mapping: Sized) -> None: ... # undocumented def __len__(self) -> int: ... class ItemsView(MappingView, AbstractSet[tuple[_KT_co, _VT_co]], Generic[_KT_co, _VT_co]): - def __init__(self, mapping: Mapping[_KT_co, _VT_co]) -> None: ... # undocumented + def __init__(self, mapping: SupportsGetItemViewable[_KT_co, _VT_co]) -> None: ... # undocumented def __and__(self, other: Iterable[Any]) -> set[tuple[_KT_co, _VT_co]]: ... def __rand__(self, other: Iterable[_T]) -> set[_T]: ... def __contains__(self, item: object) -> bool: ... @@ -720,7 +720,7 @@ class ItemsView(MappingView, AbstractSet[tuple[_KT_co, _VT_co]], Generic[_KT_co, def __rxor__(self, other: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... class KeysView(MappingView, AbstractSet[_KT_co]): - def __init__(self, mapping: Mapping[_KT_co, Any]) -> None: ... # undocumented + def __init__(self, mapping: Viewable[_KT_co]) -> None: ... # undocumented def __and__(self, other: Iterable[Any]) -> set[_KT_co]: ... def __rand__(self, other: Iterable[_T]) -> set[_T]: ... def __contains__(self, key: object) -> bool: ... @@ -733,7 +733,7 @@ class KeysView(MappingView, AbstractSet[_KT_co]): def __rxor__(self, other: Iterable[_T]) -> set[_KT_co | _T]: ... class ValuesView(MappingView, Collection[_VT_co]): - def __init__(self, mapping: Mapping[Any, _VT_co]) -> None: ... # undocumented + def __init__(self, mapping: SupportsGetItemViewable[Any, _VT_co]) -> None: ... # undocumented def __contains__(self, value: object) -> bool: ... def __iter__(self) -> Iterator[_VT_co]: ... From 1a23f64335df0f21293d6cc3df2027b24183a42b Mon Sep 17 00:00:00 2001 From: Gatsik <74517072+Gatsik@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:14:29 +0300 Subject: [PATCH 2/2] Avoid inheritance and explicitly define protocol methods --- stdlib/_typeshed/__init__.pyi | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/stdlib/_typeshed/__init__.pyi b/stdlib/_typeshed/__init__.pyi index 02be66667a49..2cfd8173afd1 100644 --- a/stdlib/_typeshed/__init__.pyi +++ b/stdlib/_typeshed/__init__.pyi @@ -3,7 +3,7 @@ # See the README.md file in this directory for more information. import sys -from collections.abc import Awaitable, Callable, Iterable, Sequence, Set as AbstractSet, Sized +from collections.abc import Awaitable, Callable, Iterable, Iterator, Sequence, Set as AbstractSet, Sized from dataclasses import Field from os import PathLike from types import FrameType, TracebackType @@ -275,6 +275,16 @@ class SupportsWrite(Protocol[_T_contra]): class SupportsFlush(Protocol): def flush(self) -> object: ... +# Suitable for dictionary view objects +class Viewable(Protocol[_T_co]): + def __len__(self) -> int: ... + def __iter__(self) -> Iterator[_T_co]: ... + +class SupportsGetItemViewable(Protocol[_KT, _VT_co]): + def __len__(self) -> int: ... + def __iter__(self) -> Iterator[_KT]: ... + def __getitem__(self, key: _KT, /) -> _VT_co: ... + # Unfortunately PEP 688 does not allow us to distinguish read-only # from writable buffers. We use these aliases for readability for now. # Perhaps a future extension of the buffer protocol will allow us to @@ -377,7 +387,3 @@ if sys.version_info >= (3, 14): # These return annotations, which can be arbitrary objects AnnotateFunc: TypeAlias = Callable[[Format], dict[str, AnnotationForm]] EvaluateFunc: TypeAlias = Callable[[Format], AnnotationForm] - -# Suitable for dictionary view objects -class Viewable(Sized, Iterable[_KT_co], Protocol): ... -class SupportsGetItemViewable(Viewable[_KT], SupportsGetItem[_KT, _VT_co], Protocol): ...