From b054f06ca0451d557f4487b4551ed4edd00dcc3f Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 8 Apr 2026 14:15:41 +0200 Subject: [PATCH 01/13] [functools] Use ParamSpec for single dispatch --- stdlib/functools.pyi | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/stdlib/functools.pyi b/stdlib/functools.pyi index 57bc3f179f7a..490d8352a278 100644 --- a/stdlib/functools.pyi +++ b/stdlib/functools.pyi @@ -26,6 +26,7 @@ __all__ = [ _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _S = TypeVar("_S") +_P = ParamSpec("_P") _PWrapped = ParamSpec("_PWrapped") _RWrapped = TypeVar("_RWrapped") _PWrapper = ParamSpec("_PWrapper") @@ -195,38 +196,38 @@ else: _RegType: TypeAlias = type[Any] @type_check_only -class _SingleDispatchCallable(Generic[_T]): - registry: types.MappingProxyType[Any, Callable[..., _T]] - def dispatch(self, cls: Any) -> Callable[..., _T]: ... +class _SingleDispatchCallable(Generic[_P, _T]): + registry: types.MappingProxyType[Any, Callable[_P, _T]] + def dispatch(self, cls: Any) -> Callable[_P, _T]: ... # @fun.register(complex) # def _(arg, verbose=False): ... @overload - def register(self, cls: _RegType, func: None = None) -> Callable[[Callable[..., _T]], Callable[..., _T]]: ... + def register(self, cls: _RegType, func: None = None) -> Callable[[Callable[_P, _T]], Callable[_P, _T]]: ... # @fun.register # def _(arg: int, verbose=False): @overload - def register(self, cls: Callable[..., _T], func: None = None) -> Callable[..., _T]: ... + def register(self, cls: Callable[_P, _T], func: None = None) -> Callable[_P, _T]: ... # fun.register(int, lambda x: x) @overload - def register(self, cls: _RegType, func: Callable[..., _T]) -> Callable[..., _T]: ... + def register(self, cls: _RegType, func: Callable[_P, _T]) -> Callable[_P, _T]: ... def _clear_cache(self) -> None: ... - def __call__(self, /, *args: Any, **kwargs: Any) -> _T: ... + def __call__(self, /, *args: _P.args, **kwargs: _P.kwargs) -> _T: ... -def singledispatch(func: Callable[..., _T]) -> _SingleDispatchCallable[_T]: ... +def singledispatch(func: Callable[_P, _T]) -> _SingleDispatchCallable[_P, _T]: ... -class singledispatchmethod(Generic[_T]): - dispatcher: _SingleDispatchCallable[_T] - func: Callable[..., _T] - def __init__(self, func: Callable[..., _T]) -> None: ... +class singledispatchmethod(Generic[_P, _T]): + dispatcher: _SingleDispatchCallable[_P, _T] + func: Callable[_P, _T] + def __init__(self, func: Callable[_P, _T]) -> None: ... @property def __isabstractmethod__(self) -> bool: ... @overload - def register(self, cls: _RegType, method: None = None) -> Callable[[Callable[..., _T]], Callable[..., _T]]: ... + def register(self, cls: _RegType, method: None = None) -> Callable[[Callable[_P, _T]], Callable[_P, _T]]: ... @overload - def register(self, cls: Callable[..., _T], method: None = None) -> Callable[..., _T]: ... + def register(self, cls: Callable[_P, _T], method: None = None) -> Callable[_P, _T]: ... @overload - def register(self, cls: _RegType, method: Callable[..., _T]) -> Callable[..., _T]: ... - def __get__(self, obj: _S, cls: type[_S] | None = None) -> Callable[..., _T]: ... + def register(self, cls: _RegType, method: Callable[_P, _T]) -> Callable[_P, _T]: ... + def __get__(self, obj: _S, cls: type[_S] | None = None) -> Callable[_P, _T]: ... class cached_property(Generic[_T_co]): func: Callable[[Any], _T_co] From 8d46a8598a6c5ea2456ccf5bfbc49ffc4911701e Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 8 Apr 2026 14:54:20 +0200 Subject: [PATCH 02/13] Use Concatenate --- stdlib/functools.pyi | 56 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/stdlib/functools.pyi b/stdlib/functools.pyi index 490d8352a278..7b728e68c2ac 100644 --- a/stdlib/functools.pyi +++ b/stdlib/functools.pyi @@ -4,7 +4,7 @@ from _typeshed import SupportsAllComparisons, SupportsItems from collections.abc import Callable, Hashable, Iterable, Sized from types import GenericAlias from typing import Any, Final, Generic, Literal, NamedTuple, TypedDict, TypeVar, final, overload, type_check_only -from typing_extensions import ParamSpec, Self, TypeAlias, disjoint_base +from typing_extensions import Concatenate, ParamSpec, Self, TypeAlias, disjoint_base __all__ = [ "update_wrapper", @@ -197,37 +197,67 @@ else: @type_check_only class _SingleDispatchCallable(Generic[_P, _T]): - registry: types.MappingProxyType[Any, Callable[_P, _T]] - def dispatch(self, cls: Any) -> Callable[_P, _T]: ... + # First argument pf the callables in the registry is the type to dispatch on. + registry: types.MappingProxyType[Any, Callable[Concatenate[Any, _P], _T]] + def dispatch(self, cls: type[_S]) -> Callable[Concatenate[_S, _P], _T]: ... + if sys.version_info >= (3, 11): + # @fun.register(complex | str) + # def _(arg, verbose=False): ... + @overload + def register( + self, cls: types.UnionType, func: None = None + ) -> Callable[[Callable[Concatenate[_S, _P], _T]], Callable[Concatenate[_S, _P], _T]]: ... # @fun.register(complex) # def _(arg, verbose=False): ... @overload - def register(self, cls: _RegType, func: None = None) -> Callable[[Callable[_P, _T]], Callable[_P, _T]]: ... + def register( + self, cls: type[_S], func: None = None + ) -> Callable[[Callable[Concatenate[_S, _P], _T]], Callable[Concatenate[_S, _P], _T]]: ... # @fun.register # def _(arg: int, verbose=False): @overload - def register(self, cls: Callable[_P, _T], func: None = None) -> Callable[_P, _T]: ... + def register(self, cls: Callable[Concatenate[_S, _P], _T], func: None = None) -> Callable[Concatenate[_S, _P], _T]: ... + if sys.version_info >= (3, 11): + # fun.register(int, lambda x: x) + @overload + def register( + self, cls: types.UnionType, func: Callable[Concatenate[_S, _P], _T] + ) -> Callable[Concatenate[_S, _P], _T]: ... # fun.register(int, lambda x: x) @overload - def register(self, cls: _RegType, func: Callable[_P, _T]) -> Callable[_P, _T]: ... + def register(self, cls: _RegType, func: Callable[Concatenate[_S, _P], _T]) -> Callable[Concatenate[_S, _P], _T]: ... def _clear_cache(self) -> None: ... - def __call__(self, /, *args: _P.args, **kwargs: _P.kwargs) -> _T: ... + def __call__(self, arg: object, /, *args: _P.args, **kwargs: _P.kwargs) -> _T: ... -def singledispatch(func: Callable[_P, _T]) -> _SingleDispatchCallable[_P, _T]: ... +def singledispatch(func: Callable[Concatenate[object, _P], _T]) -> _SingleDispatchCallable[_P, _T]: ... class singledispatchmethod(Generic[_P, _T]): dispatcher: _SingleDispatchCallable[_P, _T] func: Callable[_P, _T] - def __init__(self, func: Callable[_P, _T]) -> None: ... + def __init__(self, func: Callable[Concatenate[object, _P], _T]) -> None: ... @property def __isabstractmethod__(self) -> bool: ... + if sys.version_info >= (3, 11): + @overload + def register( + self, cls: types.UnionType, method: None = None + ) -> Callable[[Callable[Concatenate[_S, _P], _T]], Callable[Concatenate[_S, _P], _T]]: ... + @overload - def register(self, cls: _RegType, method: None = None) -> Callable[[Callable[_P, _T]], Callable[_P, _T]]: ... + def register( + self, cls: type[_S], method: None = None + ) -> Callable[[Callable[Concatenate[_S, _P], _T]], Callable[Concatenate[_S, _P], _T]]: ... @overload - def register(self, cls: Callable[_P, _T], method: None = None) -> Callable[_P, _T]: ... + def register(self, cls: Callable[Concatenate[_S, _P], _T], method: None = None) -> Callable[Concatenate[_S, _P], _T]: ... + if sys.version_info >= (3, 11): + @overload + def register( + self, cls: types.UnionType, method: Callable[Concatenate[_S, _P], _T] + ) -> Callable[Concatenate[_S, _P], _T]: ... + @overload - def register(self, cls: _RegType, method: Callable[_P, _T]) -> Callable[_P, _T]: ... - def __get__(self, obj: _S, cls: type[_S] | None = None) -> Callable[_P, _T]: ... + def register(self, cls: type[_S], method: Callable[Concatenate[_S, _P], _T]) -> Callable[Concatenate[_S, _P], _T]: ... + def __get__(self, obj: _S, cls: type[_S] | None = None) -> Callable[Concatenate[_S, _P], _T]: ... class cached_property(Generic[_T_co]): func: Callable[[Any], _T_co] From a79bb7574a896df91f75d5066a76a21a2697ca69 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 8 Apr 2026 14:57:05 +0200 Subject: [PATCH 03/13] Fix one overload --- stdlib/functools.pyi | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/stdlib/functools.pyi b/stdlib/functools.pyi index 7b728e68c2ac..42a09ce0e3c2 100644 --- a/stdlib/functools.pyi +++ b/stdlib/functools.pyi @@ -190,11 +190,6 @@ class partialmethod(Generic[_T]): def __isabstractmethod__(self) -> bool: ... def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... -if sys.version_info >= (3, 11): - _RegType: TypeAlias = type[Any] | types.UnionType -else: - _RegType: TypeAlias = type[Any] - @type_check_only class _SingleDispatchCallable(Generic[_P, _T]): # First argument pf the callables in the registry is the type to dispatch on. @@ -225,7 +220,7 @@ class _SingleDispatchCallable(Generic[_P, _T]): ) -> Callable[Concatenate[_S, _P], _T]: ... # fun.register(int, lambda x: x) @overload - def register(self, cls: _RegType, func: Callable[Concatenate[_S, _P], _T]) -> Callable[Concatenate[_S, _P], _T]: ... + def register(self, cls: type[_S], func: Callable[Concatenate[_S, _P], _T]) -> Callable[Concatenate[_S, _P], _T]: ... def _clear_cache(self) -> None: ... def __call__(self, arg: object, /, *args: _P.args, **kwargs: _P.kwargs) -> _T: ... From b50ff5f7baa95c5b3ba2962d76fae2e1f9143536 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 8 Apr 2026 15:05:56 +0200 Subject: [PATCH 04/13] Ignore away all the errors --- stdlib/functools.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/functools.pyi b/stdlib/functools.pyi index 42a09ce0e3c2..16c62f9fe479 100644 --- a/stdlib/functools.pyi +++ b/stdlib/functools.pyi @@ -205,7 +205,7 @@ class _SingleDispatchCallable(Generic[_P, _T]): # @fun.register(complex) # def _(arg, verbose=False): ... @overload - def register( + def register( # type: ignore[overload-overlap] self, cls: type[_S], func: None = None ) -> Callable[[Callable[Concatenate[_S, _P], _T]], Callable[Concatenate[_S, _P], _T]]: ... # @fun.register @@ -239,7 +239,7 @@ class singledispatchmethod(Generic[_P, _T]): ) -> Callable[[Callable[Concatenate[_S, _P], _T]], Callable[Concatenate[_S, _P], _T]]: ... @overload - def register( + def register( # type: ignore[overload-overlap] self, cls: type[_S], method: None = None ) -> Callable[[Callable[Concatenate[_S, _P], _T]], Callable[Concatenate[_S, _P], _T]]: ... @overload From 7b3519a7d09e6af6921136c0ed0b3317af2c6bae Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 8 Apr 2026 15:11:11 +0200 Subject: [PATCH 05/13] Add tests --- stdlib/@tests/test_cases/check_functools.py | 34 ++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/stdlib/@tests/test_cases/check_functools.py b/stdlib/@tests/test_cases/check_functools.py index a25c0111adf9..e54112a018d3 100644 --- a/stdlib/@tests/test_cases/check_functools.py +++ b/stdlib/@tests/test_cases/check_functools.py @@ -1,6 +1,6 @@ from __future__ import annotations -from functools import cache, cached_property, wraps +from functools import _SingleDispatchCallable, cache, cached_property, singledispatch, wraps from typing import Callable, TypeVar from typing_extensions import ParamSpec, assert_type @@ -108,3 +108,35 @@ class CachedChild(CachedParent): @cache def method(self) -> Child: return Child() + + +def check_singledispatch_simple() -> None: + @singledispatch + def sd_fun(arg: object) -> str: + return "" + + + @sd_fun.register + def _(int_arg: int) -> str: + return "" + + assert_type(sd_fun, _SingleDispatchCallable[[object], str]) + + sd_fun.dispatch(42) + sd_fun.dispatch("") + sd_fun.dispatch(1, 2) # type: ignore + + +def check_singledispatch_additional_args() -> None: + @singledispatch + def sd_fun(arg: object, posonly: str, /, verbose: bool = False) -> str: + return "" + + + @sd_fun.register + def _(int_arg: int, posonly: str, /, verbose: bool = False) -> str: + return "" + + sd_fun.dispatch(5.4, "") + sd_fun.dispatch(5.4, "", verbose=True) + sd_fun.dispatch(1, 2) # type: ignore From d9eb0a0100d36df8255079a0015efa67277c8cfa Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 13:13:26 +0000 Subject: [PATCH 06/13] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/@tests/test_cases/check_functools.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/@tests/test_cases/check_functools.py b/stdlib/@tests/test_cases/check_functools.py index e54112a018d3..26763b46d6de 100644 --- a/stdlib/@tests/test_cases/check_functools.py +++ b/stdlib/@tests/test_cases/check_functools.py @@ -115,7 +115,6 @@ def check_singledispatch_simple() -> None: def sd_fun(arg: object) -> str: return "" - @sd_fun.register def _(int_arg: int) -> str: return "" @@ -132,7 +131,6 @@ def check_singledispatch_additional_args() -> None: def sd_fun(arg: object, posonly: str, /, verbose: bool = False) -> str: return "" - @sd_fun.register def _(int_arg: int, posonly: str, /, verbose: bool = False) -> str: return "" From 9ec49de530659ee9fd435c5a4e26ba48493eb9e2 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 8 Apr 2026 15:17:51 +0200 Subject: [PATCH 07/13] Add a type ignore???? --- stubs/aiofiles/aiofiles/threadpool/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/aiofiles/aiofiles/threadpool/__init__.pyi b/stubs/aiofiles/aiofiles/threadpool/__init__.pyi index 71d2f47024ac..a84ae4105e8c 100644 --- a/stubs/aiofiles/aiofiles/threadpool/__init__.pyi +++ b/stubs/aiofiles/aiofiles/threadpool/__init__.pyi @@ -99,7 +99,7 @@ def open( ) -> AiofilesContextManager[_UnknownAsyncBinaryIO]: ... stdin: AsyncTextIndirectIOWrapper -stdout: AsyncTextIndirectIOWrapper +stdout: AsyncTextIndirectIOWrapper # type: ignore # ??? stderr: AsyncTextIndirectIOWrapper stdin_bytes: AsyncIndirectBufferedIOBase stdout_bytes: AsyncIndirectBufferedIOBase From 302109eb49d17dc8f236fb796a217717b0ee4247 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 13:20:44 +0000 Subject: [PATCH 08/13] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stubs/aiofiles/aiofiles/threadpool/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/aiofiles/aiofiles/threadpool/__init__.pyi b/stubs/aiofiles/aiofiles/threadpool/__init__.pyi index a84ae4105e8c..6731e1dcb403 100644 --- a/stubs/aiofiles/aiofiles/threadpool/__init__.pyi +++ b/stubs/aiofiles/aiofiles/threadpool/__init__.pyi @@ -99,7 +99,7 @@ def open( ) -> AiofilesContextManager[_UnknownAsyncBinaryIO]: ... stdin: AsyncTextIndirectIOWrapper -stdout: AsyncTextIndirectIOWrapper # type: ignore # ??? +stdout: AsyncTextIndirectIOWrapper # type: ignore # ??? stderr: AsyncTextIndirectIOWrapper stdin_bytes: AsyncIndirectBufferedIOBase stdout_bytes: AsyncIndirectBufferedIOBase From e004de496e6f1b864b9ee354db4f5d9350691da4 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 8 Apr 2026 15:53:18 +0200 Subject: [PATCH 09/13] Remove assert type --- stdlib/@tests/test_cases/check_functools.py | 2 -- stubs/aiofiles/aiofiles/threadpool/__init__.pyi | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/stdlib/@tests/test_cases/check_functools.py b/stdlib/@tests/test_cases/check_functools.py index 26763b46d6de..475405af1edb 100644 --- a/stdlib/@tests/test_cases/check_functools.py +++ b/stdlib/@tests/test_cases/check_functools.py @@ -119,8 +119,6 @@ def sd_fun(arg: object) -> str: def _(int_arg: int) -> str: return "" - assert_type(sd_fun, _SingleDispatchCallable[[object], str]) - sd_fun.dispatch(42) sd_fun.dispatch("") sd_fun.dispatch(1, 2) # type: ignore diff --git a/stubs/aiofiles/aiofiles/threadpool/__init__.pyi b/stubs/aiofiles/aiofiles/threadpool/__init__.pyi index 6731e1dcb403..71d2f47024ac 100644 --- a/stubs/aiofiles/aiofiles/threadpool/__init__.pyi +++ b/stubs/aiofiles/aiofiles/threadpool/__init__.pyi @@ -99,7 +99,7 @@ def open( ) -> AiofilesContextManager[_UnknownAsyncBinaryIO]: ... stdin: AsyncTextIndirectIOWrapper -stdout: AsyncTextIndirectIOWrapper # type: ignore # ??? +stdout: AsyncTextIndirectIOWrapper stderr: AsyncTextIndirectIOWrapper stdin_bytes: AsyncIndirectBufferedIOBase stdout_bytes: AsyncIndirectBufferedIOBase From ca066fb2c7f33f5d949f2a9660254d65efcb30ad Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 8 Apr 2026 15:56:18 +0200 Subject: [PATCH 10/13] Remove unused import --- stdlib/@tests/test_cases/check_functools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/@tests/test_cases/check_functools.py b/stdlib/@tests/test_cases/check_functools.py index 475405af1edb..5ce2bfad9599 100644 --- a/stdlib/@tests/test_cases/check_functools.py +++ b/stdlib/@tests/test_cases/check_functools.py @@ -1,6 +1,6 @@ from __future__ import annotations -from functools import _SingleDispatchCallable, cache, cached_property, singledispatch, wraps +from functools import cache, cached_property, singledispatch, wraps from typing import Callable, TypeVar from typing_extensions import ParamSpec, assert_type From ba3c5dac6060bb3184e2759530a48483eb7a312d Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 8 Apr 2026 16:28:10 +0200 Subject: [PATCH 11/13] Fix aiofiles problem --- stubs/aiofiles/aiofiles/threadpool/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/aiofiles/aiofiles/threadpool/__init__.pyi b/stubs/aiofiles/aiofiles/threadpool/__init__.pyi index 51cb1d2fd8bd..554cd6ea1109 100644 --- a/stubs/aiofiles/aiofiles/threadpool/__init__.pyi +++ b/stubs/aiofiles/aiofiles/threadpool/__init__.pyi @@ -99,7 +99,7 @@ def open( executor: Executor | None = None, ) -> AiofilesContextManager[_UnknownAsyncBinaryIO]: ... -wrap: _SingleDispatchCallable[Any] +wrap: _SingleDispatchCallable[Any, Any] stdin: AsyncTextIndirectIOWrapper stdout: AsyncTextIndirectIOWrapper From 5e23409d29e675ea72602007a8329f381c273cca Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 8 Apr 2026 16:31:45 +0200 Subject: [PATCH 12/13] Use defaults for `_SingleDispatchCallable` --- stdlib/functools.pyi | 47 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/stdlib/functools.pyi b/stdlib/functools.pyi index 16c62f9fe479..0ed4555d1457 100644 --- a/stdlib/functools.pyi +++ b/stdlib/functools.pyi @@ -26,7 +26,8 @@ __all__ = [ _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _S = TypeVar("_S") -_P = ParamSpec("_P") +_P = ParamSpec("_P", default=Any) +_R = TypeVar("_R", default=Any) _PWrapped = ParamSpec("_PWrapped") _RWrapped = TypeVar("_RWrapped") _PWrapper = ParamSpec("_PWrapper") @@ -191,68 +192,68 @@ class partialmethod(Generic[_T]): def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... @type_check_only -class _SingleDispatchCallable(Generic[_P, _T]): +class _SingleDispatchCallable(Generic[_P, _R]): # First argument pf the callables in the registry is the type to dispatch on. - registry: types.MappingProxyType[Any, Callable[Concatenate[Any, _P], _T]] - def dispatch(self, cls: type[_S]) -> Callable[Concatenate[_S, _P], _T]: ... + registry: types.MappingProxyType[Any, Callable[Concatenate[Any, _P], _R]] + def dispatch(self, cls: type[_S]) -> Callable[Concatenate[_S, _P], _R]: ... if sys.version_info >= (3, 11): # @fun.register(complex | str) # def _(arg, verbose=False): ... @overload def register( self, cls: types.UnionType, func: None = None - ) -> Callable[[Callable[Concatenate[_S, _P], _T]], Callable[Concatenate[_S, _P], _T]]: ... + ) -> Callable[[Callable[Concatenate[_S, _P], _R]], Callable[Concatenate[_S, _P], _R]]: ... # @fun.register(complex) # def _(arg, verbose=False): ... @overload def register( # type: ignore[overload-overlap] self, cls: type[_S], func: None = None - ) -> Callable[[Callable[Concatenate[_S, _P], _T]], Callable[Concatenate[_S, _P], _T]]: ... + ) -> Callable[[Callable[Concatenate[_S, _P], _R]], Callable[Concatenate[_S, _P], _R]]: ... # @fun.register # def _(arg: int, verbose=False): @overload - def register(self, cls: Callable[Concatenate[_S, _P], _T], func: None = None) -> Callable[Concatenate[_S, _P], _T]: ... + def register(self, cls: Callable[Concatenate[_S, _P], _R], func: None = None) -> Callable[Concatenate[_S, _P], _R]: ... if sys.version_info >= (3, 11): # fun.register(int, lambda x: x) @overload def register( - self, cls: types.UnionType, func: Callable[Concatenate[_S, _P], _T] - ) -> Callable[Concatenate[_S, _P], _T]: ... + self, cls: types.UnionType, func: Callable[Concatenate[_S, _P], _R] + ) -> Callable[Concatenate[_S, _P], _R]: ... # fun.register(int, lambda x: x) @overload - def register(self, cls: type[_S], func: Callable[Concatenate[_S, _P], _T]) -> Callable[Concatenate[_S, _P], _T]: ... + def register(self, cls: type[_S], func: Callable[Concatenate[_S, _P], _R]) -> Callable[Concatenate[_S, _P], _R]: ... def _clear_cache(self) -> None: ... - def __call__(self, arg: object, /, *args: _P.args, **kwargs: _P.kwargs) -> _T: ... + def __call__(self, arg: object, /, *args: _P.args, **kwargs: _P.kwargs) -> _R: ... -def singledispatch(func: Callable[Concatenate[object, _P], _T]) -> _SingleDispatchCallable[_P, _T]: ... +def singledispatch(func: Callable[Concatenate[object, _P], _R]) -> _SingleDispatchCallable[_P, _R]: ... -class singledispatchmethod(Generic[_P, _T]): - dispatcher: _SingleDispatchCallable[_P, _T] - func: Callable[_P, _T] - def __init__(self, func: Callable[Concatenate[object, _P], _T]) -> None: ... +class singledispatchmethod(Generic[_P, _R]): + dispatcher: _SingleDispatchCallable[_P, _R] + func: Callable[_P, _R] + def __init__(self, func: Callable[Concatenate[object, _P], _R]) -> None: ... @property def __isabstractmethod__(self) -> bool: ... if sys.version_info >= (3, 11): @overload def register( self, cls: types.UnionType, method: None = None - ) -> Callable[[Callable[Concatenate[_S, _P], _T]], Callable[Concatenate[_S, _P], _T]]: ... + ) -> Callable[[Callable[Concatenate[_S, _P], _R]], Callable[Concatenate[_S, _P], _R]]: ... @overload def register( # type: ignore[overload-overlap] self, cls: type[_S], method: None = None - ) -> Callable[[Callable[Concatenate[_S, _P], _T]], Callable[Concatenate[_S, _P], _T]]: ... + ) -> Callable[[Callable[Concatenate[_S, _P], _R]], Callable[Concatenate[_S, _P], _R]]: ... @overload - def register(self, cls: Callable[Concatenate[_S, _P], _T], method: None = None) -> Callable[Concatenate[_S, _P], _T]: ... + def register(self, cls: Callable[Concatenate[_S, _P], _R], method: None = None) -> Callable[Concatenate[_S, _P], _R]: ... if sys.version_info >= (3, 11): @overload def register( - self, cls: types.UnionType, method: Callable[Concatenate[_S, _P], _T] - ) -> Callable[Concatenate[_S, _P], _T]: ... + self, cls: types.UnionType, method: Callable[Concatenate[_S, _P], _R] + ) -> Callable[Concatenate[_S, _P], _R]: ... @overload - def register(self, cls: type[_S], method: Callable[Concatenate[_S, _P], _T]) -> Callable[Concatenate[_S, _P], _T]: ... - def __get__(self, obj: _S, cls: type[_S] | None = None) -> Callable[Concatenate[_S, _P], _T]: ... + def register(self, cls: type[_S], method: Callable[Concatenate[_S, _P], _R]) -> Callable[Concatenate[_S, _P], _R]: ... + def __get__(self, obj: _S, cls: type[_S] | None = None) -> Callable[Concatenate[_S, _P], _R]: ... class cached_property(Generic[_T_co]): func: Callable[[Any], _T_co] From 3cfe03a23064b650efa3f4fc86ab533ebcbd4908 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 8 Apr 2026 16:58:45 +0200 Subject: [PATCH 13/13] Fix default --- stdlib/functools.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/functools.pyi b/stdlib/functools.pyi index 0ed4555d1457..adbdd7d83cec 100644 --- a/stdlib/functools.pyi +++ b/stdlib/functools.pyi @@ -26,7 +26,7 @@ __all__ = [ _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _S = TypeVar("_S") -_P = ParamSpec("_P", default=Any) +_P = ParamSpec("_P", default=...) _R = TypeVar("_R", default=Any) _PWrapped = ParamSpec("_PWrapped") _RWrapped = TypeVar("_RWrapped")