Skip to content

Commit

Permalink
Merge pull request #8658 from SolidifiedRay/feature-custom-section
Browse files Browse the repository at this point in the history
Close #8573: napoleon: Add more custom section styles
  • Loading branch information
tk0miya committed Jan 19, 2021
2 parents 40f2c83 + 7ad85cd commit ca06770
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 8 deletions.
26 changes: 25 additions & 1 deletion doc/usage/extensions/napoleon.rst
Original file line number Diff line number Diff line change
Expand Up @@ -546,4 +546,28 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
If an attribute is documented in the docstring without a type and
has an annotation in the class body, that type is used.

.. versionadded:: 3.4
.. versionadded:: 3.4

.. confval:: napoleon_custom_sections

Add a list of custom sections to include, expanding the list of parsed sections.
*Defaults to None.*

The entries can either be strings or tuples, depending on the intention:

* To create a custom "generic" section, just pass a string.
* To create an alias for an existing section, pass a tuple containing the
alias name and the original, in that order.
* To create a custom section that displays like the parameters or returns
section, pass a tuple containing the custom section name and a string
value, "params_style" or "returns_style".

If an entry is just a string, it is interpreted as a header for a generic
section. If the entry is a tuple/list/indexed container, the first entry
is the name of the section, the second is the section key to emulate. If the
second entry value is "params_style" or "returns_style", the custom section
will be displayed like the parameters section or returns section.

.. versionadded:: 1.8
.. versionchanged:: 3.5
Support ``params_style`` and ``returns_style``
7 changes: 6 additions & 1 deletion sphinx/ext/napoleon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,15 @@ def __unicode__(self):
* To create a custom "generic" section, just pass a string.
* To create an alias for an existing section, pass a tuple containing the
alias name and the original, in that order.
* To create a custom section that displays like the parameters or returns
section, pass a tuple containing the custom section name and a string
value, "params_style" or "returns_style".
If an entry is just a string, it is interpreted as a header for a generic
section. If the entry is a tuple/list/indexed container, the first entry
is the name of the section, the second is the section key to emulate.
is the name of the section, the second is the section key to emulate. If the
second entry value is "params_style" or "returns_style", the custom section
will be displayed like the parameters section or returns section.
napoleon_attr_annotations : :obj:`bool` (Defaults to True)
Use the type annotations of class attributes that are documented in the docstring
Expand Down
24 changes: 19 additions & 5 deletions sphinx/ext/napoleon/docstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,11 +549,18 @@ def _load_custom_sections(self) -> None:
self._sections[entry.lower()] = self._parse_custom_generic_section
else:
# otherwise, assume entry is container;
# [0] is new section, [1] is the section to alias.
# in the case of key mismatch, just handle as generic section.
self._sections[entry[0].lower()] = \
self._sections.get(entry[1].lower(),
self._parse_custom_generic_section)
if entry[1] == "params_style":
self._sections[entry[0].lower()] = \
self._parse_custom_params_style_section
elif entry[1] == "returns_style":
self._sections[entry[0].lower()] = \
self._parse_custom_returns_style_section
else:
# [0] is new section, [1] is the section to alias.
# in the case of key mismatch, just handle as generic section.
self._sections[entry[0].lower()] = \
self._sections.get(entry[1].lower(),
self._parse_custom_generic_section)

def _parse(self) -> None:
self._parsed_lines = self._consume_empty()
Expand Down Expand Up @@ -641,6 +648,13 @@ def _parse_custom_generic_section(self, section: str) -> List[str]:
# for now, no admonition for simple custom sections
return self._parse_generic_section(section, False)

def _parse_custom_params_style_section(self, section: str) -> List[str]:
return self._format_fields(section, self._consume_fields())

def _parse_custom_returns_style_section(self, section: str) -> List[str]:
fields = self._consume_returns_section()
return self._format_fields(section, fields)

def _parse_usage_section(self, section: str) -> List[str]:
header = ['.. rubric:: Usage:', '']
block = ['.. code-block:: python', '']
Expand Down
19 changes: 18 additions & 1 deletion tests/test_ext_napoleon_docstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -1072,10 +1072,27 @@ def test_custom_generic_sections(self):
Sooper Warning:
Stop hitting yourself!
""", """:Warns: **Stop hitting yourself!**
"""),
("""\
Params Style:
arg1 (int): Description of arg1
arg2 (str): Description of arg2
""", """\
:Params Style: * **arg1** (*int*) -- Description of arg1
* **arg2** (*str*) -- Description of arg2
"""),
("""\
Returns Style:
description of custom section
""", """:Returns Style: description of custom section
"""))

testConfig = Config(napoleon_custom_sections=['Really Important Details',
('Sooper Warning', 'warns')])
('Sooper Warning', 'warns'),
('Params Style', 'params_style'),
('Returns Style', 'returns_style')])

for docstring, expected in docstrings:
actual = str(GoogleDocstring(docstring, testConfig))
Expand Down

0 comments on commit ca06770

Please sign in to comment.