mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #10451 from tk0miya/9648_autodoc_typehints_description_and_stared_args
Fix #9648: autodoc: *args and **kwargs entries are duplicated
This commit is contained in:
2
CHANGES
2
CHANGES
@@ -39,6 +39,8 @@ Bugs fixed
|
||||
|
||||
* #9575: autodoc: The annotation of return value should not be shown when
|
||||
``autodoc_typehints="description"``
|
||||
* #9648: autodoc: ``*args`` and ``**kwargs`` entries are duplicated when
|
||||
``autodoc_typehints="description"``
|
||||
* #10456: py domain: ``:meta:`` fields are displayed if docstring contains two
|
||||
or more meta-field
|
||||
|
||||
|
||||
@@ -115,7 +115,15 @@ def modify_field_list(node: nodes.field_list, annotations: Dict[str, str],
|
||||
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)
|
||||
@@ -167,13 +175,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.
|
||||
|
||||
@@ -94,8 +94,10 @@ def missing_attr(c,
|
||||
class _ClassWithDocumentedInit:
|
||||
"""Class docstring."""
|
||||
|
||||
def __init__(self, x: int) -> None:
|
||||
def __init__(self, x: int, *args: int, **kwargs: int) -> None:
|
||||
"""Init docstring.
|
||||
|
||||
:param x: Some integer
|
||||
:param args: Some integer
|
||||
:param kwargs: Some integer
|
||||
"""
|
||||
|
||||
5
tests/roots/test-ext-napoleon/conf.py
Normal file
5
tests/roots/test-ext-napoleon/conf.py
Normal file
@@ -0,0 +1,5 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath('.'))
|
||||
extensions = ['sphinx.ext.napoleon']
|
||||
6
tests/roots/test-ext-napoleon/index.rst
Normal file
6
tests/roots/test-ext-napoleon/index.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
test-ext-napoleon
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
|
||||
typehints
|
||||
0
tests/roots/test-ext-napoleon/mypackage/__init__.py
Normal file
0
tests/roots/test-ext-napoleon/mypackage/__init__.py
Normal file
11
tests/roots/test-ext-napoleon/mypackage/typehints.py
Normal file
11
tests/roots/test-ext-napoleon/mypackage/typehints.py
Normal file
@@ -0,0 +1,11 @@
|
||||
def hello(x: int, *args: int, **kwargs: int) -> None:
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
x
|
||||
X
|
||||
*args
|
||||
Additional arguments.
|
||||
**kwargs
|
||||
Extra arguments.
|
||||
"""
|
||||
5
tests/roots/test-ext-napoleon/typehints.rst
Normal file
5
tests/roots/test-ext-napoleon/typehints.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
typehints
|
||||
=========
|
||||
|
||||
.. automodule:: mypackage.typehints
|
||||
:members:
|
||||
@@ -1034,19 +1034,27 @@ def test_autodoc_typehints_description_with_documented_init(app):
|
||||
)
|
||||
app.build()
|
||||
context = (app.outdir / 'index.txt').read_text(encoding='utf8')
|
||||
assert ('class target.typehints._ClassWithDocumentedInit(x)\n'
|
||||
assert ('class target.typehints._ClassWithDocumentedInit(x, *args, **kwargs)\n'
|
||||
'\n'
|
||||
' Class docstring.\n'
|
||||
'\n'
|
||||
' Parameters:\n'
|
||||
' **x** (*int*) --\n'
|
||||
' * **x** (*int*) --\n'
|
||||
'\n'
|
||||
' __init__(x)\n'
|
||||
' * **args** (*int*) --\n'
|
||||
'\n'
|
||||
' * **kwargs** (*int*) --\n'
|
||||
'\n'
|
||||
' __init__(x, *args, **kwargs)\n'
|
||||
'\n'
|
||||
' Init docstring.\n'
|
||||
'\n'
|
||||
' Parameters:\n'
|
||||
' **x** (*int*) -- Some integer\n'
|
||||
' * **x** (*int*) -- Some integer\n'
|
||||
'\n'
|
||||
' * **args** (*int*) -- Some integer\n'
|
||||
'\n'
|
||||
' * **kwargs** (*int*) -- Some integer\n'
|
||||
'\n'
|
||||
' Return type:\n'
|
||||
' None\n' == context)
|
||||
@@ -1063,16 +1071,20 @@ def test_autodoc_typehints_description_with_documented_init_no_undoc(app):
|
||||
)
|
||||
app.build()
|
||||
context = (app.outdir / 'index.txt').read_text(encoding='utf8')
|
||||
assert ('class target.typehints._ClassWithDocumentedInit(x)\n'
|
||||
assert ('class target.typehints._ClassWithDocumentedInit(x, *args, **kwargs)\n'
|
||||
'\n'
|
||||
' Class docstring.\n'
|
||||
'\n'
|
||||
' __init__(x)\n'
|
||||
' __init__(x, *args, **kwargs)\n'
|
||||
'\n'
|
||||
' Init docstring.\n'
|
||||
'\n'
|
||||
' Parameters:\n'
|
||||
' **x** (*int*) -- Some integer\n' == context)
|
||||
' * **x** (*int*) -- Some integer\n'
|
||||
'\n'
|
||||
' * **args** (*int*) -- Some integer\n'
|
||||
'\n'
|
||||
' * **kwargs** (*int*) -- Some integer\n' == context)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('text', testroot='ext-autodoc',
|
||||
@@ -1089,16 +1101,20 @@ def test_autodoc_typehints_description_with_documented_init_no_undoc_doc_rtype(a
|
||||
)
|
||||
app.build()
|
||||
context = (app.outdir / 'index.txt').read_text(encoding='utf8')
|
||||
assert ('class target.typehints._ClassWithDocumentedInit(x)\n'
|
||||
assert ('class target.typehints._ClassWithDocumentedInit(x, *args, **kwargs)\n'
|
||||
'\n'
|
||||
' Class docstring.\n'
|
||||
'\n'
|
||||
' __init__(x)\n'
|
||||
' __init__(x, *args, **kwargs)\n'
|
||||
'\n'
|
||||
' Init docstring.\n'
|
||||
'\n'
|
||||
' Parameters:\n'
|
||||
' **x** (*int*) -- Some integer\n' == context)
|
||||
' * **x** (*int*) -- Some integer\n'
|
||||
'\n'
|
||||
' * **args** (*int*) -- Some integer\n'
|
||||
'\n'
|
||||
' * **kwargs** (*int*) -- Some integer\n' == context)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('text', testroot='ext-autodoc',
|
||||
|
||||
@@ -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'
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user