From 1cd497fab16fac92988203411e407c7e089a9957 Mon Sep 17 00:00:00 2001 From: "mingyu.park" Date: Fri, 16 May 2025 13:24:16 +0900 Subject: [PATCH 1/8] Add SetProxy and support for set operations in multiprocessing.managers for Python 3.14 --- stdlib/multiprocessing/managers.pyi | 57 ++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/stdlib/multiprocessing/managers.pyi b/stdlib/multiprocessing/managers.pyi index 50e4f1c1fe66..37584b515909 100644 --- a/stdlib/multiprocessing/managers.pyi +++ b/stdlib/multiprocessing/managers.pyi @@ -2,7 +2,17 @@ import queue import sys import threading from _typeshed import SupportsKeysAndGetItem, SupportsRichComparison, SupportsRichComparisonT -from collections.abc import Callable, Iterable, Iterator, Mapping, MutableMapping, MutableSequence, Sequence +from collections.abc import ( + Callable, + Iterable, + Iterator, + Mapping, + MutableMapping, + MutableSequence, + MutableSet, + Sequence, + Set as AbstractSet, +) from types import GenericAlias, TracebackType from typing import Any, AnyStr, ClassVar, Generic, SupportsIndex, TypeVar, overload from typing_extensions import Self, TypeAlias @@ -18,6 +28,7 @@ __all__ = ["BaseManager", "SyncManager", "BaseProxy", "Token", "SharedMemoryMana _T = TypeVar("_T") _KT = TypeVar("_KT") _VT = TypeVar("_VT") +_S = TypeVar("_S") class Namespace: def __init__(self, **kwds: Any) -> None: ... @@ -111,6 +122,45 @@ else: def items(self) -> list[tuple[_KT, _VT]]: ... # type: ignore[override] def values(self) -> list[_VT]: ... # type: ignore[override] +if sys.version_info >= (3, 14): + class _BaseSetProxy(BaseProxy, MutableSet[_T]): + __builtins__: ClassVar[dict[str, Any]] + # Copied from builtins.set + def add(self, element: _T, /) -> None: ... + def copy(self) -> set[_T]: ... + def difference(self, *s: Iterable[Any]) -> set[_T]: ... + def difference_update(self, *s: Iterable[Any]) -> None: ... + def discard(self, element: _T, /) -> None: ... + def intersection(self, *s: Iterable[Any]) -> set[_T]: ... + def intersection_update(self, *s: Iterable[Any]) -> None: ... + def isdisjoint(self, s: Iterable[Any], /) -> bool: ... + def issubset(self, s: Iterable[Any], /) -> bool: ... + def issuperset(self, s: Iterable[Any], /) -> bool: ... + def remove(self, element: _T, /) -> None: ... + def symmetric_difference(self, s: Iterable[_T], /) -> set[_T]: ... + 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 __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[_T | None], /) -> 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 __eq__(self, value: object, /) -> bool: ... + + class SetProxy(_BaseSetProxy[_T]): + def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... + class BaseListProxy(BaseProxy, MutableSequence[_T]): __builtins__: ClassVar[dict[str, Any]] def __len__(self) -> int: ... @@ -273,6 +323,11 @@ class SyncManager(BaseManager): def list(self, sequence: Sequence[_T], /) -> ListProxy[_T]: ... @overload def list(self) -> ListProxy[Any]: ... + if sys.version_info >= (3, 14): + @overload + def set(self, iterable: Iterable[_T], /) -> SetProxy[_T]: ... + @overload + def set(self) -> SetProxy[Any]: ... class RemoteError(Exception): ... From 8b814c4b7ac1c95a09c519b3c8e4227405ff8d4b Mon Sep 17 00:00:00 2001 From: "mingyu.park" Date: Fri, 16 May 2025 14:28:53 +0900 Subject: [PATCH 2/8] Add __ror__, __rand__, __rsub__, __rxor__, __class_getitem__ --- stdlib/multiprocessing/managers.pyi | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/stdlib/multiprocessing/managers.pyi b/stdlib/multiprocessing/managers.pyi index 37584b515909..881aa0ffed29 100644 --- a/stdlib/multiprocessing/managers.pyi +++ b/stdlib/multiprocessing/managers.pyi @@ -157,10 +157,15 @@ 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: ... - - class SetProxy(_BaseSetProxy[_T]): + def __rand__(self, value: AbstractSet[object], /) -> set[_T]: ... + def __ror__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... + def __rsub__(self, value: AbstractSet[_T], /) -> set[_T]: ... + def __rxor__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... + class SetProxy(_BaseSetProxy[_T]): ... + + class BaseListProxy(BaseProxy, MutableSequence[_T]): __builtins__: ClassVar[dict[str, Any]] def __len__(self) -> int: ... From 2abe0d456f1fc0eb6a74d334bfdb5778147f7f98 Mon Sep 17 00:00:00 2001 From: "mingyu.park" Date: Fri, 16 May 2025 14:37:12 +0900 Subject: [PATCH 3/8] Add pop, clear, copy and `/` --- stdlib/multiprocessing/managers.pyi | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stdlib/multiprocessing/managers.pyi b/stdlib/multiprocessing/managers.pyi index 881aa0ffed29..c12345de3592 100644 --- a/stdlib/multiprocessing/managers.pyi +++ b/stdlib/multiprocessing/managers.pyi @@ -127,7 +127,8 @@ if sys.version_info >= (3, 14): __builtins__: ClassVar[dict[str, Any]] # Copied from builtins.set def add(self, element: _T, /) -> None: ... - def copy(self) -> set[_T]: ... + def copy(self, /) -> set[_T]: ... + def clear(self, /) -> None: ... def difference(self, *s: Iterable[Any]) -> set[_T]: ... def difference_update(self, *s: Iterable[Any]) -> None: ... def discard(self, element: _T, /) -> None: ... @@ -136,14 +137,15 @@ if sys.version_info >= (3, 14): def isdisjoint(self, s: Iterable[Any], /) -> bool: ... def issubset(self, s: Iterable[Any], /) -> bool: ... def issuperset(self, s: Iterable[Any], /) -> bool: ... + def pop(self, /) -> _T: ... def remove(self, element: _T, /) -> None: ... def symmetric_difference(self, s: Iterable[_T], /) -> set[_T]: ... 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 __len__(self) -> int: ... + def __len__(self, /) -> int: ... def __contains__(self, o: object, /) -> bool: ... - def __iter__(self) -> Iterator[_T]: ... + 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]: ... From c88750416b1c977f035b73b6f0bc4af7b3a3b759 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 16 May 2025 05:38:52 +0000 Subject: [PATCH 4/8] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/multiprocessing/managers.pyi | 1 - 1 file changed, 1 deletion(-) diff --git a/stdlib/multiprocessing/managers.pyi b/stdlib/multiprocessing/managers.pyi index c12345de3592..ba946cac5a32 100644 --- a/stdlib/multiprocessing/managers.pyi +++ b/stdlib/multiprocessing/managers.pyi @@ -167,7 +167,6 @@ if sys.version_info >= (3, 14): class SetProxy(_BaseSetProxy[_T]): ... - class BaseListProxy(BaseProxy, MutableSequence[_T]): __builtins__: ClassVar[dict[str, Any]] def __len__(self) -> int: ... From 88825dc8ca9f857fce952963cc5b316c19280dce Mon Sep 17 00:00:00 2001 From: "mingyu.park" Date: Fri, 16 May 2025 15:17:46 +0900 Subject: [PATCH 5/8] type: ignore[misc] in ror, rxor --- stdlib/multiprocessing/managers.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/multiprocessing/managers.pyi b/stdlib/multiprocessing/managers.pyi index ba946cac5a32..3af90c4c20fa 100644 --- a/stdlib/multiprocessing/managers.pyi +++ b/stdlib/multiprocessing/managers.pyi @@ -160,9 +160,9 @@ if sys.version_info >= (3, 14): def __gt__(self, value: AbstractSet[object], /) -> bool: ... def __eq__(self, value: object, /) -> bool: ... def __rand__(self, value: AbstractSet[object], /) -> set[_T]: ... - def __ror__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... + def __ror__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... # type: ignore[misc] def __rsub__(self, value: AbstractSet[_T], /) -> set[_T]: ... - def __rxor__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... + def __rxor__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... # type: ignore[misc] def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... class SetProxy(_BaseSetProxy[_T]): ... From 4a933b18f6a50c52089d77f3118f4776ff1887d1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 16 May 2025 06:21:49 +0000 Subject: [PATCH 6/8] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/multiprocessing/managers.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/multiprocessing/managers.pyi b/stdlib/multiprocessing/managers.pyi index 3af90c4c20fa..64adf6e68e3d 100644 --- a/stdlib/multiprocessing/managers.pyi +++ b/stdlib/multiprocessing/managers.pyi @@ -160,9 +160,9 @@ if sys.version_info >= (3, 14): def __gt__(self, value: AbstractSet[object], /) -> bool: ... def __eq__(self, value: object, /) -> bool: ... def __rand__(self, value: AbstractSet[object], /) -> set[_T]: ... - def __ror__(self, value: AbstractSet[_S], /) -> set[_T | _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 __rxor__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... # type: ignore[misc] + def __rxor__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... # type: ignore[misc] def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... class SetProxy(_BaseSetProxy[_T]): ... From d8116e267edba964c3d10024b8b0fbee6a1c945d Mon Sep 17 00:00:00 2001 From: Mingyu Park Date: Sat, 17 May 2025 12:46:00 +0900 Subject: [PATCH 7/8] Add stubtest_allowlists --- stdlib/@tests/stubtest_allowlists/py314.txt | 6 ++++++ stdlib/multiprocessing/managers.pyi | 10 +++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/stdlib/@tests/stubtest_allowlists/py314.txt b/stdlib/@tests/stubtest_allowlists/py314.txt index 922c0189915f..80a62e8b14e1 100644 --- a/stdlib/@tests/stubtest_allowlists/py314.txt +++ b/stdlib/@tests/stubtest_allowlists/py314.txt @@ -229,6 +229,12 @@ multiprocessing.managers._BaseDictProxy.keys multiprocessing.managers._BaseDictProxy.popitem multiprocessing.managers._BaseDictProxy.values +multiprocessing.managers._BaseSetProxy.__iter__ +multiprocessing.managers._BaseSetProxy.__len__ +multiprocessing.managers._BaseSetProxy.clear +multiprocessing.managers._BaseSetProxy.copy +multiprocessing.managers._BaseSetProxy.pop + # To match `dict`, we lie about the runtime, but use overloads to match the correct behavior types.MappingProxyType.get diff --git a/stdlib/multiprocessing/managers.pyi b/stdlib/multiprocessing/managers.pyi index 64adf6e68e3d..b0ccac41b925 100644 --- a/stdlib/multiprocessing/managers.pyi +++ b/stdlib/multiprocessing/managers.pyi @@ -127,8 +127,8 @@ if sys.version_info >= (3, 14): __builtins__: ClassVar[dict[str, Any]] # Copied from builtins.set def add(self, element: _T, /) -> None: ... - def copy(self, /) -> set[_T]: ... - def clear(self, /) -> None: ... + def copy(self) -> set[_T]: ... + def clear(self) -> None: ... def difference(self, *s: Iterable[Any]) -> set[_T]: ... def difference_update(self, *s: Iterable[Any]) -> None: ... def discard(self, element: _T, /) -> None: ... @@ -137,15 +137,15 @@ if sys.version_info >= (3, 14): def isdisjoint(self, s: Iterable[Any], /) -> bool: ... def issubset(self, s: Iterable[Any], /) -> bool: ... def issuperset(self, s: Iterable[Any], /) -> bool: ... - def pop(self, /) -> _T: ... + def pop(self) -> _T: ... def remove(self, element: _T, /) -> None: ... def symmetric_difference(self, s: Iterable[_T], /) -> set[_T]: ... 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 __len__(self, /) -> int: ... + def __len__(self) -> int: ... def __contains__(self, o: object, /) -> bool: ... - def __iter__(self, /) -> Iterator[_T]: ... + 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]: ... From 2a52862d8c8eaf1d4112cfd6a80a4ea52583e4a5 Mon Sep 17 00:00:00 2001 From: Mingyu Park Date: Sat, 17 May 2025 12:48:08 +0900 Subject: [PATCH 8/8] Remove multiprocessing.managers.SyncManager.set in stubtest_allowlists --- stdlib/@tests/stubtest_allowlists/py314.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/stdlib/@tests/stubtest_allowlists/py314.txt b/stdlib/@tests/stubtest_allowlists/py314.txt index 80a62e8b14e1..fe75c657c75e 100644 --- a/stdlib/@tests/stubtest_allowlists/py314.txt +++ b/stdlib/@tests/stubtest_allowlists/py314.txt @@ -77,7 +77,6 @@ multiprocessing.forkserver.main multiprocessing.managers.BaseListProxy.clear multiprocessing.managers.BaseListProxy.copy multiprocessing.managers.DictProxy.__ior__ -multiprocessing.managers.SyncManager.set multiprocessing.managers._BaseDictProxy.__ior__ multiprocessing.managers._BaseDictProxy.__or__ multiprocessing.managers._BaseDictProxy.__reversed__