From 2e66e0997ebced9de0853327650ba7bf84d85059 Mon Sep 17 00:00:00 2001 From: Trinh Quoc Anh Date: Sat, 24 Oct 2026 10:25:58 +0200 Subject: [PATCH 1/4] Add reflected set operators to `AbstractSet` Closes #15532 Co-Authored-By: Claude Opus 5.5 --- stdlib/builtins.pyi | 16 ++++++++-------- stdlib/multiprocessing/managers.pyi | 4 ++-- stdlib/typing.pyi | 4 ++++ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 6feba7ea2567..d7936761c501 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -1456,7 +1456,7 @@ class set(MutableSet[_T]): def __and__(self, value: AbstractSet[object], /) -> set[_T]: ... def __iand__(self, value: AbstractSet[object], /) -> Self: ... - @overload + @overload # type: ignore[override] def __rand__(self, value: set[_S], /) -> set[_S]: ... @overload def __rand__(self, value: frozenset[_S], /) -> frozenset[_S]: ... @@ -1464,7 +1464,7 @@ class set(MutableSet[_T]): def __or__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... def __ior__(self, value: AbstractSet[_T], /) -> Self: ... # type: ignore[override,misc] - @overload + @overload # type: ignore[override] def __ror__(self, value: set[_S], /) -> set[_T | _S]: ... @overload def __ror__(self, value: frozenset[_S], /) -> frozenset[_T | _S]: ... @@ -1472,7 +1472,7 @@ class set(MutableSet[_T]): def __sub__(self, value: AbstractSet[object], /) -> set[_T]: ... def __isub__(self, value: AbstractSet[object], /) -> Self: ... - @overload + @overload # type: ignore[override] def __rsub__(self, value: set[_S], /) -> set[_S]: ... @overload def __rsub__(self, value: frozenset[_S], /) -> frozenset[_S]: ... @@ -1480,7 +1480,7 @@ class set(MutableSet[_T]): def __xor__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... def __ixor__(self, value: AbstractSet[_T], /) -> Self: ... # type: ignore[override,misc] - @overload + @overload # type: ignore[override] def __rxor__(self, value: set[_S], /) -> set[_T | _S]: ... @overload def __rxor__(self, value: frozenset[_S], /) -> frozenset[_T | _S]: ... @@ -1513,28 +1513,28 @@ class frozenset(AbstractSet[_T_co]): def __iter__(self) -> Iterator[_T_co]: ... def __and__(self, value: AbstractSet[object], /) -> frozenset[_T_co]: ... - @overload + @overload # type: ignore[override] def __rand__(self, value: set[_S], /) -> set[_S]: ... @overload def __rand__(self, value: frozenset[_S], /) -> frozenset[_S]: ... def __or__(self, value: AbstractSet[_S], /) -> frozenset[_T_co | _S]: ... - @overload + @overload # type: ignore[override] def __ror__(self, value: set[_S], /) -> set[_T_co | _S]: ... @overload def __ror__(self, value: frozenset[_S], /) -> frozenset[_T_co | _S]: ... def __sub__(self, value: AbstractSet[object], /) -> frozenset[_T_co]: ... - @overload + @overload # type: ignore[override] def __rsub__(self, value: set[_S], /) -> set[_S]: ... @overload def __rsub__(self, value: frozenset[_S], /) -> frozenset[_S]: ... def __xor__(self, value: AbstractSet[_S], /) -> frozenset[_T_co | _S]: ... - @overload + @overload # type: ignore[override] def __rxor__(self, value: set[_S], /) -> set[_T_co | _S]: ... @overload def __rxor__(self, value: frozenset[_S], /) -> frozenset[_T_co | _S]: ... diff --git a/stdlib/multiprocessing/managers.pyi b/stdlib/multiprocessing/managers.pyi index 0f1d4e87b0dc..e2cd2f3e95dc 100644 --- a/stdlib/multiprocessing/managers.pyi +++ b/stdlib/multiprocessing/managers.pyi @@ -192,9 +192,9 @@ if sys.version_info >= (3, 14): def __ge__(self, value: AbstractSet[object], /) -> bool: ... def __gt__(self, value: AbstractSet[object], /) -> bool: ... def __eq__(self, value: object, /) -> bool: ... - def __rand__(self, value: AbstractSet[object], /) -> set[_T]: ... + def __rand__(self, value: AbstractSet[_S], /) -> set[_S]: ... # type: ignore[misc] def __ror__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... # type: ignore[misc] - def __rsub__(self, value: AbstractSet[_T], /) -> set[_T]: ... + def __rsub__(self, value: AbstractSet[_S], /) -> set[_S]: ... # type: ignore[misc] def __rxor__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... # type: ignore[misc] def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi index 198dd45feedf..d6fe08c16930 100644 --- a/stdlib/typing.pyi +++ b/stdlib/typing.pyi @@ -741,9 +741,13 @@ class AbstractSet(Collection[_T_co]): def __gt__(self, other: AbstractSet[Any], /) -> bool: ... def __ge__(self, other: AbstractSet[Any], /) -> bool: ... def __and__(self, other: AbstractSet[Any], /) -> AbstractSet[_T_co]: ... + def __rand__(self, other: AbstractSet[_T], /) -> AbstractSet[_T]: ... def __or__(self, other: AbstractSet[_T], /) -> AbstractSet[_T_co | _T]: ... + def __ror__(self, other: AbstractSet[_T], /) -> AbstractSet[_T_co | _T]: ... def __sub__(self, other: AbstractSet[Any], /) -> AbstractSet[_T_co]: ... + def __rsub__(self, other: AbstractSet[_T], /) -> AbstractSet[_T]: ... def __xor__(self, other: AbstractSet[_T], /) -> AbstractSet[_T_co | _T]: ... + def __rxor__(self, other: AbstractSet[_T], /) -> AbstractSet[_T_co | _T]: ... def __eq__(self, other: object, /) -> bool: ... def isdisjoint(self, other: Iterable[Any], /) -> bool: ... From ceb79fccae207e00f62b00fb0a2671cc1893b921 Mon Sep 17 00:00:00 2001 From: Trinh Quoc Anh Date: Sat, 24 Oct 2026 10:35:58 +0200 Subject: [PATCH 2/4] Mirror `set` overloads for `_BaseSetProxy` reflected operators The proxy forwards to a real `set`, so a `frozenset` operand yields a `frozenset` and non-set operands yield `NotImplemented`. Co-Authored-By: Claude Opus 5.5 --- stdlib/multiprocessing/managers.pyi | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/stdlib/multiprocessing/managers.pyi b/stdlib/multiprocessing/managers.pyi index e2cd2f3e95dc..558b0971d648 100644 --- a/stdlib/multiprocessing/managers.pyi +++ b/stdlib/multiprocessing/managers.pyi @@ -192,10 +192,22 @@ if sys.version_info >= (3, 14): def __ge__(self, value: AbstractSet[object], /) -> bool: ... def __gt__(self, value: AbstractSet[object], /) -> bool: ... def __eq__(self, value: object, /) -> bool: ... - def __rand__(self, value: AbstractSet[_S], /) -> set[_S]: ... # type: ignore[misc] - def __ror__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... # type: ignore[misc] - def __rsub__(self, value: AbstractSet[_S], /) -> set[_S]: ... # type: ignore[misc] - def __rxor__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... # type: ignore[misc] + @overload # type: ignore[override] + def __rand__(self, value: set[_S], /) -> set[_S]: ... + @overload + def __rand__(self, value: frozenset[_S], /) -> frozenset[_S]: ... + @overload # type: ignore[override] + def __ror__(self, value: set[_S], /) -> set[_T | _S]: ... + @overload + def __ror__(self, value: frozenset[_S], /) -> frozenset[_T | _S]: ... + @overload # type: ignore[override] + def __rsub__(self, value: set[_S], /) -> set[_S]: ... + @overload + def __rsub__(self, value: frozenset[_S], /) -> frozenset[_S]: ... + @overload # type: ignore[override] + def __rxor__(self, value: set[_S], /) -> set[_T | _S]: ... + @overload + def __rxor__(self, value: frozenset[_S], /) -> frozenset[_T | _S]: ... def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... class SetProxy(_BaseSetProxy[_T]): ... From afdcc84524395602b430846f9ad3dda012898f56 Mon Sep 17 00:00:00 2001 From: Trinh Quoc Anh Date: Sat, 24 Oct 2026 10:47:40 +0200 Subject: [PATCH 3/4] [boltons] Ignore `IndexedSet.__rsub__` override It returns `type(other)(...)`, which need not be a set. Co-Authored-By: Claude Opus 5.5 --- stubs/boltons/boltons/setutils.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/boltons/boltons/setutils.pyi b/stubs/boltons/boltons/setutils.pyi index d94de1967fc0..92a3945bdae0 100644 --- a/stubs/boltons/boltons/setutils.pyi +++ b/stubs/boltons/boltons/setutils.pyi @@ -40,7 +40,7 @@ class IndexedSet(MutableSet[Any]): # __sub__ = difference # __xor__ = symmetric_difference __rxor__ = symmetric_difference - def __rsub__(self, other: _RSub[_T_co]) -> _RSub[_T_co]: ... + def __rsub__(self, other: _RSub[_T_co]) -> _RSub[_T_co]: ... # type: ignore[override] def update(self, *others: Iterable[Any]) -> None: ... def intersection_update(self, *others: Iterable[Any]) -> None: ... def difference_update(self, *others: Container[Any]) -> None: ... From d057917c1ebc23aa94e175dd9c45bb741de7619e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 24 Oct 2026 09:20:53 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/multiprocessing/managers.pyi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stdlib/multiprocessing/managers.pyi b/stdlib/multiprocessing/managers.pyi index 558b0971d648..0a5ed1a82bdb 100644 --- a/stdlib/multiprocessing/managers.pyi +++ b/stdlib/multiprocessing/managers.pyi @@ -192,22 +192,27 @@ if sys.version_info >= (3, 14): def __ge__(self, value: AbstractSet[object], /) -> bool: ... def __gt__(self, value: AbstractSet[object], /) -> bool: ... def __eq__(self, value: object, /) -> bool: ... + @overload # type: ignore[override] def __rand__(self, value: set[_S], /) -> set[_S]: ... @overload def __rand__(self, value: frozenset[_S], /) -> frozenset[_S]: ... + @overload # type: ignore[override] def __ror__(self, value: set[_S], /) -> set[_T | _S]: ... @overload def __ror__(self, value: frozenset[_S], /) -> frozenset[_T | _S]: ... + @overload # type: ignore[override] def __rsub__(self, value: set[_S], /) -> set[_S]: ... @overload def __rsub__(self, value: frozenset[_S], /) -> frozenset[_S]: ... + @overload # type: ignore[override] def __rxor__(self, value: set[_S], /) -> set[_T | _S]: ... @overload def __rxor__(self, value: frozenset[_S], /) -> frozenset[_T | _S]: ... + def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... class SetProxy(_BaseSetProxy[_T]): ...