Properly support of in docstring type specifiers (#10738)

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
This commit is contained in:
ProGamerGov 2022-08-02 16:43:32 -06:00 committed by GitHub
parent f72a25ce76
commit b2fe07e1a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 122 additions and 1 deletions

View File

@ -30,6 +30,7 @@ Contributors
* Antonio Valentino -- qthelp builder, docstring inheritance
* Antti Kaihola -- doctest extension (skipif option)
* Barry Warsaw -- setup command improvements
* Ben Egan -- Napoleon improvements
* Benjamin Peterson -- unittests
* Blaise Laflamme -- pyramid theme
* Bruce Mitchener -- Minor epub improvement

View File

@ -41,6 +41,9 @@ Deprecated
Features added
--------------
* #10738: napoleon: Add support for docstring types using 'of', like
``type of type``. Example: ``tuple of int``.
Bugs fixed
----------

View File

@ -380,7 +380,7 @@ class PyXrefMixin:
innernode: Type[TextlikeNode] = nodes.emphasis,
contnode: Node = None, env: BuildEnvironment = None,
inliner: Inliner = None, location: Node = None) -> List[Node]:
delims = r'(\s*[\[\]\(\),](?:\s*or\s)?\s*|\s+or\s+|\s*\|\s*|\.\.\.)'
delims = r'(\s*[\[\]\(\),](?:\s*o[rf]\s)?\s*|\s+o[rf]\s+|\s*\|\s*|\.\.\.)'
delims_re = re.compile(delims)
sub_targets = re.split(delims, target)

View File

