From 668f9b498db053d977aab226bd89617493dace1e Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 13 Jul 2021 07:20:07 -0700 Subject: [PATCH 1/5] Make Mapping/MutableMapping params positional-only These are positional-only on dict, so it makes sense to mark them as positional-only in these base classes too. Fixes #5771 --- stdlib/typing.pyi | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi index 359a7d4f9e92..dadb1653be89 100644 --- a/stdlib/typing.pyi +++ b/stdlib/typing.pyi @@ -439,29 +439,29 @@ class Mapping(_Collection[_KT], Generic[_KT, _VT_co]): # TODO: We wish the key type could also be covariant, but that doesn't work, # see discussion in https: //github.com/python/typing/pull/273. @abstractmethod - def __getitem__(self, k: _KT) -> _VT_co: ... + def __getitem__(self, __k: _KT) -> _VT_co: ... # Mixin methods @overload - def get(self, key: _KT) -> Optional[_VT_co]: ... + def get(self, __key: _KT) -> Optional[_VT_co]: ... @overload - def get(self, key: _KT, default: Union[_VT_co, _T]) -> Union[_VT_co, _T]: ... + def get(self, __key: _KT, __default: Union[_VT_co, _T]) -> Union[_VT_co, _T]: ... def items(self) -> AbstractSet[Tuple[_KT, _VT_co]]: ... def keys(self) -> AbstractSet[_KT]: ... def values(self) -> ValuesView[_VT_co]: ... - def __contains__(self, o: object) -> bool: ... + def __contains__(self, __o: object) -> bool: ... class MutableMapping(Mapping[_KT, _VT], Generic[_KT, _VT]): @abstractmethod - def __setitem__(self, k: _KT, v: _VT) -> None: ... + def __setitem__(self, __k: _KT, __v: _VT) -> None: ... @abstractmethod - def __delitem__(self, v: _KT) -> None: ... + def __delitem__(self, __v: _KT) -> None: ... def clear(self) -> None: ... @overload - def pop(self, key: _KT) -> _VT: ... + def pop(self, __key: _KT) -> _VT: ... @overload - def pop(self, key: _KT, default: Union[_VT, _T] = ...) -> Union[_VT, _T]: ... + def pop(self, __key: _KT, __default: Union[_VT, _T] = ...) -> Union[_VT, _T]: ... def popitem(self) -> Tuple[_KT, _VT]: ... - def setdefault(self, key: _KT, default: _VT = ...) -> _VT: ... + def setdefault(self, __key: _KT, __default: _VT = ...) -> _VT: ... # 'update' used to take a Union, but using overloading is better. # The second overloaded type here is a bit too general, because # Mapping[Tuple[_KT, _VT], W] is a subclass of Iterable[Tuple[_KT, _VT]], From f78f10bdaf79eacb616c7e84b50842dfb74a190a Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Fri, 16 Jul 2021 19:13:07 -0700 Subject: [PATCH 2/5] fix a few issues --- stdlib/collections/__init__.pyi | 15 ++++++++++----- stdlib/weakref.pyi | 10 ++++++++++ stubs/cachetools/cachetools/cache.pyi | 8 +++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/stdlib/collections/__init__.pyi b/stdlib/collections/__init__.pyi index a625c2b38b1e..52de3f5fb7ae 100644 --- a/stdlib/collections/__init__.pyi +++ b/stdlib/collections/__init__.pyi @@ -54,9 +54,9 @@ class UserDict(MutableMapping[_KT, _VT]): def __delitem__(self, key: _KT) -> None: ... def __iter__(self) -> Iterator[_KT]: ... def __contains__(self, key: object) -> bool: ... - def copy(self: _S) -> _S: ... + def copy(self: Self) -> Self: ... @classmethod - def fromkeys(cls: Type[_S], iterable: Iterable[_KT], value: Optional[_VT] = ...) -> _S: ... + def fromkeys(cls: Type[Self], iterable: Iterable[_KT], value: Optional[_VT] = ...) -> Self: ... class UserList(MutableSequence[_T]): data: List[_T] @@ -219,7 +219,7 @@ class Counter(Dict[_T, int], Generic[_T]): def __init__(self, __mapping: Mapping[_T, int]) -> None: ... @overload def __init__(self, __iterable: Iterable[_T]) -> None: ... - def copy(self: _S) -> _S: ... + def copy(self: Self) -> Self: ... def elements(self) -> Iterator[_T]: ... def most_common(self, n: Optional[int] = ...) -> List[Tuple[_T, int]]: ... @classmethod @@ -264,7 +264,7 @@ class _OrderedDictValuesView(ValuesView[_VT], Reversible[_VT]): class OrderedDict(Dict[_KT, _VT], Reversible[_KT], Generic[_KT, _VT]): def popitem(self, last: bool = ...) -> Tuple[_KT, _VT]: ... def move_to_end(self, key: _KT, last: bool = ...) -> None: ... - def copy(self: _S) -> _S: ... + def copy(self: Self) -> Self: ... def __reversed__(self) -> Iterator[_KT]: ... def keys(self) -> _OrderedDictKeysView[_KT]: ... def items(self) -> _OrderedDictItemsView[_KT, _VT]: ... @@ -290,7 +290,7 @@ class defaultdict(Dict[_KT, _VT], Generic[_KT, _VT]): ) -> None: ... def __missing__(self, key: _KT) -> _VT: ... # TODO __reversed__ - def copy(self: _S) -> _S: ... + def copy(self: Self) -> Self: ... class ChainMap(MutableMapping[_KT, _VT], Generic[_KT, _VT]): maps: List[Mapping[_KT, _VT]] @@ -304,3 +304,8 @@ class ChainMap(MutableMapping[_KT, _VT], Generic[_KT, _VT]): def __iter__(self) -> Iterator[_KT]: ... def __len__(self) -> int: ... def __missing__(self, key: _KT) -> _VT: ... # undocumented + def setdefault(self, key: _KT, default: _VT = ...) -> _VT: ... + @overload + def pop(self, key: _KT) -> _VT: ... + @overload + def pop(self, key: _KT, default: Union[_VT, _T] = ...) -> Union[_VT, _T]: ... diff --git a/stdlib/weakref.pyi b/stdlib/weakref.pyi index a4998ddc4219..a1c0ddf60d21 100644 --- a/stdlib/weakref.pyi +++ b/stdlib/weakref.pyi @@ -58,6 +58,11 @@ class WeakValueDictionary(MutableMapping[_KT, _VT]): def items(self) -> Iterator[Tuple[_KT, _VT]]: ... # type: ignore def itervaluerefs(self) -> Iterator[KeyedRef[_KT, _VT]]: ... def valuerefs(self) -> List[KeyedRef[_KT, _VT]]: ... + def setdefault(self, key: _KT, default: _VT = ...) -> _VT: ... + @overload + def pop(self, key: _KT) -> _VT: ... + @overload + def pop(self, key: _KT, default: Union[_VT, _T] = ...) -> Union[_VT, _T]: ... class KeyedRef(ref[_T], Generic[_KT, _T]): key: _KT @@ -83,6 +88,11 @@ class WeakKeyDictionary(MutableMapping[_KT, _VT]): def values(self) -> Iterator[_VT]: ... # type: ignore def items(self) -> Iterator[Tuple[_KT, _VT]]: ... # type: ignore def keyrefs(self) -> List[ref[_KT]]: ... + def setdefault(self, key: _KT, default: _VT = ...) -> _VT: ... + @overload + def pop(self, key: _KT) -> _VT: ... + @overload + def pop(self, key: _KT, default: Union[_VT, _T] = ...) -> Union[_VT, _T]: ... class finalize: def __init__(self, __obj: object, __func: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... diff --git a/stubs/cachetools/cachetools/cache.pyi b/stubs/cachetools/cachetools/cache.pyi index fe13a5e387d7..5af361ec5081 100644 --- a/stubs/cachetools/cachetools/cache.pyi +++ b/stubs/cachetools/cachetools/cache.pyi @@ -1,9 +1,10 @@ -from typing import Callable, Generic, Iterator, Optional, TypeVar +from typing import overload, Callable, Generic, Iterator, Optional, TypeVar, Union from .abc import DefaultMapping as DefaultMapping _KT = TypeVar("_KT") _VT = TypeVar("_VT") +_T = TypeVar("_T") class Cache(DefaultMapping[_KT, _VT], Generic[_KT, _VT]): def __init__(self, maxsize: float, getsizeof: Optional[Callable[[_VT], float]] = ...) -> None: ... @@ -18,3 +19,8 @@ class Cache(DefaultMapping[_KT, _VT], Generic[_KT, _VT]): def currsize(self) -> float: ... @staticmethod def getsizeof(value: _VT) -> float: ... + def setdefault(self, key: _KT, default: _VT = ...) -> _VT: ... + @overload + def pop(self, key: _KT) -> _VT: ... + @overload + def pop(self, key: _KT, default: Union[_VT, _T] = ...) -> Union[_VT, _T]: ... From 3cfe306e6bd94a73f01c85950c2c8dfe66f4976f Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sun, 7 Nov 2021 15:20:24 -0800 Subject: [PATCH 3/5] merge conflicts are hard --- stdlib/weakref.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/weakref.pyi b/stdlib/weakref.pyi index ba4c073b23dd..dbb6b49f2f2e 100644 --- a/stdlib/weakref.pyi +++ b/stdlib/weakref.pyi @@ -78,7 +78,7 @@ class WeakKeyDictionary(MutableMapping[_KT, _VT]): @overload def pop(self, key: _KT, default: _VT | _T = ...) -> _VT | _T: ... - class finalize: +class finalize: def __init__(self, __obj: object, __func: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... def __call__(self, _: Any = ...) -> Any | None: ... def detach(self) -> tuple[Any, Any, Tuple[Any, ...], dict[str, Any]] | None: ... From c9afd1db2e8747f3ced3559df321611d50d40851 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sun, 7 Nov 2021 15:22:18 -0800 Subject: [PATCH 4/5] PEP 604 --- stdlib/collections/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/collections/__init__.pyi b/stdlib/collections/__init__.pyi index 4991d1b90295..a7f0681c16c2 100644 --- a/stdlib/collections/__init__.pyi +++ b/stdlib/collections/__init__.pyi @@ -294,4 +294,4 @@ class ChainMap(MutableMapping[_KT, _VT], Generic[_KT, _VT]): @overload def pop(self, key: _KT) -> _VT: ... @overload - def pop(self, key: _KT, default: Union[_VT, _T] = ...) -> Union[_VT, _T]: ... + def pop(self, key: _KT, default: _VT | _T = ...) -> _VT | _T: ... From 2fbb627794442d618e272f4dca91c564eea2ac96 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Wed, 17 Nov 2021 22:11:20 -0800 Subject: [PATCH 5/5] add to stubtest allowlist --- tests/stubtest_allowlists/py310.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/stubtest_allowlists/py310.txt b/tests/stubtest_allowlists/py310.txt index 59478e1c2ad8..9fd59b843b7f 100644 --- a/tests/stubtest_allowlists/py310.txt +++ b/tests/stubtest_allowlists/py310.txt @@ -13,6 +13,16 @@ _collections_abc.Generator.throw _collections_abc.ItemsView.__reversed__ _collections_abc.KeysView.__reversed__ _collections_abc.ValuesView.__reversed__ + +# These are not positional-only at runtime, but we treat them +# as positional-only to match dict. +_collections_abc.Mapping.__getitem__ +_collections_abc.Mapping.__contains__ +_collections_abc.MutableMapping.__delitem__ +_collections_abc.MutableMapping.__setitem__ +_collections_abc.MutableMapping.pop +_collections_abc.MutableMapping.setdefault + _dummy_thread ast.Bytes.__new__ ast.Ellipsis.__new__