mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Closes #1429: Adds smarter Args parsing for Google style docstrings.
This commit is contained in:
parent
3e7ce5d3a1
commit
c430f7f4c6
@ -24,7 +24,8 @@ if sys.version_info[0] >= 3:
|
||||
|
||||
|
||||
_directive_regex = re.compile(r'\.\. \S+::')
|
||||
_field_parens_regex = re.compile(r'\s*(\w+)\s*\(\s*(.+?)\s*\)')
|
||||
_google_untyped_arg_regex = re.compile(r'\s*(\w+)\s*:\s*(.*)')
|
||||
_google_typed_arg_regex = re.compile(r'\s*(\w+)\s*\(\s*(.+?)\s*\)\s*:\s*(.*)')
|
||||
|
||||
|
||||
class GoogleDocstring(object):
|
||||
@ -213,12 +214,22 @@ class GoogleDocstring(object):
|
||||
|
||||
def _consume_field(self, parse_type=True, prefer_type=False):
|
||||
line = self._line_iter.next()
|
||||
_name, _, _desc = line.partition(':')
|
||||
_name, _type, _desc = _name.strip(), '', _desc.strip()
|
||||
match = _field_parens_regex.match(_name)
|
||||
if parse_type and match:
|
||||
|
||||
match = None
|
||||
_name, _type, _desc = line.strip(), '', ''
|
||||
if parse_type:
|
||||
match = _google_typed_arg_regex.match(line)
|
||||
if match:
|
||||
_name = match.group(1)
|
||||
_type = match.group(2)
|
||||
_desc = match.group(3)
|
||||
|
||||
if not match:
|
||||
match = _google_untyped_arg_regex.match(line)
|
||||
if match:
|
||||
_name = match.group(1)
|
||||
_desc = match.group(2)
|
||||
|
||||
if prefer_type and not _type:
|
||||
_type, _name = _name, _type
|
||||
indent = self._get_indent(line) + 1
|
||||
@ -238,17 +249,21 @@ class GoogleDocstring(object):
|
||||
def _consume_returns_section(self):
|
||||
lines = self._dedent(self._consume_to_next_section())
|
||||
if lines:
|
||||
if ':' in lines[0]:
|
||||
_type, _, _desc = lines[0].partition(':')
|
||||
_name, _type, _desc = '', _type.strip(), _desc.strip()
|
||||
match = _field_parens_regex.match(_type)
|
||||
_name, _type, _desc = '', '', lines
|
||||
match = _google_typed_arg_regex.match(lines[0])
|
||||
if match:
|
||||
_name = match.group(1)
|
||||
_type = match.group(2)
|
||||
_desc = match.group(3)
|
||||
else:
|
||||
match = _google_untyped_arg_regex.match(lines[0])
|
||||
if match:
|
||||
_type = match.group(1)
|
||||
_desc = match.group(2)
|
||||
if match:
|
||||
lines[0] = _desc
|
||||
_desc = lines
|
||||
else:
|
||||
_name, _type, _desc = '', '', lines
|
||||
|
||||
_desc = self.__class__(_desc, self._config).lines()
|
||||
return [(_name, _type, _desc,)]
|
||||
else:
|
||||
|
@ -146,6 +146,19 @@ class GoogleDocstringTest(BaseDocstringTest):
|
||||
:returns: *str* --
|
||||
Extended
|
||||
description of return value"""
|
||||
), (
|
||||
"""
|
||||
Single line summary
|
||||
|
||||
Returns:
|
||||
Extended
|
||||
description of return value
|
||||
""",
|
||||
"""
|
||||
Single line summary
|
||||
|
||||
:returns: Extended
|
||||
description of return value"""
|
||||
)]
|
||||
|
||||
def test_docstrings(self):
|
||||
@ -155,6 +168,43 @@ class GoogleDocstringTest(BaseDocstringTest):
|
||||
expected = textwrap.dedent(expected)
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_parameters_with_class_reference(self):
|
||||
docstring = """\
|
||||
Construct a new XBlock.
|
||||
|
||||
This class should only be used by runtimes.
|
||||
|
||||
Arguments:
|
||||
runtime (:class:`Runtime`): Use it to access the environment.
|
||||
It is available in XBlock code as ``self.runtime``.
|
||||
|
||||
field_data (:class:`FieldData`): Interface used by the XBlock
|
||||
fields to access their data from wherever it is persisted.
|
||||
|
||||
scope_ids (:class:`ScopeIds`): Identifiers needed to resolve scopes.
|
||||
|
||||
"""
|
||||
|
||||
actual = str(GoogleDocstring(docstring))
|
||||
expected = """\
|
||||
Construct a new XBlock.
|
||||
|
||||
This class should only be used by runtimes.
|
||||
|
||||
:param runtime: Use it to access the environment.
|
||||
It is available in XBlock code as ``self.runtime``.
|
||||
|
||||
:type runtime: :class:`Runtime`
|
||||
:param field_data: Interface used by the XBlock
|
||||
fields to access their data from wherever it is persisted.
|
||||
|
||||
:type field_data: :class:`FieldData`
|
||||
:param scope_ids: Identifiers needed to resolve scopes.
|
||||
|
||||
:type scope_ids: :class:`ScopeIds`
|
||||
"""
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
|
||||
class NumpyDocstringTest(BaseDocstringTest):
|
||||
docstrings = [(
|
||||
@ -268,7 +318,7 @@ class NumpyDocstringTest(BaseDocstringTest):
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_parameters_with_class_reference(self):
|
||||
docstring = """
|
||||
docstring = """\
|
||||
Parameters
|
||||
----------
|
||||
param1 : :class:`MyClass <name.space.MyClass>` instance
|
||||
@ -276,22 +326,22 @@ class NumpyDocstringTest(BaseDocstringTest):
|
||||
"""
|
||||
|
||||
config = Config(napoleon_use_param=False)
|
||||
actual = str(NumpyDocstring(textwrap.dedent(docstring), config))
|
||||
expected = textwrap.dedent("""
|
||||
actual = str(NumpyDocstring(docstring, config))
|
||||
expected = """\
|
||||
:Parameters: **param1** (:class:`MyClass <name.space.MyClass>` instance)
|
||||
""")
|
||||
"""
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
config = Config(napoleon_use_param=True)
|
||||
actual = str(NumpyDocstring(textwrap.dedent(docstring), config))
|
||||
expected = textwrap.dedent("""
|
||||
actual = str(NumpyDocstring(docstring, config))
|
||||
expected = """\
|
||||
|
||||
:type param1: :class:`MyClass <name.space.MyClass>` instance
|
||||
""")
|
||||
"""
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_parameters_without_class_reference(self):
|
||||
docstring = """
|
||||
docstring = """\
|
||||
Parameters
|
||||
----------
|
||||
param1 : MyClass instance
|
||||
@ -299,22 +349,22 @@ class NumpyDocstringTest(BaseDocstringTest):
|
||||
"""
|
||||
|
||||
config = Config(napoleon_use_param=False)
|
||||
actual = str(NumpyDocstring(textwrap.dedent(docstring), config))
|
||||
expected = textwrap.dedent("""
|
||||
actual = str(NumpyDocstring(docstring, config))
|
||||
expected = """\
|
||||
:Parameters: **param1** (*MyClass instance*)
|
||||
""")
|
||||
"""
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
config = Config(napoleon_use_param=True)
|
||||
actual = str(NumpyDocstring(textwrap.dedent(docstring), config))
|
||||
expected = textwrap.dedent("""
|
||||
expected = """\
|
||||
|
||||
:type param1: MyClass instance
|
||||
""")
|
||||
"""
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_see_also_refs(self):
|
||||
docstring = """
|
||||
docstring = """\
|
||||
numpy.multivariate_normal(mean, cov, shape=None, spam=None)
|
||||
|
||||
See Also
|
||||
@ -324,19 +374,21 @@ class NumpyDocstringTest(BaseDocstringTest):
|
||||
|
||||
"""
|
||||
|
||||
actual = str(NumpyDocstring(textwrap.dedent(docstring)))
|
||||
actual = str(NumpyDocstring(docstring))
|
||||
|
||||
expected = """
|
||||
expected = """\
|
||||
numpy.multivariate_normal(mean, cov, shape=None, spam=None)
|
||||
|
||||
.. seealso::
|
||||
\n :obj:`some`, :obj:`other`, :obj:`funcs`
|
||||
\n :obj:`otherfunc`
|
||||
|
||||
:obj:`some`, :obj:`other`, :obj:`funcs`
|
||||
\n\
|
||||
:obj:`otherfunc`
|
||||
relationship
|
||||
"""
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
docstring = """
|
||||
docstring = """\
|
||||
numpy.multivariate_normal(mean, cov, shape=None, spam=None)
|
||||
|
||||
See Also
|
||||
@ -348,15 +400,16 @@ numpy.multivariate_normal(mean, cov, shape=None, spam=None)
|
||||
|
||||
config = Config()
|
||||
app = Mock()
|
||||
actual = str(NumpyDocstring(textwrap.dedent(docstring),
|
||||
config, app, "method"))
|
||||
actual = str(NumpyDocstring(docstring, config, app, "method"))
|
||||
|
||||
expected = """
|
||||
expected = """\
|
||||
numpy.multivariate_normal(mean, cov, shape=None, spam=None)
|
||||
|
||||
.. seealso::
|
||||
\n :meth:`some`, :meth:`other`, :meth:`funcs`
|
||||
\n :meth:`otherfunc`
|
||||
|
||||
:meth:`some`, :meth:`other`, :meth:`funcs`
|
||||
\n\
|
||||
:meth:`otherfunc`
|
||||
relationship
|
||||
"""
|
||||
self.assertEqual(expected, actual)
|
||||
|
Loading…
Reference in New Issue
Block a user