Closes #1927: [Napoleon] fixes parsing & formatting of types in Raises section

This commit is contained in:
Rob Ruana 2015-06-11 01:15:52 -07:00
parent cf42c46beb
commit d82d110dfd
2 changed files with 382 additions and 23 deletions

View File

@ -506,33 +506,31 @@ class GoogleDocstring(UnicodeMixin):
return self._format_fields('Parameters', fields) return self._format_fields('Parameters', fields)
def _parse_raises_section(self, section): def _parse_raises_section(self, section):
fields = self._consume_fields() fields = self._consume_fields(parse_type=False, prefer_type=True)
field_type = ':raises:' field_type = ':raises:'
padding = ' ' * len(field_type) padding = ' ' * len(field_type)
multi = len(fields) > 1 multi = len(fields) > 1
lines = [] lines = []
for _name, _type, _desc in fields: for _, _type, _desc in fields:
sep = _desc and ' -- ' or '' has_desc = any(_desc)
if _name: sep = (_desc and _desc[0]) and ' -- ' or ''
if ' ' in _name: if _type:
_name = '**%s**' % _name has_refs = '`' in _type or ':' in _type
has_space = any(c in ' \t\n\v\f ' for c in _type)
if not has_refs and not has_space:
_type = ':exc:`%s`%s' % (_type, sep)
elif has_desc and has_space:
_type = '*%s*%s' % (_type, sep)
else: else:
_name = ':exc:`%s`' % _name _type = '%s%s' % (_type, sep)
if _type:
if '`' in _type: if has_desc:
field = ['%s (%s)%s' % (_name, _type, sep)] field = [_type] + _desc
else:
field = ['%s (*%s*)%s' % (_name, _type, sep)]
else: else:
field = ['%s%s' % (_name, sep)] field = [_type]
elif _type:
if '`' in _type:
field = ['%s%s' % (_type, sep)]
else:
field = ['*%s*%s' % (_type, sep)]
else: else:
field = [] field = _desc
field = field + _desc
if multi: if multi:
if lines: if lines:
lines.extend(self._format_block(padding + ' * ', field)) lines.extend(self._format_block(padding + ' * ', field))
@ -540,6 +538,8 @@ class GoogleDocstring(UnicodeMixin):
lines.extend(self._format_block(field_type + ' * ', field)) lines.extend(self._format_block(field_type + ' * ', field))
else: else:
lines.extend(self._format_block(field_type + ' ', field)) lines.extend(self._format_block(field_type + ' ', field))
if lines and lines[-1]:
lines.append('')
return lines return lines
def _parse_references_section(self, section): def _parse_references_section(self, section):
@ -736,8 +736,6 @@ class NumpyDocstring(GoogleDocstring):
line = next(self._line_iter) line = next(self._line_iter)
if parse_type: if parse_type:
_name, _, _type = self._partition_field_on_colon(line) _name, _, _type = self._partition_field_on_colon(line)
if not _name:
_type = line
else: else:
_name, _type = line, '' _name, _type = line, ''
_name, _type = _name.strip(), _type.strip() _name, _type = _name.strip(), _type.strip()

View File

