Skip to content

Commit 9c4bfd5

Browse files
authored
Updated functools.wraps and functools.update_wrapper (#6670)
Updated functools.wraps and functools.update_wrapper to use ParamSpec to preserve signatures of wrapped and wrapper functions.
1 parent fee5f1b commit 9c4bfd5

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

stdlib/functools.pyi

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import sys
22
import types
3-
from _typeshed import IdentityFunction, SupportsAllComparisons, SupportsItems
3+
from _typeshed import SupportsAllComparisons, SupportsItems
44
from collections.abc import Callable, Hashable, Iterable, Sequence, Sized
55
from typing import Any, Generic, NamedTuple, TypeVar, overload
6-
from typing_extensions import Literal, Self, TypeAlias, final
6+
from typing_extensions import Literal, ParamSpec, Self, TypeAlias, final
77

88
if sys.version_info >= (3, 9):
99
from types import GenericAlias
@@ -28,10 +28,12 @@ if sys.version_info >= (3, 8):
2828
if sys.version_info >= (3, 9):
2929
__all__ += ["cache"]
3030

31-
_AnyCallable: TypeAlias = Callable[..., object]
32-
3331
_T = TypeVar("_T")
3432
_S = TypeVar("_S")
33+
_PWrapped = ParamSpec("_PWrapped")
34+
_RWrapped = TypeVar("_RWrapped")
35+
_PWrapper = ParamSpec("_PWrapper")
36+
_RWapper = TypeVar("_RWapper")
3537

3638
@overload
3739
def reduce(function: Callable[[_T, _S], _T], sequence: Iterable[_S], initial: _T) -> _T: ...
@@ -67,8 +69,22 @@ WRAPPER_ASSIGNMENTS: tuple[
6769
]
6870
WRAPPER_UPDATES: tuple[Literal["__dict__"]]
6971

70-
def update_wrapper(wrapper: _T, wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ...) -> _T: ...
71-
def wraps(wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ...) -> IdentityFunction: ...
72+
class _Wrapped(Generic[_PWrapped, _RWrapped, _PWrapper, _RWapper]):
73+
__wrapped__: Callable[_PWrapped, _RWrapped]
74+
def __call__(self, *args: _PWrapper.args, **kwargs: _PWrapper.kwargs) -> _RWapper: ...
75+
76+
class _Wrapper(Generic[_PWrapped, _RWrapped]):
77+
def __call__(self, f: Callable[_PWrapper, _RWapper]) -> _Wrapped[_PWrapped, _RWrapped, _PWrapper, _RWapper]: ...
78+
79+
def update_wrapper(
80+
wrapper: Callable[_PWrapper, _RWapper],
81+
wrapped: Callable[_PWrapped, _RWrapped],
82+
assigned: Sequence[str] = ...,
83+
updated: Sequence[str] = ...,
84+
) -> _Wrapped[_PWrapped, _RWrapped, _PWrapper, _RWapper]: ...
85+
def wraps(
86+
wrapped: Callable[_PWrapped, _RWrapped], assigned: Sequence[str] = ..., updated: Sequence[str] = ...
87+
) -> _Wrapper[_PWrapped, _RWrapped]: ...
7288
def total_ordering(cls: type[_T]) -> type[_T]: ...
7389
def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], SupportsAllComparisons]: ...
7490

0 commit comments

Comments
 (0)