From 95bb8feb32525011521d4ec8e627769d2efacd4c Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 21 Sep 2020 11:04:24 +0900 Subject: [PATCH] Fix #8219: autodoc: A signature of constructor of generic class is incorrect Ignore the signature of typing.Generic.__new__() to get correct a signature of the constructor from a subclass. --- CHANGES | 1 + sphinx/ext/autodoc/__init__.py | 15 ++++++++--- .../roots/test-ext-autodoc/target/classes.py | 11 ++++++++ tests/test_ext_autodoc_autoclass.py | 25 +++++++++++++++++++ 4 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 tests/test_ext_autodoc_autoclass.py diff --git a/CHANGES b/CHANGES index 738baf34159..9c319c758fd 100644 --- a/CHANGES +++ b/CHANGES @@ -25,6 +25,7 @@ Bugs fixed * #8143: autodoc: AttributeError is raised when False value is passed to autodoc_default_options * #8103: autodoc: functools.cached_property is not considered as a property +* #8219: autodoc: A signature of constructor of generic class is incorrect * #8192: napoleon: description is disappeared when it contains inline literals * #8169: LaTeX: pxjahyper loaded even when latex_engine is not platex * #8093: The highlight warning has wrong location in some builders (LaTeX, diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index ed02c2c9087..00dafe7c85b 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1312,13 +1312,17 @@ def format_args(self, **kwargs: Any) -> Any: return None -# Types which have confusing metaclass signatures it would be best not to show. -# These are listed by name, rather than storing the objects themselves, to avoid -# needing to import the modules. +# Types which have confusing metaclass signatures and superclass signatures it +# would be best not to show. These are listed by name, rather than storing the +# objects themselves, to avoid needing to import the modules. _METACLASS_CALL_BLACKLIST = [ 'enum.EnumMeta.__call__', ] +_SUPERCLASS_NEW_BLACKLIST = [ + 'typing.Generic.__new__', +] + class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: ignore """ @@ -1388,6 +1392,11 @@ def get_user_defined_function_or_method(obj: Any, attr: str) -> Any: # Now we check if the 'obj' class has a '__new__' method new = get_user_defined_function_or_method(self.object, '__new__') + + if new is not None: + if "{0.__module__}.{0.__qualname__}".format(new) in _SUPERCLASS_NEW_BLACKLIST: + new = None + if new is not None: self.env.app.emit('autodoc-before-process-signature', new, True) try: diff --git a/tests/roots/test-ext-autodoc/target/classes.py b/tests/roots/test-ext-autodoc/target/classes.py index dc471a6f39c..22c401e013d 100644 --- a/tests/roots/test-ext-autodoc/target/classes.py +++ b/tests/roots/test-ext-autodoc/target/classes.py @@ -1,3 +1,9 @@ +from typing import Generic, TypeVar + + +T = TypeVar("T") + + class Foo: pass @@ -10,3 +16,8 @@ def __init__(self, x, y): class Baz: def __new__(cls, x, y): pass + + +class Qux(Generic[T]): + 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..99918879309 --- /dev/null +++ b/tests/test_ext_autodoc_autoclass.py @@ -0,0 +1,25 @@ +""" + 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_generic_class(app): + actual = do_autodoc(app, 'class', 'target.classes.Qux') + assert list(actual) == [ + '', + '.. py:class:: Qux(x, y)', + ' :module: target.classes', + '', + ]