Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.7k
Description
Bug report
Bug description:
PEP 702 – Marking deprecations using the type system introduces a new APIwarnings.deprecated for deprecation.
While decorating a class object, it will update the__new__ method:
Lines 589 to 603 in2268289
| original_new=arg.__new__ | |
| @functools.wraps(original_new) | |
| def__new__(cls,*args,**kwargs): | |
| ifclsisarg: | |
| warn(msg,category=category,stacklevel=stacklevel+1) | |
| iforiginal_newisnotobject.__new__: | |
| returnoriginal_new(cls,*args,**kwargs) | |
| # Mirrors a similar check in object.__new__. | |
| elifcls.__init__isobject.__init__and (argsorkwargs): | |
| raiseTypeError(f"{cls.__name__}() takes no arguments") | |
| else: | |
| returnoriginal_new(cls) | |
| arg.__new__=staticmethod(__new__) |
and the__init_subclass__ method:
Lines 605 to 625 in2268289
| original_init_subclass=arg.__init_subclass__ | |
| # We need slightly different behavior if __init_subclass__ | |
| # is a bound method (likely if it was implemented in Python) | |
| ifisinstance(original_init_subclass,MethodType): | |
| original_init_subclass=original_init_subclass.__func__ | |
| @functools.wraps(original_init_subclass) | |
| def__init_subclass__(*args,**kwargs): | |
| warn(msg,category=category,stacklevel=stacklevel+1) | |
| returnoriginal_init_subclass(*args,**kwargs) | |
| arg.__init_subclass__=classmethod(__init_subclass__) | |
| # Or otherwise, which likely means it's a builtin such as | |
| # object's implementation of __init_subclass__. | |
| else: | |
| @functools.wraps(original_init_subclass) | |
| def__init_subclass__(*args,**kwargs): | |
| warn(msg,category=category,stacklevel=stacklevel+1) | |
| returnoriginal_init_subclass(*args,**kwargs) | |
| arg.__init_subclass__=__init_subclass__ |
For a class (cls) that does not implement the__new__ and__init_subclass__ methods, thewarnings.deprecated decorator will generate these two methods (based onobject.__new__ andtype.__init_subclass__ ) and assign them tocls.__dict__.
However, if users want to inspect the methods incls.__dict__, theinspect module fails to get the correct definition ofcls.__new__. It is defined inwarnings.py rather thanobject.__new__.
# test.pyfromwarningsimportdeprecated# or from typing_extensions import deprecatedclassFoo:def__new__(cls):returnsuper().__new__(cls)@deprecated("test")classBar:pass
In [1]:importinspectIn [2]:fromtestimportFoo,BarIn [3]:inspect.getsourcelines(Foo.__new__)Out[3]: ([' def __new__(cls):\n',' return super().__new__(cls)\n'],7)In [4]:inspect.getsourcelines(Bar.__new__)TypeError:module,class,method,function,traceback,frame,orcodeobjectwasexpected,gotbuiltin_function_or_method
Expected to haveinspect.getsourcelines(Bar.__new__) to be source code in/.../lib/python3.13/warnings.py.
CPython versions tested on:
3.13
Operating systems tested on:
Linux