Fix #9648: autodoc: *args and **kwargs entries are duplicated

In basic usage of autodoc (docstring), `args` and `kwargs` arguments
are marked up without stars.  But numpydoc style recommends to mark
them up with stars.

This adds support for starred arguments in docstrings to
`autodoc_typehints` feature.
This commit is contained in:
Takeshi KOMIYA
2022-05-15 20:43:04 +09:00
parent 92fcac321b
commit 06a9139308
8 changed files with 92 additions and 3 deletions

View File

@@ -16,6 +16,9 @@ Features added
Bugs fixed
----------
* #9648: autodoc: ``*args`` and ``**kwargs`` entries are duplicated when
``autodoc_typehints="description"``
Testing
--------

View File

@@ -111,7 +111,15 @@ def modify_field_list(node: nodes.field_list, annotations: Dict[str, str]) -> No
if name == 'return':
continue
arg = arguments.get(name, {})
if '*' + name in arguments:
name = '*' + name
arguments.get(name)
elif '**' + name in arguments:
name = '**' + name
arguments.get(name)
else:
arg = arguments.get(name, {})
if not arg.get('type'):
field = nodes.field()
field += nodes.field_name('', 'type ' + name)
@@ -159,13 +167,19 @@ def augment_descriptions_with_types(
has_type.add('return')
# Add 'type' for parameters with a description but no declared type.
for name in annotations:
for name, annotation in annotations.items():
if name in ('return', 'returns'):
continue
if '*' + name in has_description:
name = '*' + name
elif '**' + name in has_description:
name = '**' + name
if name in has_description and name not in has_type:
field = nodes.field()
field += nodes.field_name('', 'type ' + name)
field += nodes.field_body('', nodes.paragraph('', annotations[name]))
field += nodes.field_body('', nodes.paragraph('', annotation))
node += field
# Add 'rtype' if 'return' is present and 'rtype' isn't.

View File

@@ -0,0 +1,5 @@
import os
import sys
sys.path.insert(0, os.path.abspath('.'))
extensions = ['sphinx.ext.napoleon']

View File

@@ -0,0 +1,6 @@
test-ext-napoleon
=================
.. toctree::
typehints

View File

@@ -0,0 +1,11 @@
def hello(x: int, *args: int, **kwargs: int) -> None:
"""
Parameters
----------
x
X
*args
Additional arguments.
**kwargs
Extra arguments.
"""

View File

@@ -0,0 +1,5 @@
typehints
=========
.. automodule:: mypackage.typehints
:members:

View File

@@ -2593,3 +2593,48 @@ Sample class with PEP 526 annotations and numpy docstring
"""
print(actual)
assert expected == actual
@pytest.mark.sphinx('text', testroot='ext-napoleon',
confoverrides={'autodoc_typehints': 'description',
'autodoc_typehints_description_target': 'all'})
def test_napoleon_and_autodoc_typehints_description_all(app, status, warning):
app.build()
content = (app.outdir / 'typehints.txt').read_text(encoding='utf-8')
assert content == (
'typehints\n'
'*********\n'
'\n'
'mypackage.typehints.hello(x, *args, **kwargs)\n'
'\n'
' Parameters:\n'
' * **x** (*int*) -- X\n'
'\n'
' * ***args** (*int*) -- Additional arguments.\n'
'\n'
' * ****kwargs** (*int*) -- Extra arguments.\n'
'\n'
' Return type:\n'
' None\n'
)
@pytest.mark.sphinx('text', testroot='ext-napoleon',
confoverrides={'autodoc_typehints': 'description',
'autodoc_typehints_description_target': 'documented_params'})
def test_napoleon_and_autodoc_typehints_description_documented_params(app, status, warning):
app.build()
content = (app.outdir / 'typehints.txt').read_text(encoding='utf-8')
assert content == (
'typehints\n'
'*********\n'
'\n'
'mypackage.typehints.hello(x, *args, **kwargs)\n'
'\n'
' Parameters:\n'
' * **x** (*int*) -- X\n'
'\n'
' * ***args** (*int*) -- Additional arguments.\n'
'\n'
' * ****kwargs** (*int*) -- Extra arguments.\n'
)