Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
1bbd09d
Update type hints to use Hashable for sets
jonathandung May 11, 2026
4b2f6f9
commit 2
jonathandung May 11, 2026
cb767b6
commit 3
jonathandung May 11, 2026
4488840
commit 4
jonathandung May 11, 2026
c4fced3
commit 5
jonathandung May 11, 2026
e195167
commit 6
jonathandung May 12, 2026
0677026
commit 7
jonathandung May 12, 2026
59dc076
commit 8
jonathandung May 17, 2026
d1d1816
commit 9
jonathandung May 17, 2026
672c349
commit 10
jonathandung May 17, 2026
0bcfb0c
commit 11
jonathandung May 17, 2026
61884f0
commit 12
jonathandung May 17, 2026
e21ad77
commit 13
jonathandung May 17, 2026
f6d11b8
commit 14
jonathandung May 17, 2026
5b73d71
commit 15
jonathandung May 17, 2026
6a22c20
commit 16
jonathandung May 17, 2026
29376a9
commit 17
jonathandung May 17, 2026
852f3fa
commit 18
jonathandung May 17, 2026
d77eb3a
commit 19
jonathandung May 17, 2026
fd6231b
Merge branch 'main' into patch-2
jonathandung May 18, 2026
197295b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 18, 2026
fb30879
commit 22
jonathandung May 18, 2026
031b650
commit 23
jonathandung May 18, 2026
5b1e83e
commit
jonathandung May 18, 2026
9bfb3c0
commit 25
jonathandung May 18, 2026
034baa9
commit 26
jonathandung May 18, 2026
412b7ab
Merge branch 'main' into patch-2
jonathandung May 18, 2026
0942b55
Merge branch 'python:main' into patch-2
jonathandung May 22, 2026
df184dc
commit 29
jonathandung Jun 3, 2026
826a840
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 3, 2026
e27f4e6
commit 30
jonathandung Jun 3, 2026
f3db3b5
Merge branch 'main' into patch-2
jonathandung Jun 3, 2026
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
6 changes: 3 additions & 3 deletions stdlib/_collections_abc.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ if sys.version_info < (3, 15):
if sys.version_info >= (3, 12):
__all__ += ["Buffer"]

_KT_co = TypeVar("_KT_co", covariant=True) # Key type covariant containers.
_KT_co = TypeVar("_KT_co", bound=Hashable, covariant=True) # Key type covariant containers.
_VT_co = TypeVar("_VT_co", covariant=True) # Value type covariant containers.

@final
Expand All @@ -75,7 +75,7 @@ class dict_keys(KeysView[_KT_co], Generic[_KT_co, _VT_co]): # undocumented
def __reversed__(self) -> Iterator[_KT_co]: ...
__hash__: ClassVar[None] # type: ignore[assignment]
if sys.version_info >= (3, 13):
def isdisjoint(self, other: Iterable[_KT_co], /) -> bool: ...
def isdisjoint(self, other: Iterable[Hashable], /) -> bool: ...

@property
def mapping(self) -> MappingProxyType[_KT_co, _VT_co]: ...
Expand All @@ -92,7 +92,7 @@ class dict_items(ItemsView[_KT_co, _VT_co]): # undocumented
def __reversed__(self) -> Iterator[tuple[_KT_co, _VT_co]]: ...
__hash__: ClassVar[None] # type: ignore[assignment]
if sys.version_info >= (3, 13):
def isdisjoint(self, other: Iterable[tuple[_KT_co, _VT_co]], /) -> bool: ...
def isdisjoint(self, other: Iterable[Hashable], /) -> bool: ...

@property
def mapping(self) -> MappingProxyType[_KT_co, _VT_co]: ...
Expand Down
4 changes: 2 additions & 2 deletions stdlib/_decimal.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ if sys.version_info >= (3, 11):
Emax: int | None = None,
capitals: int | None = None,
clamp: int | None = None,
traps: dict[_TrapType, bool] | None = None,
flags: dict[_TrapType, bool] | None = None,
traps: dict[_TrapType, bool] | None = None, # type: ignore[type-var]
flags: dict[_TrapType, bool] | None = None, # type: ignore[type-var]
) -> _ContextManager: ...

else:
Expand Down
4 changes: 4 additions & 0 deletions stdlib/_typeshed/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,13 @@ OpenBinaryMode: TypeAlias = OpenBinaryModeUpdating | OpenBinaryModeReading | Ope
class HasFileno(Protocol):
def fileno(self) -> int: ...

class HasFilenoAndHash(HasFileno, Protocol):
def __hash__(self) -> int: ...

FileDescriptor: TypeAlias = int # stable
FileDescriptorLike: TypeAlias = int | HasFileno # stable
FileDescriptorOrPath: TypeAlias = int | StrOrBytesPath
HashableFDLike: TypeAlias = int | HasFilenoAndHash