@ -376,6 +376,175 @@ Returns:
actual = str(GoogleDocstring(docstring)) actual = str(GoogleDocstring(docstring))
self.assertEqual(expected, actual) self.assertEqual(expected, actual)
def test_raises_types(self):
docstrings = [("""
Example Function
Raises:
RuntimeError:
A setting wasn't specified, or was invalid.
ValueError:
Something something value error.
""", """
Example Function
:raises: * :exc:`RuntimeError`
A setting wasn't specified, or was invalid.
* :exc:`ValueError`
Something something value error.
"""),
################################
("""
Example Function
Raises:
InvalidDimensionsError
""", """
Example Function
:raises: :exc:`InvalidDimensionsError`
"""),
################################
("""
Example Function
Raises:
Invalid Dimensions Error
""", """
Example Function
:raises: Invalid Dimensions Error
"""),
################################
("""
Example Function
Raises:
Invalid Dimensions Error: With description
""", """
Example Function
:raises: *Invalid Dimensions Error* --
With description
"""),
################################
("""
Example Function
Raises:
InvalidDimensionsError: If the dimensions couldn't be parsed.
""", """
Example Function
:raises: :exc:`InvalidDimensionsError` --
If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises:
Invalid Dimensions Error: If the dimensions couldn't be parsed.
""", """
Example Function
:raises: *Invalid Dimensions Error* --
If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises:
If the dimensions couldn't be parsed.
""", """
Example Function
:raises: If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises:
:class:`exc.InvalidDimensionsError`
""", """
Example Function
:raises: :class:`exc.InvalidDimensionsError`
"""),
################################
("""
Example Function
Raises:
:class:`exc.InvalidDimensionsError`: If the dimensions couldn't be parsed.
""", """
Example Function
:raises: :class:`exc.InvalidDimensionsError` --
If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises:
:class:`exc.InvalidDimensionsError`: If the dimensions couldn't be parsed,
then a :class:`exc.InvalidDimensionsError` will be raised.
""", """
Example Function
:raises: :class:`exc.InvalidDimensionsError` --
If the dimensions couldn't be parsed,
then a :class:`exc.InvalidDimensionsError` will be raised.
"""),
################################
("""
Example Function
Raises:
:class:`exc.InvalidDimensionsError`: If the dimensions couldn't be parsed.
:class:`exc.InvalidArgumentsError`: If the arguments are invalid.
""", """
Example Function
:raises: * :class:`exc.InvalidDimensionsError` --
If the dimensions couldn't be parsed.
* :class:`exc.InvalidArgumentsError` --
If the arguments are invalid.
"""),
################################
("""
Example Function
Raises:
:class:`exc.InvalidDimensionsError`
:class:`exc.InvalidArgumentsError`
""", """
Example Function
:raises: * :class:`exc.InvalidDimensionsError`
* :class:`exc.InvalidArgumentsError`
""")]
for docstring, expected in docstrings:
actual = str(GoogleDocstring(docstring))
self.assertEqual(expected, actual)
def test_kwargs_in_arguments(self): def test_kwargs_in_arguments(self):
docstring = """Allows to create attributes binded to this device. docstring = """Allows to create attributes binded to this device.
@ -564,7 +733,7 @@ class NumpyDocstringTest(BaseDocstringTest):
:Yields: *str* -- :Yields: *str* --
Extended Extended
description of yielded value""" description of yielded value"""
)] )]
def test_docstrings(self): def test_docstrings(self):
config = Config(napoleon_use_param=False, napoleon_use_rtype=False) config = Config(napoleon_use_param=False, napoleon_use_rtype=False)
@ -713,6 +882,198 @@ arg_ : type
self.assertEqual(expected, actual) self.assertEqual(expected, actual)
def test_raises_types(self):
docstrings = [("""
Example Function
Raises
------
RuntimeError
A setting wasn't specified, or was invalid.
ValueError
Something something value error.
""", """
Example Function
:raises: * :exc:`RuntimeError`
A setting wasn't specified, or was invalid.
* :exc:`ValueError`
Something something value error.
"""),
################################
("""
Example Function
Raises
------
InvalidDimensionsError
""", """
Example Function
:raises: :exc:`InvalidDimensionsError`
"""),
################################
("""
Example Function
Raises
------
Invalid Dimensions Error
""", """
Example Function
:raises: Invalid Dimensions Error
"""),
################################
("""
Example Function
Raises
------
Invalid Dimensions Error
With description
""", """
Example Function
:raises: *Invalid Dimensions Error* --
With description
"""),
################################
("""
Example Function
Raises
------
InvalidDimensionsError
If the dimensions couldn't be parsed.
""", """
Example Function
:raises: :exc:`InvalidDimensionsError` --
If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises
------
Invalid Dimensions Error
If the dimensions couldn't be parsed.
""", """
Example Function
:raises: *Invalid Dimensions Error* --
If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises
------
If the dimensions couldn't be parsed.
""", """
Example Function
:raises: If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises
------
:class:`exc.InvalidDimensionsError`
""", """
Example Function
:raises: :class:`exc.InvalidDimensionsError`
"""),
################################
("""
Example Function
Raises
------
:class:`exc.InvalidDimensionsError`
If the dimensions couldn't be parsed.
""", """
Example Function
:raises: :class:`exc.InvalidDimensionsError` --
If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises
------
:class:`exc.InvalidDimensionsError`
If the dimensions couldn't be parsed,
then a :class:`exc.InvalidDimensionsError` will be raised.
""", """
Example Function
:raises: :class:`exc.InvalidDimensionsError` --
If the dimensions couldn't be parsed,
then a :class:`exc.InvalidDimensionsError` will be raised.
"""),
################################
("""
Example Function
Raises
------
:class:`exc.InvalidDimensionsError`
If the dimensions couldn't be parsed.
:class:`exc.InvalidArgumentsError`
If the arguments are invalid.
""", """
Example Function
:raises: * :class:`exc.InvalidDimensionsError` --
If the dimensions couldn't be parsed.
* :class:`exc.InvalidArgumentsError` --
If the arguments are invalid.
"""),
################################
("""
Example Function
Raises
------
:class:`exc.InvalidDimensionsError`
:class:`exc.InvalidArgumentsError`
""", """
Example Function
:raises: * :class:`exc.InvalidDimensionsError`
* :class:`exc.InvalidArgumentsError`
""")]
for docstring, expected in docstrings:
config = Config()
app = mock.Mock()
actual = str(NumpyDocstring(docstring, config, app, "method"))
self.assertEqual(expected, actual)
def test_xrefs_in_return_type(self): def test_xrefs_in_return_type(self):
docstring = """ docstring = """
Example Function Example Function