Skip to content

Commit 7e0faae

Browse files
committed
Add protocols SequenceLike and MappingLike
`Sequence` and `Mapping` are commonly used in argument types. This can be problematic, since they are not protocols, making it impossible to safely duck type or mock them. Also, not all sequence- or mapping-like types derive from these ABCs at runtime, although in typeshed we often pretend they do. Ideally we'd be able to avoid this discrepancy in the far future. Finally, the ABCs sometimes make more API promises than their sub-classes fulfill. For example, `Mapping` arguments are keyword-or-positional, while its most important subtype `dict` only accepts positional arguments. These protocols have tighter guarantees. `SequenceLike` contains most, `MappingLike` all methods from their respective types, making them an easy substitute in argument types.
1 parent 0483be6 commit 7e0faae

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

stdlib/_typeshed/__init__.pyi

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,18 @@
33
# See the README.md file in this directory for more information.
44

55
import sys
6-
from collections.abc import Awaitable, Callable, Iterable, Iterator, Sequence, Set as AbstractSet, Sized
6+
from collections.abc import (
7+
Awaitable,
8+
Callable,
9+
ItemsView,
10+
Iterable,
11+
Iterator,
12+
KeysView,
13+
Sequence,
14+
Set as AbstractSet,
15+
Sized,
16+
ValuesView,
17+
)
718
from dataclasses import Field
819
from os import PathLike
920
from types import FrameType, TracebackType
@@ -179,6 +190,40 @@ class SupportsItemAccess(Protocol[_KT_contra, _VT]):
179190
def __setitem__(self, key: _KT_contra, value: _VT, /) -> None: ...
180191
def __delitem__(self, key: _KT_contra, /) -> None: ...
181192

193+
194+
# Protocol for sequence-like objects. This includes commonly used methods
195+
# from collections.abc.Sequence, and can be used in argument types when using
196+
# more specific protocols would be cumbersome.
197+
#
198+
# Please note that this protocol is not yet marked as stable, and may be
199+
# extended in the future to include more methods.
200+
class SequenceLike(Protocol[_T_co]):
201+
def __contains__(self, value: object, /) -> bool: ...
202+
@overload
203+
def __getitem__(self, index: int, /) -> _T_co: ...
204+
# This does not necessarily return a sequence of the same type.
205+
@overload
206+
def __getitem__(self, index: slice, /) -> Sequence[_T_co]: ...
207+
def __iter__(self) -> Iterator[_T_co]: ...
208+
def __len__(self) -> int: ...
209+
210+
# Protocol for mapping-like objects. This includes the methods from
211+
# collections.abc.Mapping, and can be used in argument types when using
212+
# more specific protocols would be cumbersome.
213+
class MappingLike(Protocol[_KT, _VT_co]):
214+
def __contains__(self, key: object, /) -> bool: ...
215+
def __getitem__(self, key: _KT, /) -> _VT_co: ...
216+
def __len__(self) -> int: ...
217+
@overload
218+
def get(self, key: _KT, /) -> _VT_co | None: ...
219+
@overload
220+
def get(self, key: _KT, default: _VT, /) -> _VT_co | _VT: ...
221+
def items(self) -> ItemsView[_KT, _VT_co]: ...
222+
def keys(self) -> KeysView[_KT]: ...
223+
def values(self) -> ValuesView[_VT_co]: ...
224+
225+
# Path- and I/O-related types
226+
182227
StrPath: TypeAlias = str | PathLike[str] # stable
183228
BytesPath: TypeAlias = bytes | PathLike[bytes] # stable
184229
GenericPath: TypeAlias = AnyStr | PathLike[AnyStr]

0 commit comments

Comments
 (0)