sphinx/tests/test_ext_napoleon_docstring.py

1989 lines
49 KiB
Python
Raw Normal View History

"""
test_napoleon_docstring
~~~~~~~~~~~~~~~~~~~~~~~
Tests for :mod:`sphinx.ext.napoleon.docstring` module.
2019-12-31 23:27:43 -06:00
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from collections import namedtuple
from inspect import cleandoc
from textwrap import dedent
from unittest import TestCase, mock
2018-02-19 07:39:14 -06:00
2014-08-10 02:31:28 -05:00
from sphinx.ext.napoleon import Config
from sphinx.ext.napoleon.docstring import GoogleDocstring, NumpyDocstring
class NamedtupleSubclass(namedtuple('NamedtupleSubclass', ('attr1', 'attr2'))):
"""Sample namedtuple subclass
Attributes
----------
attr1 : Arbitrary type
Quick description of attr1
attr2 : Another arbitrary type
Quick description of attr2
attr3 : Type
Adds a newline after the type
"""
# To avoid creating a dict, as a namedtuple doesn't have it:
__slots__ = ()
def __new__(cls, attr1, attr2=None):
return super().__new__(cls, attr1, attr2)
class BaseDocstringTest(TestCase):
pass
class NamedtupleSubclassTest(BaseDocstringTest):
def test_attributes_docstring(self):
config = Config()
actual = str(NumpyDocstring(cleandoc(NamedtupleSubclass.__doc__),
config=config, app=None, what='class',
name='NamedtupleSubclass', obj=NamedtupleSubclass))
expected = """\
Sample namedtuple subclass
.. attribute:: attr1
:type: Arbitrary type
Quick description of attr1
.. attribute:: attr2
:type: Another arbitrary type
Quick description of attr2
.. attribute:: attr3
:type: Type
Adds a newline after the type
"""
self.assertEqual(expected, actual)
class InlineAttributeTest(BaseDocstringTest):
def test_class_data_member(self):
config = Config()
docstring = dedent("""\
data member description:
- a: b
""")
actual = str(GoogleDocstring(docstring, config=config, app=None,
what='attribute', name='some_data', obj=0))
expected = dedent("""\
data member description:
- a: b""")
self.assertEqual(expected, actual)
def test_class_data_member_inline(self):
config = Config()
docstring = """b: data member description with :ref:`reference`"""
actual = str(GoogleDocstring(docstring, config=config, app=None,
what='attribute', name='some_data', obj=0))
expected = dedent("""\
data member description with :ref:`reference`
:type: b""")
self.assertEqual(expected, actual)
def test_class_data_member_inline_no_type(self):
config = Config()
docstring = """data with ``a : in code`` and :ref:`reference` and no type"""
actual = str(GoogleDocstring(docstring, config=config, app=None,
what='attribute', name='some_data', obj=0))
expected = """data with ``a : in code`` and :ref:`reference` and no type"""
self.assertEqual(expected, actual)
def test_class_data_member_inline_ref_in_type(self):
config = Config()
docstring = """:class:`int`: data member description"""
actual = str(GoogleDocstring(docstring, config=config, app=None,
what='attribute', name='some_data', obj=0))
expected = dedent("""\
data member description
:type: :class:`int`""")
self.assertEqual(expected, actual)
class GoogleDocstringTest(BaseDocstringTest):
docstrings = [(
"""Single line summary""",
"""Single line summary"""
), (
"""
Single line summary
Extended description
""",
"""
Single line summary
Extended description
"""
), (
"""
Single line summary
Args:
arg1(str):Extended
description of arg1
""",
"""
Single line summary
:Parameters: **arg1** (*str*) -- Extended
description of arg1
"""
), (
"""
Single line summary
Args:
arg1(str):Extended
description of arg1
arg2 ( int ) : Extended
description of arg2
Keyword Args:
kwarg1(str):Extended
description of kwarg1
kwarg2 ( int ) : Extended
description of kwarg2""",
"""
Single line summary
:Parameters: * **arg1** (*str*) -- Extended
description of arg1
* **arg2** (*int*) -- Extended
description of arg2
:Keyword Arguments: * **kwarg1** (*str*) -- Extended
description of kwarg1
* **kwarg2** (*int*) -- Extended
description of kwarg2
"""
), (
"""
Single line summary
Arguments:
arg1(str):Extended
description of arg1
arg2 ( int ) : Extended
description of arg2
Keyword Arguments:
kwarg1(str):Extended
description of kwarg1
kwarg2 ( int ) : Extended
description of kwarg2""",
"""
Single line summary
:Parameters: * **arg1** (*str*) -- Extended
description of arg1
* **arg2** (*int*) -- Extended
description of arg2
:Keyword Arguments: * **kwarg1** (*str*) -- Extended
description of kwarg1
* **kwarg2** (*int*) -- Extended
description of kwarg2
"""
), (
"""
Single line summary
Return:
str:Extended
description of return value
""",
"""
Single line summary
:returns: *str* -- Extended
description of return value
"""
), (
"""
Single line summary
Returns:
str:Extended
description of return value
""",
"""
Single line summary
: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
"""
), (
"""
Single line summary
Args:
arg1(str):Extended
description of arg1
*args: Variable length argument list.
**kwargs: Arbitrary keyword arguments.
""",
"""
Single line summary
:Parameters: * **arg1** (*str*) -- Extended
description of arg1
* **\\*args** -- Variable length argument list.
* **\\*\\*kwargs** -- Arbitrary keyword arguments.
"""
), (
"""
Single line summary
Args:
arg1 (list(int)): Description
arg2 (list[int]): Description
arg3 (dict(str, int)): Description
arg4 (dict[str, int]): Description
""",
"""
Single line summary
:Parameters: * **arg1** (*list(int)*) -- Description
* **arg2** (*list[int]*) -- Description
* **arg3** (*dict(str, int)*) -- Description
* **arg4** (*dict[str, int]*) -- Description
"""
), (
"""
Single line summary
Yield:
str:Extended
description of yielded value
""",
"""
Single line summary
:Yields: *str* -- Extended
description of yielded value
"""
), (
"""
Single line summary
Yields:
Extended
description of yielded value
""",
"""
Single line summary
:Yields: Extended
description of yielded value
"""
)]
2018-02-13 10:38:44 -06:00
def test_sphinx_admonitions(self):
admonition_map = {
'Attention': 'attention',
'Caution': 'caution',
'Danger': 'danger',
'Error': 'error',
'Hint': 'hint',
'Important': 'important',
'Note': 'note',
'Tip': 'tip',
'Todo': 'todo',
'Warning': 'warning',
'Warnings': 'warning',
}
config = Config()
for section, admonition in admonition_map.items():
# Multiline
actual = str(GoogleDocstring(("{}:\n"
2018-02-19 09:08:44 -06:00
" this is the first line\n"
"\n"
" and this is the second line\n"
).format(section), config))
2018-02-13 10:38:44 -06:00
expect = (".. {}::\n"
"\n"
" this is the first line\n"
" \n"
" and this is the second line\n"
).format(admonition)
self.assertEqual(expect, actual)
# Single line
actual = str(GoogleDocstring(("{}:\n"
2018-02-19 09:08:44 -06:00
" this is a single line\n"
).format(section), config))
2018-02-13 10:38:44 -06:00
expect = (".. {}:: this is a single line\n"
).format(admonition)
self.assertEqual(expect, actual)
def test_docstrings(self):
config = Config(
napoleon_use_param=False,
napoleon_use_rtype=False,
napoleon_use_keyword=False
)
for docstring, expected in self.docstrings:
actual = str(GoogleDocstring(dedent(docstring), config))
expected = 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:
2017-03-03 07:00:35 -06:00
runtime (:class:`~typing.Dict`\\[:class:`int`,:class:`str`\\]): 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``.
2017-03-03 07:00:35 -06:00
:type runtime: :class:`~typing.Dict`\\[:class:`int`,:class:`str`\\]
: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)
def test_attributes_with_class_reference(self):
docstring = """\
Attributes:
in_attr(:class:`numpy.ndarray`): super-dooper attribute
"""
actual = str(GoogleDocstring(docstring))
expected = """\
.. attribute:: in_attr
:type: :class:`numpy.ndarray`
super-dooper attribute
"""
self.assertEqual(expected, actual)
docstring = """\
Attributes:
in_attr(numpy.ndarray): super-dooper attribute
"""
actual = str(GoogleDocstring(docstring))
expected = """\
.. attribute:: in_attr
:type: numpy.ndarray
super-dooper attribute
"""
self.assertEqual(expected, actual)
def test_code_block_in_returns_section(self):
docstring = """
Returns:
foobar: foo::
codecode
codecode
"""
expected = """
:returns:
foo::
codecode
codecode
:rtype: foobar
"""
actual = str(GoogleDocstring(docstring))
self.assertEqual(expected, actual)
def test_colon_in_return_type(self):
docstring = """Example property.
Returns:
:py:class:`~.module.submodule.SomeClass`: an example instance
if available, None if not available.
"""
expected = """Example property.
:returns: an example instance
if available, None if not available.
:rtype: :py:class:`~.module.submodule.SomeClass`
"""
actual = str(GoogleDocstring(docstring))
self.assertEqual(expected, actual)
def test_xrefs_in_return_type(self):
docstring = """Example Function
Returns:
:class:`numpy.ndarray`: A :math:`n \\times 2` array containing
a bunch of math items
"""
expected = """Example Function
:returns: A :math:`n \\times 2` array containing
a bunch of math items
:rtype: :class:`numpy.ndarray`
"""
actual = str(GoogleDocstring(docstring))
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.
:py:class:`AttributeError`
errors for missing attributes.
~InvalidDimensionsError
If the dimensions couldn't be parsed.
`InvalidArgumentsError`
If the arguments are invalid.
:exc:`~ValueError`
If the arguments are wrong.
""", """
Example Function
:raises RuntimeError: A setting wasn't specified, or was invalid.
:raises ValueError: Something something value error.
:raises AttributeError: errors for missing attributes.
:raises ~InvalidDimensionsError: If the dimensions couldn't be parsed.
:raises InvalidArgumentsError: If the arguments are invalid.
:raises ~ValueError: If the arguments are wrong.
"""),
################################
("""
Example Function
Raises:
InvalidDimensionsError
""", """
Example Function
:raises 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 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 exc.InvalidDimensionsError:
"""),
################################
("""
Example Function
Raises:
:class:`exc.InvalidDimensionsError`: If the dimensions couldn't be parsed.
""", """
Example Function
:raises 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 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 exc.InvalidDimensionsError: If the dimensions couldn't be parsed.
:raises exc.InvalidArgumentsError: If the arguments are invalid.
"""),
################################
("""
Example Function
Raises:
:class:`exc.InvalidDimensionsError`
:class:`exc.InvalidArgumentsError`
""", """
Example Function
:raises exc.InvalidDimensionsError:
:raises exc.InvalidArgumentsError:
""")]
for docstring, expected in docstrings:
actual = str(GoogleDocstring(docstring))
self.assertEqual(expected, actual)
def test_kwargs_in_arguments(self):
docstring = """Allows to create attributes binded to this device.
Some other paragraph.
Code sample for usage::
dev.bind(loopback=Loopback)
dev.loopback.configure()
Arguments:
**kwargs: name/class pairs that will create resource-managers
bound as instance attributes to this instance. See code
example above.
"""
expected = """Allows to create attributes binded to this device.
Some other paragraph.
Code sample for usage::
dev.bind(loopback=Loopback)
dev.loopback.configure()
:param \\*\\*kwargs: name/class pairs that will create resource-managers
bound as instance attributes to this instance. See code
example above.
"""
actual = str(GoogleDocstring(docstring))
self.assertEqual(expected, actual)
def test_section_header_formatting(self):
docstrings = [("""
Summary line
Example:
Multiline reStructuredText
literal code block
""", """
Summary line
.. rubric:: Example
Multiline reStructuredText
literal code block
"""),
################################
("""
Summary line
Example::
Multiline reStructuredText
literal code block
""", """
Summary line
Example::
Multiline reStructuredText
literal code block
"""),
################################
("""
Summary line
:Example:
Multiline reStructuredText
literal code block
""", """
Summary line
:Example:
Multiline reStructuredText
literal code block
""")]
for docstring, expected in docstrings:
actual = str(GoogleDocstring(docstring))
self.assertEqual(expected, actual)
def test_list_in_parameter_description(self):
docstring = """One line summary.
Parameters:
no_list (int):
one_bullet_empty (int):
*
one_bullet_single_line (int):
- first line
one_bullet_two_lines (int):
+ first line
continued
two_bullets_single_line (int):
- first line
- second line
two_bullets_two_lines (int):
* first line
continued
* second line
continued
one_enumeration_single_line (int):
1. first line
one_enumeration_two_lines (int):
1) first line
continued
two_enumerations_one_line (int):
(iii) first line
(iv) second line
two_enumerations_two_lines (int):
a. first line
continued
b. second line
continued
one_definition_one_line (int):
item 1
first line
one_definition_two_lines (int):
item 1
first line
continued
two_definitions_one_line (int):
item 1
first line
item 2
second line
two_definitions_two_lines (int):
item 1
first line
continued
item 2
second line
continued
one_definition_blank_line (int):
item 1
first line
extra first line
two_definitions_blank_lines (int):
item 1
first line
extra first line
item 2
second line
extra second line
definition_after_inline_text (int): text line
item 1
first line
definition_after_normal_text (int):
text line
item 1
first line
"""
expected = """One line summary.
:param no_list:
:type no_list: int
:param one_bullet_empty:
*
:type one_bullet_empty: int
:param one_bullet_single_line:
- first line
:type one_bullet_single_line: int
:param one_bullet_two_lines:
+ first line
continued
:type one_bullet_two_lines: int
:param two_bullets_single_line:
- first line
- second line
:type two_bullets_single_line: int
:param two_bullets_two_lines:
* first line
continued
* second line
continued
:type two_bullets_two_lines: int
:param one_enumeration_single_line:
1. first line
:type one_enumeration_single_line: int
:param one_enumeration_two_lines:
1) first line
continued
:type one_enumeration_two_lines: int
:param two_enumerations_one_line:
(iii) first line
(iv) second line
:type two_enumerations_one_line: int
:param two_enumerations_two_lines:
a. first line
continued
b. second line
continued
:type two_enumerations_two_lines: int
:param one_definition_one_line:
item 1
first line
:type one_definition_one_line: int
:param one_definition_two_lines:
item 1
first line
continued
:type one_definition_two_lines: int
:param two_definitions_one_line:
item 1
first line
item 2
second line
:type two_definitions_one_line: int
:param two_definitions_two_lines:
item 1
first line
continued
item 2
second line
continued
:type two_definitions_two_lines: int
:param one_definition_blank_line:
item 1
first line
extra first line
:type one_definition_blank_line: int
:param two_definitions_blank_lines:
item 1
first line
extra first line
item 2
second line
extra second line
:type two_definitions_blank_lines: int
:param definition_after_inline_text: text line
item 1
first line
:type definition_after_inline_text: int
:param definition_after_normal_text: text line
item 1
first line
:type definition_after_normal_text: int
"""
config = Config(napoleon_use_param=True)
actual = str(GoogleDocstring(docstring, config))
self.assertEqual(expected, actual)
expected = """One line summary.
:Parameters: * **no_list** (*int*)
* **one_bullet_empty** (*int*) --
*
* **one_bullet_single_line** (*int*) --
- first line
* **one_bullet_two_lines** (*int*) --
+ first line
continued
* **two_bullets_single_line** (*int*) --
- first line
- second line
* **two_bullets_two_lines** (*int*) --
* first line
continued
* second line
continued
* **one_enumeration_single_line** (*int*) --
1. first line
* **one_enumeration_two_lines** (*int*) --
1) first line
continued
* **two_enumerations_one_line** (*int*) --
(iii) first line
(iv) second line
* **two_enumerations_two_lines** (*int*) --
a. first line
continued
b. second line
continued
* **one_definition_one_line** (*int*) --
item 1
first line
* **one_definition_two_lines** (*int*) --
item 1
first line
continued
* **two_definitions_one_line** (*int*) --
item 1
first line
item 2
second line
* **two_definitions_two_lines** (*int*) --
item 1
first line
continued
item 2
second line
continued
* **one_definition_blank_line** (*int*) --
item 1
first line
extra first line
* **two_definitions_blank_lines** (*int*) --
item 1
first line
extra first line
item 2
second line
extra second line
* **definition_after_inline_text** (*int*) -- text line
item 1
first line
* **definition_after_normal_text** (*int*) -- text line
item 1
first line
"""
config = Config(napoleon_use_param=False)
actual = str(GoogleDocstring(docstring, config))
self.assertEqual(expected, actual)
def test_custom_generic_sections(self):
2018-02-19 09:08:44 -06:00
docstrings = (("""\
Really Important Details:
You should listen to me!
2018-02-19 09:08:44 -06:00
""", """.. rubric:: Really Important Details
You should listen to me!
2018-02-19 09:08:44 -06:00
"""),
("""\
Sooper Warning:
Stop hitting yourself!
2018-02-19 09:08:44 -06:00
""", """:Warns: **Stop hitting yourself!**
"""))
2018-02-19 09:08:44 -06:00
testConfig = Config(napoleon_custom_sections=['Really Important Details',
('Sooper Warning', 'warns')])
for docstring, expected in docstrings:
actual = str(GoogleDocstring(docstring, testConfig))
self.assertEqual(expected, actual)
def test_noindex(self):
docstring = """
Attributes:
arg
description
Methods:
func(i, j)
description
"""
expected = """
.. attribute:: arg
:noindex:
description
.. method:: func(i, j)
:noindex:
description
"""
config = Config()
actual = str(GoogleDocstring(docstring, config=config, app=None, what='module',
options={'noindex': True}))
self.assertEqual(expected, actual)
class NumpyDocstringTest(BaseDocstringTest):
docstrings = [(
"""Single line summary""",
"""Single line summary"""
), (
"""
Single line summary
Extended description
""",
"""
Single line summary
Extended description
"""
), (
"""
Single line summary
Parameters
----------
arg1:str
Extended
description of arg1
""",
"""
Single line summary
:Parameters: **arg1** (*str*) -- Extended
description of arg1
"""
), (
"""
Single line summary
Parameters
----------
arg1:str
Extended
description of arg1
arg2 : int
Extended
description of arg2
Keyword Arguments
-----------------
kwarg1:str
Extended
description of kwarg1
kwarg2 : int
Extended
description of kwarg2
""",
"""
Single line summary
:Parameters: * **arg1** (*str*) -- Extended
description of arg1
* **arg2** (*int*) -- Extended
description of arg2
:Keyword Arguments: * **kwarg1** (*str*) -- Extended
description of kwarg1
* **kwarg2** (*int*) -- Extended
description of kwarg2
"""
), (
"""
Single line summary
Return
------
str
Extended
description of return value
""",
"""
Single line summary
:returns: *str* -- Extended
description of return value
"""
), (
"""
Single line summary
Returns
-------
str
Extended
description of return value
""",
"""
Single line summary
:returns: *str* -- Extended
description of return value
"""
), (
"""
Single line summary
Parameters
----------
arg1:str
Extended description of arg1
*args:
Variable length argument list.
**kwargs:
Arbitrary keyword arguments.
""",
"""
Single line summary
:Parameters: * **arg1** (*str*) -- Extended description of arg1
* **\\*args** -- Variable length argument list.
* **\\*\\*kwargs** -- Arbitrary keyword arguments.
"""
), (
"""
Single line summary
Yield
-----
str
Extended
description of yielded value
""",
"""
Single line summary
:Yields: *str* -- Extended
description of yielded value
"""
), (
"""
Single line summary
Yields
------
str
Extended
description of yielded value
""",
"""
Single line summary
:Yields: *str* -- Extended
description of yielded value
"""
)]
2018-02-13 10:38:44 -06:00
def test_sphinx_admonitions(self):
admonition_map = {
'Attention': 'attention',
'Caution': 'caution',
'Danger': 'danger',
'Error': 'error',
'Hint': 'hint',
'Important': 'important',
'Note': 'note',
'Tip': 'tip',
'Todo': 'todo',
'Warning': 'warning',
'Warnings': 'warning',
}
config = Config()
for section, admonition in admonition_map.items():
# Multiline
actual = str(NumpyDocstring(("{}\n"
2018-02-19 09:08:44 -06:00
"{}\n"
" this is the first line\n"
"\n"
" and this is the second line\n"
).format(section, '-' * len(section)), config))
2018-02-13 10:38:44 -06:00
expect = (".. {}::\n"
"\n"
" this is the first line\n"
" \n"
" and this is the second line\n"
).format(admonition)
self.assertEqual(expect, actual)
# Single line
actual = str(NumpyDocstring(("{}\n"
2018-02-19 09:08:44 -06:00
"{}\n"
" this is a single line\n"
).format(section, '-' * len(section)), config))
2018-02-13 10:38:44 -06:00
expect = (".. {}:: this is a single line\n"
).format(admonition)
self.assertEqual(expect, actual)
def test_docstrings(self):
config = Config(
napoleon_use_param=False,
napoleon_use_rtype=False,
napoleon_use_keyword=False)
for docstring, expected in self.docstrings:
actual = str(NumpyDocstring(dedent(docstring), config))
expected = dedent(expected)
self.assertEqual(expected, actual)
def test_parameters_with_class_reference(self):
docstring = """\
Parameters
----------
param1 : :class:`MyClass <name.space.MyClass>` instance
"""
config = Config(napoleon_use_param=False)
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(docstring, config))
expected = """\
2015-01-09 11:41:09 -06:00
:param param1:
:type param1: :class:`MyClass <name.space.MyClass>` instance
"""
self.assertEqual(expected, actual)
def test_parameters_without_class_reference(self):
docstring = """\
Parameters
----------
param1 : MyClass instance
"""
config = Config(napoleon_use_param=False)
actual = str(NumpyDocstring(docstring, config))
expected = """\
:Parameters: **param1** (*MyClass instance*)
"""
self.assertEqual(expected, actual)
config = Config(napoleon_use_param=True)
actual = str(NumpyDocstring(dedent(docstring), config))
expected = """\
2015-01-09 11:41:09 -06:00
:param param1:
:type param1: MyClass instance
"""
self.assertEqual(expected, actual)
def test_see_also_refs(self):
docstring = """\
numpy.multivariate_normal(mean, cov, shape=None, spam=None)
See Also
--------
some, other, funcs
otherfunc : relationship
"""
actual = str(NumpyDocstring(docstring))
expected = """\
numpy.multivariate_normal(mean, cov, shape=None, spam=None)
.. seealso::
:obj:`some`, :obj:`other`, :obj:`funcs`
\n\
:obj:`otherfunc`
relationship
"""
self.assertEqual(expected, actual)
docstring = """\
numpy.multivariate_normal(mean, cov, shape=None, spam=None)
See Also
--------
some, other, funcs
otherfunc : relationship
"""
config = Config()
2014-08-10 02:31:28 -05:00
app = mock.Mock()
actual = str(NumpyDocstring(docstring, config, app, "method"))
expected = """\
numpy.multivariate_normal(mean, cov, shape=None, spam=None)
.. seealso::
:meth:`some`, :meth:`other`, :meth:`funcs`
\n\
:meth:`otherfunc`
relationship
"""
self.assertEqual(expected, actual)
def test_colon_in_return_type(self):
docstring = """
Summary
Returns
-------
:py:class:`~my_mod.my_class`
an instance of :py:class:`~my_mod.my_class`
"""
expected = """
Summary
:returns: an instance of :py:class:`~my_mod.my_class`
:rtype: :py:class:`~my_mod.my_class`
"""
config = Config()
app = mock.Mock()
actual = str(NumpyDocstring(docstring, config, app, "method"))
self.assertEqual(expected, actual)
def test_underscore_in_attribute(self):
docstring = """
Attributes
----------
arg_ : type
some description
"""
expected = """
:ivar arg_: some description
:vartype arg_: type
"""
config = Config(napoleon_use_ivar=True)
app = mock.Mock()
actual = str(NumpyDocstring(docstring, config, app, "class"))
self.assertEqual(expected, actual)
def test_underscore_in_attribute_strip_signature_backslash(self):
docstring = """
Attributes
----------
arg_ : type
some description
"""
expected = """
:ivar arg\\_: some description
:vartype arg\\_: type
"""
config = Config(napoleon_use_ivar=True)
config.strip_signature_backslash = True
app = mock.Mock()
actual = str(NumpyDocstring(docstring, config, app, "class"))
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 RuntimeError: A setting wasn't specified, or was invalid.
:raises ValueError: Something something value error.
"""),
################################
("""
Example Function
Raises
------
InvalidDimensionsError
""", """
Example Function
:raises 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 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 exc.InvalidDimensionsError:
"""),
################################
("""
Example Function
Raises
------
:class:`exc.InvalidDimensionsError`
If the dimensions couldn't be parsed.
""", """
Example Function
:raises 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 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 exc.InvalidDimensionsError: If the dimensions couldn't be parsed.
:raises exc.InvalidArgumentsError: If the arguments are invalid.
"""),
################################
("""
Example Function
Raises
------
:class:`exc.InvalidDimensionsError`
:class:`exc.InvalidArgumentsError`
""", """
Example Function
:raises exc.InvalidDimensionsError:
:raises 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):
docstring = """
Example Function
Returns
-------
:class:`numpy.ndarray`
A :math:`n \\times 2` array containing
a bunch of math items
"""
expected = """
Example Function
:returns: A :math:`n \\times 2` array containing
a bunch of math items
:rtype: :class:`numpy.ndarray`
"""
config = Config()
app = mock.Mock()
actual = str(NumpyDocstring(docstring, config, app, "method"))
self.assertEqual(expected, actual)
def test_section_header_underline_length(self):
docstrings = [("""
Summary line
Example
-
Multiline example
body
""", """
Summary line
Example
-
Multiline example
body
"""),
################################
("""
Summary line
Example
--
Multiline example
body
""", """
Summary line
.. rubric:: Example
Multiline example
body
"""),
################################
("""
Summary line
Example
-------
Multiline example
body
""", """
Summary line
.. rubric:: Example
Multiline example
body
"""),
################################
("""
Summary line
Example
------------
Multiline example
body
""", """
Summary line
.. rubric:: Example
Multiline example
body
""")]
for docstring, expected in docstrings:
actual = str(NumpyDocstring(docstring))
self.assertEqual(expected, actual)
def test_list_in_parameter_description(self):
docstring = """One line summary.
Parameters
----------
no_list : int
one_bullet_empty : int
*
one_bullet_single_line : int
- first line
one_bullet_two_lines : int
+ first line
continued
two_bullets_single_line : int
- first line
- second line
two_bullets_two_lines : int
* first line
continued
* second line
continued
one_enumeration_single_line : int
1. first line
one_enumeration_two_lines : int
1) first line
continued
two_enumerations_one_line : int
(iii) first line
(iv) second line
two_enumerations_two_lines : int
a. first line
continued
b. second line
continued
one_definition_one_line : int
item 1
first line
one_definition_two_lines : int
item 1
first line
continued
two_definitions_one_line : int
item 1
first line
item 2
second line
two_definitions_two_lines : int
item 1
first line
continued
item 2
second line
continued
one_definition_blank_line : int
item 1
first line
extra first line
two_definitions_blank_lines : int
item 1
first line
extra first line
item 2
second line
extra second line
definition_after_normal_text : int
text line
item 1
first line
"""
expected = """One line summary.
:param no_list:
:type no_list: int
:param one_bullet_empty:
*
:type one_bullet_empty: int
:param one_bullet_single_line:
- first line
:type one_bullet_single_line: int
:param one_bullet_two_lines:
+ first line
continued
:type one_bullet_two_lines: int
:param two_bullets_single_line:
- first line
- second line
:type two_bullets_single_line: int
:param two_bullets_two_lines:
* first line
continued
* second line
continued
:type two_bullets_two_lines: int
:param one_enumeration_single_line:
1. first line
:type one_enumeration_single_line: int
:param one_enumeration_two_lines:
1) first line
continued
:type one_enumeration_two_lines: int
:param two_enumerations_one_line:
(iii) first line
(iv) second line
:type two_enumerations_one_line: int
:param two_enumerations_two_lines:
a. first line
continued
b. second line
continued
:type two_enumerations_two_lines: int
:param one_definition_one_line:
item 1
first line
:type one_definition_one_line: int
:param one_definition_two_lines:
item 1
first line
continued
:type one_definition_two_lines: int
:param two_definitions_one_line:
item 1
first line
item 2
second line
:type two_definitions_one_line: int
:param two_definitions_two_lines:
item 1
first line
continued
item 2
second line
continued
:type two_definitions_two_lines: int
:param one_definition_blank_line:
item 1
first line
extra first line
:type one_definition_blank_line: int
:param two_definitions_blank_lines:
item 1
first line
extra first line
item 2
second line
extra second line
:type two_definitions_blank_lines: int
:param definition_after_normal_text: text line
item 1
first line
:type definition_after_normal_text: int
"""
config = Config(napoleon_use_param=True)
actual = str(NumpyDocstring(docstring, config))
self.assertEqual(expected, actual)
expected = """One line summary.
:Parameters: * **no_list** (*int*)
* **one_bullet_empty** (*int*) --
*
* **one_bullet_single_line** (*int*) --
- first line
* **one_bullet_two_lines** (*int*) --
+ first line
continued
* **two_bullets_single_line** (*int*) --
- first line
- second line
* **two_bullets_two_lines** (*int*) --
* first line
continued
* second line
continued
* **one_enumeration_single_line** (*int*) --
1. first line
* **one_enumeration_two_lines** (*int*) --
1) first line
continued
* **two_enumerations_one_line** (*int*) --
(iii) first line
(iv) second line
* **two_enumerations_two_lines** (*int*) --
a. first line
continued
b. second line
continued
* **one_definition_one_line** (*int*) --
item 1
first line
* **one_definition_two_lines** (*int*) --
item 1
first line
continued
* **two_definitions_one_line** (*int*) --
item 1
first line
item 2
second line
* **two_definitions_two_lines** (*int*) --
item 1
first line
continued
item 2
second line
continued
* **one_definition_blank_line** (*int*) --
item 1
first line
extra first line
* **two_definitions_blank_lines** (*int*) --
item 1
first line
extra first line
item 2
second line
extra second line
* **definition_after_normal_text** (*int*) -- text line
item 1
first line
"""
config = Config(napoleon_use_param=False)
actual = str(NumpyDocstring(docstring, config))
self.assertEqual(expected, actual)
def test_keywords_with_types(self):
docstring = """\
Do as you please
Keyword Args:
gotham_is_yours (None): shall interfere.
"""
actual = str(GoogleDocstring(docstring))
expected = """\
Do as you please
:keyword gotham_is_yours: shall interfere.
:kwtype gotham_is_yours: None
"""
self.assertEqual(expected, actual)