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

autodoc.typehints can accurately represent overloads #9185

Merged
merged 2 commits into from May 11, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 14 additions & 2 deletions doc/usage/extensions/autodoc.rst
Expand Up @@ -573,15 +573,27 @@ There are also config values that you can set:
This value controls how to represent typehints. The setting takes the
following values:

* ``'signature'`` -- Show typehints as its signature (default)
* ``'description'`` -- Show typehints as content of function or method
* ``'signature'`` -- Show typehints in the signature (default)
* ``'description'`` -- Show typehints as content of the function or method
The typehints of overloaded functions or methods will still be represented
in the signature.
* ``'none'`` -- Do not show typehints
* ``'both'`` -- Show typehints in the signature and as content of
the function or method

Overloaded functions or methods will not have typehints included in the
description because it is impossible to accurately represent all possible
overloads as a list of parameters.

.. versionadded:: 2.1
.. versionadded:: 3.0

New option ``'description'`` is added.

.. versionadded:: 4.0
tk0miya marked this conversation as resolved.
Show resolved Hide resolved

New option ``'both'`` is added.

.. confval:: autodoc_typehints_description_target

This value controls whether the types of undocumented parameters and return
Expand Down
8 changes: 4 additions & 4 deletions sphinx/ext/autodoc/__init__.py
Expand Up @@ -1314,7 +1314,7 @@ def format_signature(self, **kwargs: Any) -> str:
sigs = []
if (self.analyzer and
'.'.join(self.objpath) in self.analyzer.overloads and
self.config.autodoc_typehints == 'signature'):
self.config.autodoc_typehints != 'none'):
# Use signatures for overloaded functions instead of the implementation function.
overloaded = True
else:
Expand Down Expand Up @@ -1560,7 +1560,7 @@ def format_signature(self, **kwargs: Any) -> str:
sigs = []

overloads = self.get_overloaded_signatures()
if overloads and self.config.autodoc_typehints == 'signature':
if overloads and self.config.autodoc_typehints != 'none':
# Use signatures for overloaded methods instead of the implementation method.
method = safe_getattr(self._signature_class, self._signature_method_name, None)
__globals__ = safe_getattr(method, '__globals__', {})
Expand Down Expand Up @@ -2109,7 +2109,7 @@ def format_signature(self, **kwargs: Any) -> str:
sigs = []
if (self.analyzer and
'.'.join(self.objpath) in self.analyzer.overloads and
self.config.autodoc_typehints == 'signature'):
self.config.autodoc_typehints != 'none'):
# Use signatures for overloaded methods instead of the implementation method.
overloaded = True
else:
Expand Down Expand Up @@ -2666,7 +2666,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
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", "description", "none"))
ENUM("signature", "description", "none", "both"))
app.add_config_value('autodoc_typehints_description_target', 'all', True,
ENUM('all', 'documented'))
app.add_config_value('autodoc_type_aliases', {}, True)
Expand Down
2 changes: 1 addition & 1 deletion sphinx/ext/autodoc/typehints.py
Expand Up @@ -40,7 +40,7 @@ def record_typehints(app: Sphinx, objtype: str, name: str, obj: Any,
def merge_typehints(app: Sphinx, domain: str, objtype: str, contentnode: Element) -> None:
if domain != 'py':
return
if app.config.autodoc_typehints != 'description':
if app.config.autodoc_typehints not in ('both', 'description'):
return

try:
Expand Down
2 changes: 2 additions & 0 deletions tests/roots/test-ext-autodoc/index.rst
Expand Up @@ -10,4 +10,6 @@

.. autofunction:: target.typehints.incr

.. autofunction:: target.overload.sum

.. autofunction:: target.typehints.tuple_args
48 changes: 48 additions & 0 deletions tests/test_ext_autodoc_configs.py
Expand Up @@ -695,6 +695,14 @@ def test_autodoc_typehints_description(app):
' Tuple[int, int]\n'
in context)

# Overloads still get displyed in the signature
assert ('target.overload.sum(x: int, y: int = 0) -> int\n'
'target.overload.sum(x: float, y: float = 0.0) -> float\n'
'target.overload.sum(x: str, y: str = None) -> str\n'
'\n'
' docstring\n'
in context)


@pytest.mark.sphinx('text', testroot='ext-autodoc',
confoverrides={'autodoc_typehints': "description",
Expand Down Expand Up @@ -787,6 +795,46 @@ def test_autodoc_typehints_description_for_invalid_node(app):
restructuredtext.parse(app, text) # raises no error


@pytest.mark.sphinx('text', testroot='ext-autodoc',
confoverrides={'autodoc_typehints': "both"})
def test_autodoc_typehints_both(app):
(app.srcdir / 'index.rst').write_text(
'.. autofunction:: target.typehints.incr\n'
'\n'
'.. autofunction:: target.typehints.tuple_args\n'
'\n'
'.. autofunction:: target.overload.sum\n'
)
app.build()
context = (app.outdir / 'index.txt').read_text()
assert ('target.typehints.incr(a: int, b: int = 1) -> int\n'
'\n'
' Parameters:\n'
' * **a** (*int*) --\n'
'\n'
' * **b** (*int*) --\n'
'\n'
' Return type:\n'
' int\n'
in context)
assert ('target.typehints.tuple_args(x: Tuple[int, Union[int, str]]) -> Tuple[int, int]\n'
'\n'
' Parameters:\n'
' **x** (*Tuple**[**int**, **Union**[**int**, **str**]**]*) --\n'
'\n'
' Return type:\n'
' Tuple[int, int]\n'
in context)

# Overloads still get displyed in the signature
assert ('target.overload.sum(x: int, y: int = 0) -> int\n'
'target.overload.sum(x: float, y: float = 0.0) -> float\n'
'target.overload.sum(x: str, y: str = None) -> str\n'
'\n'
' docstring\n'
in context)


@pytest.mark.skipif(sys.version_info < (3, 7), reason='python 3.7+ is required.')
@pytest.mark.sphinx('text', testroot='ext-autodoc')
def test_autodoc_type_aliases(app):
Expand Down