From 9a44e4527704f17cca158b260b68a8dd37f95970 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 1 Nov 2020 18:23:24 +0900 Subject: [PATCH 1/2] Fix #7613: autodoc: autodoc does not respect __signature__ of the class --- CHANGES | 1 + sphinx/ext/autodoc/__init__.py | 7 ++- .../roots/test-ext-autodoc/target/classes.py | 11 ++++ tests/test_ext_autodoc_autoclass.py | 50 +++++++++++++++++++ tests/test_ext_autodoc_autofunction.py | 8 +++ 5 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 tests/test_ext_autodoc_autoclass.py diff --git a/CHANGES b/CHANGES index ca79187f7aa..f181af9d37b 100644 --- a/CHANGES +++ b/CHANGES @@ -52,6 +52,7 @@ Bugs fixed * #7786: autodoc: can't detect overloaded methods defined in other file * #8294: autodoc: single-string __slots__ is not handled correctly * #7785: autodoc: autodoc_typehints='none' does not effect to overloaded functions +* #7613: autodoc: autodoc does not respect __signature__ of the class * #8192: napoleon: description is disappeared when it contains inline literals * #8142: napoleon: Potential of regex denial of service in google style docs * #8169: LaTeX: pxjahyper loaded even when latex_engine is not platex diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 7343d41b6a9..3f249588228 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1391,7 +1391,12 @@ def get_user_defined_function_or_method(obj: Any, attr: str) -> Any: # This sequence is copied from inspect._signature_from_callable. # ValueError means that no signature could be found, so we keep going. - # First, let's see if it has an overloaded __call__ defined + # First, we check the obj has a __signature__ attribute + if (hasattr(self.object, '__signature__') and + isinstance(self.object.__signature__, Signature)): + return None, None, self.object.__signature__ + + # Next, let's see if it has an overloaded __call__ defined # in its metaclass call = get_user_defined_function_or_method(type(self.object), '__call__') diff --git a/tests/roots/test-ext-autodoc/target/classes.py b/tests/roots/test-ext-autodoc/target/classes.py index dc471a6f39c..52c23748b77 100644 --- a/tests/roots/test-ext-autodoc/target/classes.py +++ b/tests/roots/test-ext-autodoc/target/classes.py @@ -1,3 +1,6 @@ +from inspect import Parameter, Signature + + class Foo: pass @@ -10,3 +13,11 @@ def __init__(self, x, y): class Baz: def __new__(cls, x, y): pass + + +class Qux: + __signature__ = Signature(parameters=[Parameter('foo', Parameter.POSITIONAL_OR_KEYWORD), + Parameter('bar', Parameter.POSITIONAL_OR_KEYWORD)]) + + def __init__(self, x, y): + pass diff --git a/tests/test_ext_autodoc_autoclass.py b/tests/test_ext_autodoc_autoclass.py new file mode 100644 index 00000000000..89a79c2c7c1 --- /dev/null +++ b/tests/test_ext_autodoc_autoclass.py @@ -0,0 +1,50 @@ +""" + 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_classes(app): + actual = do_autodoc(app, 'function', 'target.classes.Foo') + assert list(actual) == [ + '', + '.. py:function:: Foo()', + ' :module: target.classes', + '', + ] + + actual = do_autodoc(app, 'function', 'target.classes.Bar') + assert list(actual) == [ + '', + '.. py:function:: Bar(x, y)', + ' :module: target.classes', + '', + ] + + actual = do_autodoc(app, 'function', 'target.classes.Baz') + assert list(actual) == [ + '', + '.. py:function:: Baz(x, y)', + ' :module: target.classes', + '', + ] + + actual = do_autodoc(app, 'function', 'target.classes.Qux') + assert list(actual) == [ + '', + '.. py:function:: Qux(foo, bar)', + ' :module: target.classes', + '', + ] + diff --git a/tests/test_ext_autodoc_autofunction.py b/tests/test_ext_autodoc_autofunction.py index bb292bc6a30..64f6e8db3dd 100644 --- a/tests/test_ext_autodoc_autofunction.py +++ b/tests/test_ext_autodoc_autofunction.py @@ -40,6 +40,14 @@ def test_classes(app): '', ] + actual = do_autodoc(app, 'function', 'target.classes.Qux') + assert list(actual) == [ + '', + '.. py:function:: Qux(foo, bar)', + ' :module: target.classes', + '', + ] + @pytest.mark.sphinx('html', testroot='ext-autodoc') def test_callable(app): From 9f1c89dd9d5139dfa8af43f9b552d549fb93d910 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 3 Nov 2020 11:39:44 +0900 Subject: [PATCH 2/2] Update CHANGES for PR #8355 --- CHANGES | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 3e5836a154b..54f4bdc3d2e 100644 --- a/CHANGES +++ b/CHANGES @@ -41,6 +41,8 @@ Features added Bugs fixed ---------- +* #7613: autodoc: autodoc does not respect __signature__ of the class + Testing -------- @@ -94,7 +96,6 @@ Bugs fixed * #7786: autodoc: can't detect overloaded methods defined in other file * #8294: autodoc: single-string __slots__ is not handled correctly * #7785: autodoc: autodoc_typehints='none' does not effect to overloaded functions -* #7613: autodoc: autodoc does not respect __signature__ of the class * #8192: napoleon: description is disappeared when it contains inline literals * #8142: napoleon: Potential of regex denial of service in google style docs * #8169: LaTeX: pxjahyper loaded even when latex_engine is not platex