mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Napoleon: custom section headers (#4387)
* Changes to allow for custom sections in google/numpy comments when parsing with napoleon * fixed some formatting to pass flake8 tests
This commit is contained in:
2
CHANGES
2
CHANGES
@@ -174,6 +174,8 @@ Features added
|
||||
|
||||
* #4271: sphinx-build supports an option called ``-j auto`` to adjust numbers of
|
||||
processes automatically.
|
||||
* Napoleon: added option to specify custom section tags.
|
||||
|
||||
|
||||
Features removed
|
||||
----------------
|
||||
|
||||
@@ -47,6 +47,7 @@ class Config(object):
|
||||
napoleon_use_param = True
|
||||
napoleon_use_rtype = True
|
||||
napoleon_use_keyword = True
|
||||
napoleon_custom_sections = None
|
||||
|
||||
.. _Google style:
|
||||
https://google.github.io/styleguide/pyguide.html
|
||||
@@ -241,6 +242,19 @@ class Config(object):
|
||||
|
||||
:returns: *bool* -- True if successful, False otherwise
|
||||
|
||||
napoleon_custom_sections : :obj:`list` (Defaults to None)
|
||||
Add a list of custom sections to include, expanding the list of parsed sections.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
"""
|
||||
_config_values = {
|
||||
'napoleon_google_docstring': (True, 'env'),
|
||||
@@ -254,7 +268,8 @@ class Config(object):
|
||||
'napoleon_use_ivar': (False, 'env'),
|
||||
'napoleon_use_param': (True, 'env'),
|
||||
'napoleon_use_rtype': (True, 'env'),
|
||||
'napoleon_use_keyword': (True, 'env')
|
||||
'napoleon_use_keyword': (True, 'env'),
|
||||
'napoleon_custom_sections': (None, 'env')
|
||||
}
|
||||
|
||||
def __init__(self, **settings):
|
||||
|
||||
@@ -170,6 +170,9 @@ class GoogleDocstring(UnicodeMixin):
|
||||
'yield': self._parse_yields_section,
|
||||
'yields': self._parse_yields_section,
|
||||
} # type: Dict[unicode, Callable]
|
||||
|
||||
self._load_custom_sections()
|
||||
|
||||
self._parse()
|
||||
|
||||
def __unicode__(self):
|
||||
@@ -530,6 +533,23 @@ class GoogleDocstring(UnicodeMixin):
|
||||
line and
|
||||
not self._is_indented(line, self._section_indent)))
|
||||
|
||||
def _load_custom_sections(self):
|
||||
# type: () -> None
|
||||
|
||||
if self._config.napoleon_custom_sections is not None:
|
||||
for entry in self._config.napoleon_custom_sections:
|
||||
if isinstance(entry, string_types):
|
||||
# if entry is just a label, add to sections list,
|
||||
# using generic section logic.
|
||||
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)
|
||||
|
||||
def _parse(self):
|
||||
# type: () -> None
|
||||
self._parsed_lines = self._consume_empty()
|
||||
@@ -597,6 +617,10 @@ class GoogleDocstring(UnicodeMixin):
|
||||
use_admonition = self._config.napoleon_use_admonition_for_examples
|
||||
return self._parse_generic_section(section, use_admonition)
|
||||
|
||||
def _parse_custom_generic_section(self, section):
|
||||
# for now, no admonition for simple custom sections
|
||||
return self._parse_generic_section(section, False)
|
||||
|
||||
def _parse_usage_section(self, section):
|
||||
# type: (unicode) -> List[unicode]
|
||||
header = ['.. rubric:: Usage:', ''] # type: List[unicode]
|
||||
|
||||
@@ -966,6 +966,28 @@ Parameters:
|
||||
actual = str(GoogleDocstring(docstring, config))
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_custom_generic_sections(self):
|
||||
|
||||
docstrings=("""\
|
||||
Really Important Details:
|
||||
You should listen to me!
|
||||
""",
|
||||
""".. rubric:: Really Important Details
|
||||
|
||||
You should listen to me!
|
||||
"""),\
|
||||
("""\
|
||||
Sooper Warning:
|
||||
Stop hitting yourself!
|
||||
""",""":Warns: **Stop hitting yourself!**
|
||||
""")
|
||||
|
||||
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)
|
||||
|
||||
|
||||
class NumpyDocstringTest(BaseDocstringTest):
|
||||
docstrings = [(
|
||||
|
||||
Reference in New Issue
Block a user