diff --git a/CHANGES b/CHANGES index 99e5cdaf9b..a5f5acd565 100644 --- a/CHANGES +++ b/CHANGES @@ -7,9 +7,14 @@ Dependencies Incompatible changes -------------------- +* #8105: autodoc: the signature of class constructor will be shown for decorated + classes, not a signature of decorator + Deprecated ---------- +* The ``follow_wrapped`` argument of ``sphinx.util.inspect.signature()`` + Features added -------------- @@ -20,6 +25,9 @@ Features added Bugs fixed ---------- +* #8105: autodoc: the signature of class constructor is incorrect if the class + is decorated + Testing -------- diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst index 2bb8aebfd6..797648a1ac 100644 --- a/doc/extdev/deprecated.rst +++ b/doc/extdev/deprecated.rst @@ -26,6 +26,12 @@ The following is a list of deprecated interfaces. - (will be) Removed - Alternatives + + * - The ``follow_wrapped`` argument of ``sphinx.util.inspect.signature()`` + - 3.4 + - 5.0 + - N/A + * - ``sphinx.builders.latex.LaTeXBuilder.usepackages`` - 3.3 - 5.0 diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 7343d41b6a..d1e9726b7b 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1213,7 +1213,7 @@ def format_args(self, **kwargs: Any) -> str: try: self.env.app.emit('autodoc-before-process-signature', self.object, False) - sig = inspect.signature(self.object, follow_wrapped=True, + sig = inspect.signature(self.object, type_aliases=self.env.config.autodoc_type_aliases) args = stringify_signature(sig, **kwargs) except TypeError as exc: @@ -1848,7 +1848,6 @@ def format_args(self, **kwargs: Any) -> str: else: self.env.app.emit('autodoc-before-process-signature', self.object, True) sig = inspect.signature(self.object, bound_method=True, - follow_wrapped=True, type_aliases=self.env.config.autodoc_type_aliases) args = stringify_signature(sig, **kwargs) except TypeError as exc: diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index f2cd8070bb..4f8e15c046 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -439,14 +439,20 @@ def _should_unwrap(subject: Callable) -> bool: return False -def signature(subject: Callable, bound_method: bool = False, follow_wrapped: bool = False, +def signature(subject: Callable, bound_method: bool = False, follow_wrapped: bool = None, type_aliases: Dict = {}) -> inspect.Signature: """Return a Signature object for the given *subject*. :param bound_method: Specify *subject* is a bound method or not :param follow_wrapped: Same as ``inspect.signature()``. - Defaults to ``False`` (get a signature of *subject*). """ + + if follow_wrapped is None: + follow_wrapped = True + else: + warnings.warn('The follow_wrapped argument of sphinx.util.inspect.signature() is ' + 'deprecated', RemovedInSphinx50Warning, stacklevel=2) + try: try: if _should_unwrap(subject): diff --git a/tests/roots/test-ext-autodoc/target/decorator.py b/tests/roots/test-ext-autodoc/target/decorator.py index 61398b324e..faad3fff95 100644 --- a/tests/roots/test-ext-autodoc/target/decorator.py +++ b/tests/roots/test-ext-autodoc/target/decorator.py @@ -29,3 +29,25 @@ class Bar: @deco1 def meth(self, name=None, age=None): pass + + +class Baz: + @deco1 + def __init__(self, name=None, age=None): + pass + + +class Qux: + @deco1 + def __new__(self, name=None, age=None): + pass + + +class _Metaclass(type): + @deco1 + def __call__(self, name=None, age=None): + pass + + +class Quux(metaclass=_Metaclass): + pass diff --git a/tests/test_ext_autodoc_autoclass.py b/tests/test_ext_autodoc_autoclass.py new file mode 100644 index 0000000000..66724d5a3d --- /dev/null +++ b/tests/test_ext_autodoc_autoclass.py @@ -0,0 +1,41 @@ +""" + test_ext_autodoc_autoclass + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Test the autodoc extension. This tests mainly the Documenters; the auto + directives are tested in a test source file translated by test_build. + + :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import pytest + +from test_ext_autodoc import do_autodoc + + +@pytest.mark.sphinx('html', testroot='ext-autodoc') +def test_decorators(app): + actual = do_autodoc(app, 'class', 'target.decorator.Baz') + assert list(actual) == [ + '', + '.. py:class:: Baz(name=None, age=None)', + ' :module: target.decorator', + '', + ] + + actual = do_autodoc(app, 'class', 'target.decorator.Qux') + assert list(actual) == [ + '', + '.. py:class:: Qux(name=None, age=None)', + ' :module: target.decorator', + '', + ] + + actual = do_autodoc(app, 'class', 'target.decorator.Quux') + assert list(actual) == [ + '', + '.. py:class:: Quux(name=None, age=None)', + ' :module: target.decorator', + '', + ]