diff --git a/CHANGES b/CHANGES index 4a8fa77d63f..fc3c7eb66d3 100644 --- a/CHANGES +++ b/CHANGES @@ -86,6 +86,8 @@ Features added * #744: autodoc: Support abstractmethod * #6325: autodoc: Support attributes in __slots__. For dict-style __slots__, autodoc considers values as a docstring of the attribute +* #6361: autodoc: Add :confval:`autodoc_typehints` to suppress typehints from + signature * #6212 autosummary: Add :confval:`autosummary_imported_members` to display imported members on autosummary * #6271: ``make clean`` is catastrophically broken if building into '.' diff --git a/doc/usage/extensions/autodoc.rst b/doc/usage/extensions/autodoc.rst index 00cca4f0a1d..8fdee214b79 100644 --- a/doc/usage/extensions/autodoc.rst +++ b/doc/usage/extensions/autodoc.rst @@ -429,6 +429,16 @@ There are also config values that you can set: This config value only requires to declare the top-level modules that should be mocked. +.. confval:: autodoc_typehints + + This value controls how to represents typehints. The setting takes the + following values: + + * ``'signature'`` -- Show typehints as its signature (default) + * ``'none'`` -- Do not show typehints + + .. versionadded: 2.1 + .. confval:: autodoc_warningiserror This value controls the behavior of :option:`sphinx-build -W` during diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 65a292b6a91..7172553ac64 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -17,6 +17,7 @@ from docutils.statemachine import StringList import sphinx +from sphinx.config import ENUM from sphinx.deprecation import ( RemovedInSphinx30Warning, RemovedInSphinx40Warning, deprecated_alias ) @@ -1007,6 +1008,9 @@ def can_document_member(cls, member, membername, isattr, parent): def format_args(self, **kwargs): # type: (Any) -> str + if self.env.config.autodoc_typehints == 'none': + kwargs.setdefault('show_annotation', False) + if inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object): # cannot introspect arguments of a C function or method return None @@ -1106,6 +1110,9 @@ def import_object(self): def format_args(self, **kwargs): # type: (Any) -> str + if self.env.config.autodoc_typehints == 'none': + kwargs.setdefault('show_annotation', False) + # for classes, the relevant signature is the __init__ method's initmeth = self.get_attr(self.object, '__init__', None) # classes without __init__ method, default __init__ or @@ -1320,6 +1327,9 @@ def import_object(self): def format_args(self, **kwargs): # type: (Any) -> str + if self.env.config.autodoc_typehints == 'none': + kwargs.setdefault('show_annotation', False) + if inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object): # can never get arguments of a C function or method return None @@ -1612,6 +1622,7 @@ def setup(app): app.add_config_value('autodoc_default_options', {}, True) app.add_config_value('autodoc_docstring_signature', True, True) app.add_config_value('autodoc_mock_imports', [], True) + app.add_config_value('autodoc_typehints', "signature", True, ENUM("signature", "none")) app.add_config_value('autodoc_warningiserror', True, True) app.add_config_value('autodoc_inherit_docstrings', True, True) app.add_event('autodoc-process-docstring') diff --git a/tests/roots/test-ext-autodoc/target/typehints.py b/tests/roots/test-ext-autodoc/target/typehints.py new file mode 100644 index 00000000000..eedaab3b997 --- /dev/null +++ b/tests/roots/test-ext-autodoc/target/typehints.py @@ -0,0 +1,10 @@ +def incr(a: int, b: int = 1) -> int: + return a + b + + +class Math: + def __init__(self, s: str, o: object = None) -> None: + pass + + def incr(self, a: int, b: int = 1) -> int: + return a + b diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 8f08bb7fa12..f6f5a618cf9 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -1689,6 +1689,58 @@ def test_partialmethod(app): assert list(actual) == expected +@pytest.mark.sphinx('html', testroot='ext-autodoc') +def test_autodoc_typehints_signature(app): + app.config.autodoc_typehints = "signature" + + options = {"members": None, + "undoc-members": True} + actual = do_autodoc(app, 'module', 'target.typehints', options) + assert list(actual) == [ + '', + '.. py:module:: target.typehints', + '', + '', + '.. py:class:: Math(s: str, o: object = None)', + ' :module: target.typehints', + '', + ' ', + ' .. py:method:: Math.incr(a: int, b: int = 1) -> int', + ' :module: target.typehints', + ' ', + '', + '.. py:function:: incr(a: int, b: int = 1) -> int', + ' :module: target.typehints', + '' + ] + + +@pytest.mark.sphinx('html', testroot='ext-autodoc') +def test_autodoc_typehints_none(app): + app.config.autodoc_typehints = "none" + + options = {"members": None, + "undoc-members": True} + actual = do_autodoc(app, 'module', 'target.typehints', options) + assert list(actual) == [ + '', + '.. py:module:: target.typehints', + '', + '', + '.. py:class:: Math(s, o = None)', + ' :module: target.typehints', + '', + ' ', + ' .. py:method:: Math.incr(a, b = 1) -> int', + ' :module: target.typehints', + ' ', + '', + '.. py:function:: incr(a, b = 1) -> int', + ' :module: target.typehints', + '' + ] + + @pytest.mark.sphinx('html', testroot='ext-autodoc') @pytest.mark.filterwarnings('ignore:autodoc_default_flags is now deprecated.') def test_merge_autodoc_default_flags1(app):