Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
8 changes: 5 additions & 3 deletions stdlib/builtins.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -1225,12 +1225,14 @@ class dict(MutableMapping[_KT, _VT]):
def get(self, key: _KT, default: _VT, /) -> _VT: ...
@overload
def get(self, key: _KT, default: _T, /) -> _VT | _T: ...
# dict.pop allows arbitrary types, which matches runtime semantics.
# linters may choose to warn if the given type does not overlap with the key type
@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
8 changes: 5 additions & 3 deletions stdlib/typing.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -794,12 +794,14 @@ class MutableMapping(Mapping[_KT, _VT]):
@abstractmethod
def __delitem__(self, key: _KT, /) -> None: ...
def clear(self) -> None: ...
# We annotate this with `Any` rather than `object` as in dict.pop, since
# specific implementations of `MutableMapping` may wish to restrict the type.
@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
Loading