diff --git a/stdlib/@tests/test_cases/builtins/check_dict.py b/stdlib/@tests/test_cases/builtins/check_dict.py index fe74ad49408e..e175f436c567 100644 --- a/stdlib/@tests/test_cases/builtins/check_dict.py +++ b/stdlib/@tests/test_cases/builtins/check_dict.py @@ -1,7 +1,7 @@ from __future__ import annotations import os -from typing import Any, Dict, Generic, Iterable, Mapping, TypeVar, Union +from typing import Any, Dict, Generic, Iterable, Literal, Mapping, TypeVar, Union from typing_extensions import Self, assert_type ################################################################### @@ -103,6 +103,15 @@ def test_iterable_tuple_overload(x: Iterable[tuple[int, str]]) -> dict[int, str] result = d_str.get("key", int_value) # type: ignore[arg-type] +def test_pop_literal(d: dict[Literal["foo", "bar"], int], key: str) -> None: + # Note: annotations also allow using keys of a disjoint type (e.g., int), + # linters / type checkers are free to issue warnings in such cases. + # statically, a .get(arg) is superfluous if the intersection of the + # dict key type and the argument type is empty. + # So we only test a case with non-empty intersection here. + d.pop(key) + + # Return values also make things weird # Pyright doesn't have a version of no-any-return, diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 693dd0b77087..0b730a2b1426 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -1226,11 +1226,11 @@ class dict(MutableMapping[_KT, _VT]): @overload def get(self, key: _KT, default: _T, /) -> _VT | _T: ... @overload - def pop(self, key: _KT, /) -> _VT: ... + def pop(self, key: object, /) -> _VT: ... @overload - def pop(self, key: _KT, default: _VT, /) -> _VT: ... + def pop(self, key: object, default: _VT, /) -> _VT: ... @overload - def pop(self, key: _KT, default: _T, /) -> _VT | _T: ... + def pop(self, key: object, default: _T, /) -> _VT | _T: ... def __len__(self) -> int: ... def __getitem__(self, key: _KT, /) -> _VT: ... def __setitem__(self, key: _KT, value: _VT, /) -> None: ... diff --git a/stdlib/collections/__init__.pyi b/stdlib/collections/__init__.pyi index 8636e6cdbdc3..9920c3c61069 100644 --- a/stdlib/collections/__init__.pyi +++ b/stdlib/collections/__init__.pyi @@ -382,11 +382,11 @@ class OrderedDict(dict[_KT, _VT]): def setdefault(self, key: _KT, default: _VT) -> _VT: ... # Same as dict.pop, but accepts keyword arguments @overload - def pop(self, key: _KT) -> _VT: ... + def pop(self, key: object) -> _VT: ... @overload - def pop(self, key: _KT, default: _VT) -> _VT: ... + def pop(self, key: object, default: _VT) -> _VT: ... @overload - def pop(self, key: _KT, default: _T) -> _VT | _T: ... + def pop(self, key: object, default: _T) -> _VT | _T: ... def __eq__(self, value: object, /) -> bool: ... @overload def __or__(self, value: dict[_KT, _VT], /) -> Self: ... @@ -471,11 +471,11 @@ class ChainMap(MutableMapping[_KT, _VT]): @overload def setdefault(self, key: _KT, default: _VT) -> _VT: ... @overload - def pop(self, key: _KT) -> _VT: ... + def pop(self, key: Any) -> _VT: ... @overload - def pop(self, key: _KT, default: _VT) -> _VT: ... + def pop(self, key: Any, default: _VT) -> _VT: ... @overload - def pop(self, key: _KT, default: _T) -> _VT | _T: ... + def pop(self, key: Any, default: _T) -> _VT | _T: ... def copy(self) -> Self: ... __copy__ = copy # All arguments to `fromkeys` are passed to `dict.fromkeys` at runtime, diff --git a/stdlib/mailbox.pyi b/stdlib/mailbox.pyi index 89bd998b4dfe..7aacfb2ad0b8 100644 --- a/stdlib/mailbox.pyi +++ b/stdlib/mailbox.pyi @@ -88,7 +88,7 @@ class Mailbox(Generic[_MessageT]): def __len__(self) -> int: ... def clear(self) -> None: ... @overload - def pop(self, key: str, default: None = None) -> _MessageT | None: ... + def pop(self, key: str) -> _MessageT | None: ... @overload def pop(self, key: str, default: _T) -> _MessageT | _T: ... def popitem(self) -> tuple[str, _MessageT]: ... diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi index 5521055bdef3..33f7425c7bd8 100644 --- a/stdlib/typing.pyi +++ b/stdlib/typing.pyi @@ -792,11 +792,11 @@ class MutableMapping(Mapping[_KT, _VT]): def __delitem__(self, key: _KT, /) -> None: ... def clear(self) -> None: ... @overload - def pop(self, key: _KT, /) -> _VT: ... + def pop(self, key: Any, /) -> _VT: ... @overload - def pop(self, key: _KT, default: _VT, /) -> _VT: ... + def pop(self, key: Any, default: _VT, /) -> _VT: ... @overload - def pop(self, key: _KT, default: _T, /) -> _VT | _T: ... + def pop(self, key: Any, default: _T, /) -> _VT | _T: ... def popitem(self) -> tuple[_KT, _VT]: ... # This overload should be allowed only if the value type is compatible with None. # diff --git a/stdlib/weakref.pyi b/stdlib/weakref.pyi index 76ab86b957a1..3e2005744453 100644 --- a/stdlib/weakref.pyi +++ b/stdlib/weakref.pyi @@ -112,11 +112,11 @@ class WeakValueDictionary(MutableMapping[_KT, _VT]): def valuerefs(self) -> list[KeyedRef[_KT, _VT]]: ... def setdefault(self, key: _KT, default: _VT) -> _VT: ... @overload - def pop(self, key: _KT) -> _VT: ... + def pop(self, key: object) -> _VT: ... @overload - def pop(self, key: _KT, default: _VT) -> _VT: ... + def pop(self, key: object, default: _VT) -> _VT: ... @overload - def pop(self, key: _KT, default: _T) -> _VT | _T: ... + def pop(self, key: object, default: _T) -> _VT | _T: ... @overload def update(self, other: SupportsKeysAndGetItem[_KT, _VT], /, **kwargs: _VT) -> None: ... @overload @@ -168,11 +168,11 @@ class WeakKeyDictionary(MutableMapping[_KT, _VT]): @overload def setdefault(self, key: _KT, default: _VT) -> _VT: ... @overload - def pop(self, key: _KT) -> _VT: ... + def pop(self, key: object) -> _VT: ... @overload - def pop(self, key: _KT, default: _VT) -> _VT: ... + def pop(self, key: object, default: _VT) -> _VT: ... @overload - def pop(self, key: _KT, default: _T) -> _VT | _T: ... + def pop(self, key: object, default: _T) -> _VT | _T: ... @overload def update(self, dict: SupportsKeysAndGetItem[_KT, _VT], /, **kwargs: _VT) -> None: ... @overload diff --git a/stubs/boltons/boltons/cacheutils.pyi b/stubs/boltons/boltons/cacheutils.pyi index 40e786e61bd8..966e72123d7b 100644 --- a/stubs/boltons/boltons/cacheutils.pyi +++ b/stubs/boltons/boltons/cacheutils.pyi @@ -31,9 +31,9 @@ class LRI(dict[_KT, _VT]): def get(self, key: _KT, default: _T) -> _T | _VT: ... def __delitem__(self, key: _KT) -> None: ... @overload - def pop(self, key: _KT) -> _VT: ... + def pop(self, key: object) -> _VT: ... @overload - def pop(self, key: _KT, default: _T) -> _T | _VT: ... + def pop(self, key: object, default: _T) -> _T | _VT: ... def popitem(self) -> tuple[_KT, _VT]: ... def clear(self) -> None: ... def copy(self) -> Self: ... diff --git a/stubs/boltons/boltons/dictutils.pyi b/stubs/boltons/boltons/dictutils.pyi index 5e609ef9af13..e725160fb806 100644 --- a/stubs/boltons/boltons/dictutils.pyi +++ b/stubs/boltons/boltons/dictutils.pyi @@ -55,7 +55,7 @@ class OneToOne(dict[_KT, _VT]): inv: OneToOne[_VT, _KT] def clear(self) -> None: ... def copy(self) -> Self: ... - def pop(self, key: _KT, default: _VT | _T = ...) -> _VT | _T: ... + def pop(self, key: object, default: _VT | _T = ...) -> _VT | _T: ... def popitem(self) -> tuple[_KT, _VT]: ... def setdefault(self, key: _KT, default: _VT | None = None) -> _VT: ... @classmethod diff --git a/stubs/yt-dlp/yt_dlp/utils/networking.pyi b/stubs/yt-dlp/yt_dlp/utils/networking.pyi index 1d3d18310dd3..fa60f5c66e42 100644 --- a/stubs/yt-dlp/yt_dlp/utils/networking.pyi +++ b/stubs/yt-dlp/yt_dlp/utils/networking.pyi @@ -21,11 +21,11 @@ class HTTPHeaderDict(dict[str, str]): @overload def get(self, key: str, /, default: type[NO_DEFAULT] | _T = ...) -> str | _T | type[NO_DEFAULT]: ... @overload - def pop(self, key: str, /) -> str: ... + def pop(self, key: object, /) -> str: ... @overload - def pop(self, key: str, /, default: _T) -> str | _T: ... + def pop(self, key: object, /, default: _T) -> str | _T: ... @overload - def pop(self, key: str, /, default: type[NO_DEFAULT] | _T | str = ...) -> str | _T | type[NO_DEFAULT]: ... + def pop(self, key: object, /, default: type[NO_DEFAULT] | _T | str = ...) -> str | _T | type[NO_DEFAULT]: ... @overload def setdefault(self, key: str, /) -> str: ... @overload