Skip to content

Commit aa8865e

Browse files
committed
Preserve class signature after wrapping with @warnings.deprecated
1 parent 275056a commit aa8865e

File tree

1 file changed

+40
-3
lines changed

1 file changed

+40
-3
lines changed

Lib/warnings.py

+40-3
Original file line numberDiff line numberDiff line change
@@ -590,17 +590,49 @@ def __call__(self, arg, /):
590590
if category is None:
591591
arg.__deprecated__ = msg
592592
return arg
593-
elif isinstance(arg, type):
593+
594+
def update_signature(original_func):
595+
# Ensure that the signature of the decorated callable matches the original one
596+
597+
def wrapper(func):
598+
import inspect
599+
600+
try:
601+
original_signature = inspect.signature(original_func)
602+
except ValueError:
603+
pass
604+
else:
605+
signature = inspect.signature(func)
606+
if signature != original_signature:
607+
try:
608+
func.__text_signature__ = str(original_signature)
609+
except (AttributeError, TypeError):
610+
pass
611+
612+
return func
613+
614+
return wrapper
615+
616+
if isinstance(arg, type):
594617
import functools
595618
from types import MethodType
596619

597620
original_new = arg.__new__
621+
is_object_new = original_new is object.__new__
622+
if is_object_new:
623+
def wraps(wrapped):
624+
def identity(func):
625+
return func
626+
return identity
627+
else:
628+
wraps = functools.wraps
598629

599-
@functools.wraps(original_new)
630+
@update_signature(arg)
631+
@wraps(original_new)
600632
def __new__(cls, *args, **kwargs):
601633
if cls is arg:
602634
warn(msg, category=category, stacklevel=stacklevel + 1)
603-
if original_new is not object.__new__:
635+
if not is_object_new:
604636
return original_new(cls, *args, **kwargs)
605637
# Mirrors a similar check in object.__new__.
606638
elif cls.__init__ is object.__init__ and (args or kwargs):
@@ -616,15 +648,19 @@ def __new__(cls, *args, **kwargs):
616648
if isinstance(original_init_subclass, MethodType):
617649
original_init_subclass = original_init_subclass.__func__
618650

651+
@update_signature(original_init_subclass)
619652
@functools.wraps(original_init_subclass)
620653
def __init_subclass__(*args, **kwargs):
621654
warn(msg, category=category, stacklevel=stacklevel + 1)
622655
return original_init_subclass(*args, **kwargs)
623656

624657
arg.__init_subclass__ = classmethod(__init_subclass__)
658+
625659
# Or otherwise, which likely means it's a builtin such as
626660
# object's implementation of __init_subclass__.
627661
else:
662+
663+
@update_signature(original_init_subclass)
628664
@functools.wraps(original_init_subclass)
629665
def __init_subclass__(*args, **kwargs):
630666
warn(msg, category=category, stacklevel=stacklevel + 1)
@@ -639,6 +675,7 @@ def __init_subclass__(*args, **kwargs):
639675
import functools
640676
import inspect
641677

678+
@update_signature(arg)
642679
@functools.wraps(arg)
643680
def wrapper(*args, **kwargs):
644681
warn(msg, category=category, stacklevel=stacklevel + 1)

0 commit comments

Comments
 (0)