From a00fcba1e77ac944276b8c4ad0a31b7b05ded59f Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 13 Mar 2024 16:42:20 +0000 Subject: [PATCH] Revert "Revert use of `ParamSpec` for `functools.wraps`" (#16942) ParamSpec support has improved so it doesn't seem necessary to revert the changes any more. --- misc/generate_changelog.py | 1 - misc/sync-typeshed.py | 1 - mypy/typeshed/stdlib/functools.pyi | 40 +++++++++++++++++++----------- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/misc/generate_changelog.py b/misc/generate_changelog.py index 7c7f28b6eeb7..ebab6c569152 100644 --- a/misc/generate_changelog.py +++ b/misc/generate_changelog.py @@ -79,7 +79,6 @@ def filter_omitted_commits(commits: list[CommitInfo]) -> list[CommitInfo]: "Revert sum literal integer change", "Remove use of LiteralString in builtins", "Revert typeshed ctypes change", - "Revert use of `ParamSpec` for `functools.wraps`", ) ): # These are generated by a typeshed sync. diff --git a/misc/sync-typeshed.py b/misc/sync-typeshed.py index ee6414ab7b19..56bc1624d5d0 100644 --- a/misc/sync-typeshed.py +++ b/misc/sync-typeshed.py @@ -182,7 +182,6 @@ def main() -> None: "d25e4a9eb", # LiteralString reverts "d132999ba", # sum reverts "dd12a2d81", # ctypes reverts - "0dd4b6f75", # ParamSpec for functools.wraps ] for commit in commits_to_cherry_pick: try: diff --git a/mypy/typeshed/stdlib/functools.pyi b/mypy/typeshed/stdlib/functools.pyi index 991182486113..d3f702bcef4f 100644 --- a/mypy/typeshed/stdlib/functools.pyi +++ b/mypy/typeshed/stdlib/functools.pyi @@ -1,9 +1,9 @@ import sys import types -from _typeshed import IdentityFunction, SupportsAllComparisons, SupportsItems +from _typeshed import SupportsAllComparisons, SupportsItems from collections.abc import Callable, Hashable, Iterable, Sequence, Sized from typing import Any, Generic, Literal, NamedTuple, TypedDict, TypeVar, final, overload -from typing_extensions import Self, TypeAlias +from typing_extensions import ParamSpec, Self, TypeAlias if sys.version_info >= (3, 9): from types import GenericAlias @@ -27,11 +27,13 @@ __all__ = [ if sys.version_info >= (3, 9): __all__ += ["cache"] -_AnyCallable: TypeAlias = Callable[..., object] - _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _S = TypeVar("_S") +_PWrapped = ParamSpec("_PWrapped") +_RWrapped = TypeVar("_RWrapped") +_PWrapper = ParamSpec("_PWrapper") +_RWrapper = TypeVar("_RWrapper") @overload def reduce(__function: Callable[[_T, _S], _T], __sequence: Iterable[_S], __initial: _T) -> _T: ... @@ -81,31 +83,41 @@ else: ] WRAPPER_UPDATES: tuple[Literal["__dict__"]] +class _Wrapped(Generic[_PWrapped, _RWrapped, _PWrapper, _RWrapper]): + __wrapped__: Callable[_PWrapped, _RWrapped] + def __call__(self, *args: _PWrapper.args, **kwargs: _PWrapper.kwargs) -> _RWrapper: ... + # as with ``Callable``, we'll assume that these attributes exist + __name__: str + __qualname__: str + +class _Wrapper(Generic[_PWrapped, _RWrapped]): + def __call__(self, f: Callable[_PWrapper, _RWrapper]) -> _Wrapped[_PWrapped, _RWrapped, _PWrapper, _RWrapper]: ... + if sys.version_info >= (3, 12): def update_wrapper( - wrapper: _T, - wrapped: _AnyCallable, + wrapper: Callable[_PWrapper, _RWrapper], + wrapped: Callable[_PWrapped, _RWrapped], assigned: Sequence[str] = ("__module__", "__name__", "__qualname__", "__doc__", "__annotations__", "__type_params__"), updated: Sequence[str] = ("__dict__",), - ) -> _T: ... + ) -> _Wrapped[_PWrapped, _RWrapped, _PWrapper, _RWrapper]: ... def wraps( - wrapped: _AnyCallable, + wrapped: Callable[_PWrapped, _RWrapped], assigned: Sequence[str] = ("__module__", "__name__", "__qualname__", "__doc__", "__annotations__", "__type_params__"), updated: Sequence[str] = ("__dict__",), - ) -> IdentityFunction: ... + ) -> _Wrapper[_PWrapped, _RWrapped]: ... else: def update_wrapper( - wrapper: _T, - wrapped: _AnyCallable, + wrapper: Callable[_PWrapper, _RWrapper], + wrapped: Callable[_PWrapped, _RWrapped], assigned: Sequence[str] = ("__module__", "__name__", "__qualname__", "__doc__", "__annotations__"), updated: Sequence[str] = ("__dict__",), - ) -> _T: ... + ) -> _Wrapped[_PWrapped, _RWrapped, _PWrapper, _RWrapper]: ... def wraps( - wrapped: _AnyCallable, + wrapped: Callable[_PWrapped, _RWrapped], assigned: Sequence[str] = ("__module__", "__name__", "__qualname__", "__doc__", "__annotations__"), updated: Sequence[str] = ("__dict__",), - ) -> IdentityFunction: ... + ) -> _Wrapper[_PWrapped, _RWrapped]: ... def total_ordering(cls: type[_T]) -> type[_T]: ... def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], SupportsAllComparisons]: ...