# stable
class SupportsRead(Protocol[_T_co]):
Expand Down
14 changes: 7 additions & 7 deletions stdlib/_weakrefset.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,18 @@ class WeakSet(MutableSet[_T]):
def __and__(self, other: Iterable[Any]) -> Self: ...
def intersection_update(self, other: Iterable[Any]) -> None: ...
def __iand__(self, other: Iterable[Any]) -> Self: ...
def issubset(self, other: Iterable[_T]) -> bool: ...
def __le__(self, other: Iterable[_T]) -> bool: ...
def __lt__(self, other: Iterable[_T]) -> bool: ...
def issuperset(self, other: Iterable[_T]) -> bool: ...
def __ge__(self, other: Iterable[_T]) -> bool: ...
def __gt__(self, other: Iterable[_T]) -> bool: ...
def issubset(self, other: Iterable[Any]) -> bool: ...
def __le__(self, other: Iterable[Any]) -> bool: ...
def __lt__(self, other: Iterable[Any]) -> bool: ...
def issuperset(self, other: Iterable[Any]) -> bool: ...
def __ge__(self, other: Iterable[Any]) -> bool: ...
def __gt__(self, other: Iterable[Any]) -> bool: ...
def __eq__(self, other: object) -> bool: ...
def symmetric_difference(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ...
def __xor__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ...
def symmetric_difference_update(self, other: Iterable[_T]) -> None: ...
def __ixor__(self, other: Iterable[_T]) -> Self: ... # type: ignore[override,misc]
def union(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ...
def __or__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ...
def isdisjoint(self, other: Iterable[_T]) -> bool: ...
def isdisjoint(self, other: Iterable[Any]) -> bool: ...
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
132 changes: 68 additions & 64 deletions stdlib/builtins.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ from _typeshed import (
SupportsRichComparisonT,
SupportsWrite,
)
from collections.abc import Awaitable, Callable, Iterable, Iterator, MutableSet, Reversible, Set as AbstractSet, Sized
from collections.abc import Awaitable, Callable, Hashable, Iterable, Iterator, MutableSet, Reversible, Set as AbstractSet, Sized
from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper
from os import PathLike
from types import CellType, CodeType, EllipsisType, GenericAlias, NotImplementedType, TracebackType
Expand Down Expand Up @@ -75,14 +75,18 @@ _I = TypeVar("_I", default=int)
_T_co = TypeVar("_T_co", covariant=True)
_T_contra = TypeVar("_T_contra", contravariant=True)
_R_co = TypeVar("_R_co", covariant=True)
_KT = TypeVar("_KT")
_KT = TypeVar("_KT", bound=Hashable)
_VT = TypeVar("_VT")
_S = TypeVar("_S")
_T1 = TypeVar("_T1")
_T2 = TypeVar("_T2")
_T3 = TypeVar("_T3")
_T4 = TypeVar("_T4")
_T5 = TypeVar("_T5")
_H1 = TypeVar("_H1", bound=Hashable)
_H2 = TypeVar("_H2", bound=Hashable)
_H1_co = TypeVar("_H1_co", bound=Hashable, covariant=True)

_SupportsNextT_co = TypeVar("_SupportsNextT_co", bound=SupportsNext[Any], covariant=True)
_SupportsAnextT_co = TypeVar("_SupportsAnextT_co", bound=SupportsAnext[Any], covariant=True)
_AwaitableT = TypeVar("_AwaitableT", bound=Awaitable[Any])
Expand Down Expand Up @@ -1323,10 +1327,10 @@ class dict(MutableMapping[_KT, _VT]):
# See #3800 & https://github.com/python/typing/issues/548#issuecomment-683336963.
@classmethod
@overload
def fromkeys(cls, iterable: Iterable[_T], value: None = None, /) -> dict[_T, Any | None]: ...
def fromkeys(cls, iterable: Iterable[_H1], value: None = None, /) -> dict[_H1, Any | None]: ...
@classmethod
@overload
def fromkeys(cls, iterable: Iterable[_T], value: _S, /) -> dict[_T, _S]: ...
def fromkeys(cls, iterable: Iterable[_H1], value: _T, /) -> dict[_H1, _T]: ...

# Positional-only in dict, but not in MutableMapping
@overload # type: ignore[override]
Expand All @@ -1353,15 +1357,15 @@ class dict(MutableMapping[_KT, _VT]):
__hash__: ClassVar[None] # type: ignore[assignment]
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
if sys.version_info >= (3, 15):
def __or__(self, value: dict[_T1, _T2] | frozendict[_T1, _T2], /) -> dict[_KT | _T1, _VT | _T2]: ...
def __or__(self, value: dict[_H1, _T] | frozendict[_H1, _T], /) -> dict[_KT | _H1, _VT | _T]: ...

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

# dict.__ior__ should be kept roughly in line with MutableMapping.update()
@overload # type: ignore[misc]
Expand All @@ -1373,7 +1377,7 @@ if sys.version_info >= (3, 15):
@disjoint_base
class frozendict(Mapping[_KT, _VT]):
@overload
def __new__(cls, /) -> frozendict[Any, Any]: ...
def __new__(cls, /) -> frozendict[Hashable, Any]: ...
@overload
def __new__(cls: type[frozendict[str, _VT]], /, **kwargs: _VT) -> frozendict[str, _VT]: ...
@overload
Expand All @@ -1394,10 +1398,10 @@ if sys.version_info >= (3, 15):

@overload
@classmethod
def fromkeys(cls, iterable: Iterable[_T], value: None = None, /) -> frozendict[_T, Any | None]: ...
def fromkeys(cls, iterable: Iterable[_H1], value: None = None, /) -> frozendict[_H1, Any | None]: ...
@overload
@classmethod
def fromkeys(cls, iterable: Iterable[_T], value: _S, /) -> frozendict[_T, _S]: ...
def fromkeys(cls, iterable: Iterable[_H1], value: _T, /) -> frozendict[_H1, _T]: ...

@overload # type: ignore[override]
def get(self, key: _KT, default: None = None, /) -> _VT | None: ...
Expand All @@ -1423,72 +1427,72 @@ if sys.version_info >= (3, 15):
def __ror__(self, value: frozendict[_T1, _T2], /) -> frozendict[_KT | _T1, _VT | _T2]: ...

@disjoint_base
class set(MutableSet[_T]):
class set(MutableSet[_H1]):
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, iterable: Iterable[_T], /) -> None: ...

def add(self, element: _T, /) -> None: ...
def copy(self) -> set[_T]: ...
def difference(self, *s: Iterable[object]) -> set[_T]: ...
def difference_update(self, *s: Iterable[object]) -> None: ...
def discard(self, element: object, /) -> None: ...
def intersection(self, *s: Iterable[object]) -> set[_T]: ...
def intersection_update(self, *s: Iterable[object]) -> None: ...
def isdisjoint(self, s: Iterable[object], /) -> bool: ...
def issubset(self, s: Iterable[object], /) -> bool: ...
def issuperset(self, s: Iterable[object], /) -> bool: ...
def remove(self, element: _T, /) -> None: ...
def symmetric_difference(self, s: Iterable[_S], /) -> set[_T | _S]: ...
def symmetric_difference_update(self, s: Iterable[_T], /) -> None: ...
def union(self, *s: Iterable[_S]) -> set[_T | _S]: ...
def update(self, *s: Iterable[_T]) -> None: ...
def __init__(self, iterable: Iterable[_H1], /) -> None: ...

def add(self, element: _H1, /) -> None: ...
def copy(self) -> set[_H1]: ...
def difference(self, *s: Iterable[Hashable]) -> set[_H1]: ...
def difference_update(self, *s: Iterable[Hashable]) -> None: ...
def discard(self, element: Hashable, /) -> None: ...
def intersection(self, *s: Iterable[Hashable]) -> set[_H1]: ...
def intersection_update(self, *s: Iterable[Hashable]) -> None: ...
def isdisjoint(self, s: Iterable[Hashable], /) -> bool: ...
def issubset(self, s: Iterable[Hashable], /) -> bool: ...
def issuperset(self, s: Iterable[Hashable], /) -> bool: ...
def remove(self, element: _H1, /) -> None: ...
def symmetric_difference(self, s: Iterable[_H2], /) -> set[_H1 | _H2]: ...
def symmetric_difference_update(self, s: Iterable[_H1], /) -> None: ...
def union(self, *s: Iterable[_H2]) -> set[_H1 | _H2]: ...
def update(self, *s: Iterable[_H1]) -> None: ...
def __len__(self) -> int: ...
def __contains__(self, o: object, /) -> bool: ...
def __iter__(self) -> Iterator[_T]: ...
def __and__(self, value: AbstractSet[object], /) -> set[_T]: ...
def __iand__(self, value: AbstractSet[object], /) -> Self: ...
def __or__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ...
def __ior__(self, value: AbstractSet[_T], /) -> Self: ... # type: ignore[override,misc]
def __sub__(self, value: AbstractSet[object], /) -> set[_T]: ...
def __isub__(self, value: AbstractSet[object], /) -> Self: ...
def __xor__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ...
def __ixor__(self, value: AbstractSet[_T], /) -> Self: ... # type: ignore[override,misc]
def __le__(self, value: AbstractSet[object], /) -> bool: ...
def __lt__(self, value: AbstractSet[object], /) -> bool: ...
def __ge__(self, value: AbstractSet[object], /) -> bool: ...
def __gt__(self, value: AbstractSet[object], /) -> bool: ...
def __contains__(self, o: Hashable, /) -> bool: ...
def __iter__(self) -> Iterator[_H1]: ...
def __and__(self, value: AbstractSet[Hashable], /) -> set[_H1]: ...
def __iand__(self, value: AbstractSet[Hashable], /) -> Self: ...
def __or__(self, value: AbstractSet[_H2], /) -> set[_H1 | _H2]: ...
def __ior__(self, value: AbstractSet[_H1], /) -> Self: ... # type: ignore[override,misc]
def __sub__(self, value: AbstractSet[Hashable], /) -> set[_H1]: ...
def __isub__(self, value: AbstractSet[Hashable], /) -> Self: ...
def __xor__(self, value: AbstractSet[_H2], /) -> set[_H1 | _H2]: ...
def __ixor__(self, value: AbstractSet[_H1], /) -> Self: ... # type: ignore[override,misc]
def __le__(self, value: AbstractSet[Hashable], /) -> bool: ...
def __lt__(self, value: AbstractSet[Hashable], /) -> bool: ...
def __ge__(self, value: AbstractSet[Hashable], /) -> bool: ...
def __gt__(self, value: AbstractSet[Hashable], /) -> bool: ...
def __eq__(self, value: object, /) -> bool: ...
__hash__: ClassVar[None] # type: ignore[assignment]
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...

@disjoint_base
class frozenset(AbstractSet[_T_co]):
class frozenset(AbstractSet[_H1_co]):
@overload
def __new__(cls) -> Self: ...
@overload
def __new__(cls, iterable: Iterable[_T_co], /) -> Self: ...
def __new__(cls, iterable: Iterable[_H1_co], /) -> Self: ...

def copy(self) -> frozenset[_T_co]: ...
def difference(self, *s: Iterable[object]) -> frozenset[_T_co]: ...
def intersection(self, *s: Iterable[object]) -> frozenset[_T_co]: ...
def isdisjoint(self, s: Iterable[object], /) -> bool: ...
def issubset(self, s: Iterable[object], /) -> bool: ...
def issuperset(self, s: Iterable[object], /) -> bool: ...
def symmetric_difference(self, s: Iterable[_S], /) -> frozenset[_T_co | _S]: ...
def union(self, *s: Iterable[_S]) -> frozenset[_T_co | _S]: ...
def copy(self) -> frozenset[_H1_co]: ...
def difference(self, *s: Iterable[Hashable]) -> frozenset[_H1_co]: ...
def intersection(self, *s: Iterable[Hashable]) -> frozenset[_H1_co]: ...
def isdisjoint(self, s: Iterable[Hashable], /) -> bool: ...
def issubset(self, s: Iterable[Hashable], /) -> bool: ...
def issuperset(self, s: Iterable[Hashable], /) -> bool: ...
def symmetric_difference(self, s: Iterable[_H1], /) -> frozenset[_H1_co | _H1]: ...
def union(self, *s: Iterable[_H1]) -> frozenset[_H1_co | _H1]: ...
def __len__(self) -> int: ...
def __contains__(self, o: object, /) -> bool: ...
def __iter__(self) -> Iterator[_T_co]: ...
def __and__(self, value: AbstractSet[object], /) -> frozenset[_T_co]: ...
def __or__(self, value: AbstractSet[_S], /) -> frozenset[_T_co | _S]: ...
def __sub__(self, value: AbstractSet[object], /) -> frozenset[_T_co]: ...
def __xor__(self, value: AbstractSet[_S], /) -> frozenset[_T_co | _S]: ...
def __le__(self, value: AbstractSet[object], /) -> bool: ...
def __lt__(self, value: AbstractSet[object], /) -> bool: ...
def __ge__(self, value: AbstractSet[object], /) -> bool: ...
def __gt__(self, value: AbstractSet[object], /) -> bool: ...
def __contains__(self, o: Hashable, /) -> bool: ...
def __iter__(self) -> Iterator[_H1_co]: ...
def __and__(self, value: AbstractSet[Hashable], /) -> frozenset[_H1_co]: ...
def __or__(self, value: AbstractSet[_H1], /) -> frozenset[_H1_co | _H1]: ...
def __sub__(self, value: AbstractSet[Hashable], /) -> frozenset[_H1_co]: ...
def __xor__(self, value: AbstractSet[_H1], /) -> frozenset[_H1_co | _H1]: ...
def __le__(self, value: AbstractSet[Hashable], /) -> bool: ...
def __lt__(self, value: AbstractSet[Hashable], /) -> bool: ...
def __ge__(self, value: AbstractSet[Hashable], /) -> bool: ...
def __gt__(self, value: AbstractSet[Hashable], /) -> bool: ...
def __eq__(self, value: object, /) -> bool: ...
def __hash__(self) -> int: ...
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
Expand Down
Loading
Loading