@ -1214,6 +1214,78 @@ def test_info_field_list_var(app):
refdomain="py", reftype="class", reftarget="int", **{"py:class": "Class"})
def test_info_field_list_napoleon_deliminator_of(app):
text = (".. py:module:: example\n"
".. py:class:: Class\n"
"\n"
" :param list_str_var: example description.\n"
" :type list_str_var: list of str\n"
" :param tuple_int_var: example description.\n"
" :type tuple_int_var: tuple of tuple of int\n"
)
doctree = restructuredtext.parse(app, text)
# :param list of str list_str_var:
assert_node(doctree[3][1][0][0][1][0][0][0],
([addnodes.literal_strong, "list_str_var"],
" (",
[pending_xref, addnodes.literal_emphasis, "list"],
[addnodes.literal_emphasis, " of "],
[pending_xref, addnodes.literal_emphasis, "str"],
")",
" -- ",
"example description."))
# :param tuple of tuple of int tuple_int_var:
assert_node(doctree[3][1][0][0][1][0][1][0],
([addnodes.literal_strong, "tuple_int_var"],
" (",
[pending_xref, addnodes.literal_emphasis, "tuple"],
[addnodes.literal_emphasis, " of "],
[pending_xref, addnodes.literal_emphasis, "tuple"],
[addnodes.literal_emphasis, " of "],
[pending_xref, addnodes.literal_emphasis, "int"],
")",
" -- ",
"example description."))
def test_info_field_list_napoleon_deliminator_or(app):
text = (".. py:module:: example\n"
".. py:class:: Class\n"
"\n"
" :param bool_str_var: example description.\n"
" :type bool_str_var: bool or str\n"
" :param str_float_int_var: example description.\n"
" :type str_float_int_var: str or float or int\n"
)
doctree = restructuredtext.parse(app, text)
# :param bool or str bool_str_var:
assert_node(doctree[3][1][0][0][1][0][0][0],
([addnodes.literal_strong, "bool_str_var"],
" (",
[pending_xref, addnodes.literal_emphasis, "bool"],
[addnodes.literal_emphasis, " or "],
[pending_xref, addnodes.literal_emphasis, "str"],
")",
" -- ",
"example description."))
# :param str or float or int str_float_int_var:
assert_node(doctree[3][1][0][0][1][0][1][0],
([addnodes.literal_strong, "str_float_int_var"],
" (",
[pending_xref, addnodes.literal_emphasis, "str"],
[addnodes.literal_emphasis, " or "],
[pending_xref, addnodes.literal_emphasis, "float"],
[addnodes.literal_emphasis, " or "],
[pending_xref, addnodes.literal_emphasis, "int"],
")",
" -- ",
"example description."))
def test_type_field(app):
text = (".. py:data:: var1\n"
" :type: .int\n"

View File

@ -356,6 +356,41 @@ class GoogleDocstringTest(BaseDocstringTest):
:Yields: Extended
description of yielded value
"""
), (
"""
Single line summary
Args:
arg1 (list of str): Extended
description of arg1.
arg2 (tuple of int): Extended
description of arg2.
arg3 (tuple of list of float): Extended
description of arg3.
arg4 (int, float, or list of bool): Extended
description of arg4.
arg5 (list of int, float, or bool): Extended
description of arg5.
arg6 (list of int or float): Extended
description of arg6.
""",
"""
Single line summary
:Parameters: * **arg1** (*list of str*) -- Extended
description of arg1.
* **arg2** (*tuple of int*) -- Extended
description of arg2.
* **arg3** (*tuple of list of float*) -- Extended
description of arg3.
* **arg4** (*int, float, or list of bool*) -- Extended
description of arg4.
* **arg5** (*list of int, float, or bool*) -- Extended
description of arg5.
* **arg6** (*list of int or float*) -- Extended
description of arg6.
"""
)]
def test_sphinx_admonitions(self):
@ -2367,6 +2402,8 @@ definition_after_normal_text : int
"defaultdict",
"int, float, or complex",
"int or float or None, optional",
"list of list of int or float, optional",
"tuple of list of str, float, or int",
'{"F", "C", "N"}',
"{'F', 'C', 'N'}, default: 'F'",
"{'F', 'C', 'N or C'}, default 'F'",
@ -2383,6 +2420,8 @@ definition_after_normal_text : int
["defaultdict"],
["int", ", ", "float", ", or ", "complex"],
["int", " or ", "float", " or ", "None", ", ", "optional"],
["list", " of ", "list", " of ", "int", " or ", "float", ", ", "optional"],
["tuple", " of ", "list", " of ", "str", ", ", "float", ", or ", "int"],
["{", '"F"', ", ", '"C"', ", ", '"N"', "}"],
["{", "'F'", ", ", "'C'", ", ", "'N'", "}", ", ", "default", ": ", "'F'"],
["{", "'F'", ", ", "'C'", ", ", "'N or C'", "}", ", ", "default", " ", "'F'"],
@ -2443,6 +2482,7 @@ definition_after_normal_text : int
"optional",
"str, optional",
"int or float or None, default: None",
"list of tuple of str, optional",
"int, default None",
'{"F", "C", "N"}',
"{'F', 'C', 'N'}, default: 'N'",
@ -2455,6 +2495,7 @@ definition_after_normal_text : int
"*optional*",
":class:`str`, *optional*",
":class:`int` or :class:`float` or :obj:`None`, *default*: :obj:`None`",
":class:`list` of :class:`tuple` of :class:`str`, *optional*",
":class:`int`, *default* :obj:`None`",
'``{"F", "C", "N"}``',
"``{'F', 'C', 'N'}``, *default*: ``'N'``",
@ -2486,6 +2527,8 @@ definition_after_normal_text : int
a optional mapping
param8 : ... or Ellipsis
ellipsis
param9 : tuple of list of int
a parameter with tuple of list of int
""")
expected = dedent("""\
:param param1: the data to work on
@ -2504,6 +2547,8 @@ definition_after_normal_text : int
:type param7: :term:`mapping` of :term:`hashable` to :class:`str`, *optional*
:param param8: ellipsis
:type param8: :obj:`... <Ellipsis>` or :obj:`Ellipsis`
:param param9: a parameter with tuple of list of int
:type param9: :class:`tuple` of :class:`list` of :class:`int`
""")
translations = {
"dict-like": ":term:`dict-like <mapping>`",