Skip to content
11 changes: 10 additions & 1 deletion stdlib/@tests/test_cases/builtins/check_dict.py
Original file line number Diff line number Diff line change
@@ -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

###################################################################
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions stdlib/builtins.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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: ...
Expand Down
12 changes: 6 additions & 6 deletions stdlib/collections/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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: ...
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion stdlib/mailbox.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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]: ...
Expand Down
6 changes: 3 additions & 3 deletions stdlib/typing.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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.
#
Expand Down
12 changes: 6 additions & 6 deletions stdlib/weakref.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions stubs/boltons/boltons/cacheutils.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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: ...
Expand Down
2 changes: 1 addition & 1 deletion stubs/boltons/boltons/dictutils.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions stubs/yt-dlp/yt_dlp/utils/networking.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down