diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py index 4397d0e41f0..39f5626ce1c 100644 --- a/sphinx/ext/napoleon/docstring.py +++ b/sphinx/ext/napoleon/docstring.py @@ -699,6 +699,9 @@ def _parse_raises_section(self, section: str) -> List[str]: m = self._name_rgx.match(_type) if m and m.group('name'): _type = m.group('name') + elif _xref_regex.match(_type): + pos = _type.find('`') + _type = _type[pos + 1:-1] _type = ' ' + _type if _type else '' _desc = self._strip_empty(_desc) _descs = ' ' + '\n '.join(_desc) if any(_desc) else '' @@ -1104,6 +1107,10 @@ def _consume_field(self, parse_type: bool = True, prefer_type: bool = False _name, _type = line, '' _name, _type = _name.strip(), _type.strip() _name = self._escape_args_and_kwargs(_name) + + if prefer_type and not _type: + _type, _name = _name, _type + if self._config.napoleon_preprocess_types: _type = _convert_numpy_type_spec( _type, @@ -1111,8 +1118,6 @@ def _consume_field(self, parse_type: bool = True, prefer_type: bool = False translations=self._config.napoleon_type_aliases or {}, ) - if prefer_type and not _type: - _type, _name = _name, _type indent = self._get_indent(line) + 1 _desc = self._dedent(self._consume_indented_block(indent)) _desc = self.__class__(_desc, self._config).lines() diff --git a/tests/test_ext_napoleon_docstring.py b/tests/test_ext_napoleon_docstring.py index bbc075edd97..da456e4a232 100644 --- a/tests/test_ext_napoleon_docstring.py +++ b/tests/test_ext_napoleon_docstring.py @@ -1177,7 +1177,7 @@ class NumpyDocstringTest(BaseDocstringTest): """ Single line summary - :returns: *str* -- Extended + :returns: :class:`str` -- Extended description of return value """ ), ( @@ -1193,7 +1193,7 @@ class NumpyDocstringTest(BaseDocstringTest): """ Single line summary - :returns: *str* -- Extended + :returns: :class:`str` -- Extended description of return value """ ), ( @@ -1246,7 +1246,7 @@ class NumpyDocstringTest(BaseDocstringTest): """ Single line summary - :Yields: *str* -- Extended + :Yields: :class:`str` -- Extended description of yielded value """ ), ( @@ -1262,7 +1262,7 @@ class NumpyDocstringTest(BaseDocstringTest): """ Single line summary - :Yields: *str* -- Extended + :Yields: :class:`str` -- Extended description of yielded value """ )] @@ -1526,6 +1526,52 @@ def test_underscore_in_attribute_strip_signature_backslash(self): self.assertEqual(expected, actual) + def test_return_types(self): + docstring = dedent(""" + Returns + ------- + DataFrame + a dataframe + """) + expected = dedent(""" + :returns: a dataframe + :rtype: :class:`~pandas.DataFrame` + """) + translations = { + "DataFrame": "~pandas.DataFrame", + } + config = Config( + napoleon_use_param=True, + napoleon_use_rtype=True, + napoleon_preprocess_types=True, + napoleon_type_aliases=translations, + ) + actual = str(NumpyDocstring(docstring, config)) + self.assertEqual(expected, actual) + + def test_yield_types(self): + docstring = dedent(""" + Example Function + + Yields + ------ + scalar or array-like + The result of the computation + """) + expected = dedent(""" + Example Function + + :Yields: :term:`scalar` or :class:`array-like ` -- The result of the computation + """) + translations = { + "scalar": ":term:`scalar`", + "array-like": ":class:`array-like `", + } + config = Config(napoleon_type_aliases=translations, napoleon_preprocess_types=True) + app = mock.Mock() + actual = str(NumpyDocstring(docstring, config, app, "method")) + self.assertEqual(expected, actual) + def test_raises_types(self): docstrings = [(""" Example Function @@ -1690,6 +1736,34 @@ def test_raises_types(self): (""" Example Function +Raises +------ +CustomError + If the dimensions couldn't be parsed. + +""", """ +Example Function + +:raises package.CustomError: If the dimensions couldn't be parsed. +"""), + ################################ + (""" +Example Function + +Raises +------ +AnotherError + If the dimensions couldn't be parsed. + +""", """ +Example Function + +:raises ~package.AnotherError: If the dimensions couldn't be parsed. +"""), + ################################ + (""" +Example Function + Raises ------ :class:`exc.InvalidDimensionsError` @@ -1702,7 +1776,11 @@ def test_raises_types(self): :raises exc.InvalidArgumentsError: """)] for docstring, expected in docstrings: - config = Config() + translations = { + "CustomError": "package.CustomError", + "AnotherError": ":py:exc:`~package.AnotherError`", + } + config = Config(napoleon_type_aliases=translations, napoleon_preprocess_types=True) app = mock.Mock() actual = str(NumpyDocstring(docstring, config, app, "method")) self.assertEqual(expected, actual)