Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

warnings.deprecated doesn't work well with pydoc #128772

Open
Viicos opened this issue Jan 13, 2025 · 0 comments
Open

warnings.deprecated doesn't work well with pydoc #128772

Viicos opened this issue Jan 13, 2025 · 0 comments
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@Viicos
Copy link
Contributor

Viicos commented Jan 13, 2025

Bug report

Bug description:

Steps to reproduce:

  • Create a module (testmodule.py):
    from warnings import deprecated
    
    @deprecated("Test")
    class A: pass
  • In the Python shell, run:
    import testmodule
    help(testmodule) 

This will raise a TypeError:

  File "/fakepath/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/pydoc.py", line 245, in parentname
    return object.__module__ + '.' + name
           ~~~~~~~~~~~~~~~~~~^~~~~
TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'

warnings.deprecated is defining custom __new__ and __init_subclass__ methods:

cpython/Lib/warnings.py

Lines 588 to 615 in 6e1e780

original_new = arg.__new__
@functools.wraps(original_new)
def __new__(cls, *args, **kwargs):
if cls is arg:
warn(msg, category=category, stacklevel=stacklevel + 1)
if original_new is not object.__new__:
return original_new(cls, *args, **kwargs)
# Mirrors a similar check in object.__new__.
elif cls.__init__ is object.__init__ and (args or kwargs):
raise TypeError(f"{cls.__name__}() takes no arguments")
else:
return original_new(cls)
arg.__new__ = staticmethod(__new__)
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)
if isinstance(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)
return original_init_subclass(*args, **kwargs)
arg.__init_subclass__ = classmethod(__init_subclass__)

and because these methods don't have a __module__ available (maybe they should?), we end up with the above exception.

Should we special case deprecated classes and other objects using the warnings.deprecated decorator in pydoc to display specific information? I don't think it's relevant to show the __new__ and __init_subclass__ overridden methods in the documentation output.

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

2 participants