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
14 changes: 14 additions & 0 deletions stdlib/@tests/test_cases/builtins/check_frozendict-py315.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,17 @@
assert_type(frozendict({"x": 1}), frozendict[str, int])
assert_type(frozendict([("k", 2)]), frozendict[str, int])
assert_type(frozendict({"x": 1}, y=2), frozendict[str, int])

# gh-16668: like ``Mapping``, ``frozendict`` is covariant in its value type
# (but not in its key type).
def takes_optional_values(d: frozendict[str, int | None]) -> None: ...

int_values: frozendict[str, int] = frozendict(a=1)
takes_optional_values(int_values)
assert_type(int_values.get("a"), int | None)
assert_type(int_values.get("a", 0), int)
assert_type(int_values.get("a", "x"), int | str)

def takes_object_keys(d: frozendict[object, int]) -> None: ...

takes_object_keys(int_values) # type: ignore
25 changes: 13 additions & 12 deletions stdlib/builtins.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ _T_contra = TypeVar("_T_contra", contravariant=True)
_R_co = TypeVar("_R_co", covariant=True)
_KT = TypeVar("_KT")
_VT = TypeVar("_VT")
_VT_co = TypeVar("_VT_co", covariant=True)
_S = TypeVar("_S")
_T1 = TypeVar("_T1")
_T2 = TypeVar("_T2")
Expand Down Expand Up @@ -1378,7 +1379,7 @@ class dict(MutableMapping[_KT, _VT]):

if sys.version_info >= (3, 15):
@disjoint_base
class frozendict(Mapping[_KT, _VT]):
class frozendict(Mapping[_KT, _VT_co]):
@overload
def __new__(cls, /) -> frozendict[Any, Any]: ...
@overload
Expand All @@ -1396,7 +1397,7 @@ if sys.version_info >= (3, 15):
cls: type[frozendict[str, _VT]], iterable: Iterable[tuple[str, _VT]], /, **kwargs: _VT
) -> frozendict[str, _VT]: ...

def copy(self) -> frozendict[_KT, _VT]: ...
def copy(self) -> frozendict[_KT, _VT_co]: ...

@overload
@classmethod
Expand All @@ -1406,27 +1407,27 @@ if sys.version_info >= (3, 15):
def fromkeys(cls, iterable: Iterable[_T], value: _S, /) -> frozendict[_T, _S]: ...

@overload # type: ignore[override]
def get(self, key: _KT, default: None = None, /) -> _VT | None: ...
def get(self, key: _KT, default: None = None, /) -> _VT_co | None: ...
@overload
def get(self, key: _KT, default: _VT, /) -> _VT: ...
def get(self, key: _KT, default: _VT_co, /) -> _VT_co: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] # Covariant type as parameter # pyrefly: ignore [invalid-variance]
@overload
def get(self, key: _KT, default: _T, /) -> _VT | _T: ...
def get(self, key: _KT, default: _T, /) -> _VT_co | _T: ...

def keys(self) -> dict_keys[_KT, _VT]: ...
def values(self) -> dict_values[_KT, _VT]: ...
def items(self) -> dict_items[_KT, _VT]: ...
def keys(self) -> dict_keys[_KT, _VT_co]: ...
def values(self) -> dict_values[_KT, _VT_co]: ...
def items(self) -> dict_items[_KT, _VT_co]: ...
def __len__(self) -> int: ...
def __getitem__(self, key: _KT, /) -> _VT: ...
def __getitem__(self, key: _KT, /) -> _VT_co: ...
def __reversed__(self) -> Iterator[_KT]: ...
def __iter__(self) -> Iterator[_KT]: ...
def __hash__(self) -> int: ...
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
def __or__(self, value: dict[_T1, _T2] | frozendict[_T1, _T2], /) -> frozendict[_KT | _T1, _VT | _T2]: ...
def __or__(self, value: dict[_T1, _T2] | frozendict[_T1, _T2], /) -> frozendict[_KT | _T1, _VT_co | _T2]: ...

@overload
def __ror__(self, value: dict[_T1, _T2], /) -> dict[_KT | _T1, _VT | _T2]: ...
def __ror__(self, value: dict[_T1, _T2], /) -> dict[_KT | _T1, _VT_co | _T2]: ...
@overload
def __ror__(self, value: frozendict[_T1, _T2], /) -> frozendict[_KT | _T1, _VT | _T2]: ...
def __ror__(self, value: frozendict[_T1, _T2], /) -> frozendict[_KT | _T1, _VT_co | _T2]: ...

@disjoint_base
class set(MutableSet[_T]):
Expand Down
Loading