Source code for sphinx_c_autodoc.napoleon

"""
Extend napoleon to provide a `Members` section for C structs and unions
similar to the `Attributes` section in python objects.
"""

from functools import partial

from typing import Optional, Any, List, Union, Dict, Callable

from sphinx.config import Config
from sphinx.ext.autodoc import Options
from sphinx.application import Sphinx
from sphinx.ext.napoleon import GoogleDocstring


# pylint: disable=too-few-public-methods
[docs] class CAutoDocString(GoogleDocstring): """ A docstring that can handle documenting some extra c sections, in particular, `members` sections of structs and unions and `enumerators` sections of enums. """ # pylint: disable=too-many-positional-arguments def __init__( self, docstring: Union[str, List[str]], config: Optional[Config] = None, app: Optional[Sphinx] = None, what: str = "", name: str = "", obj: Optional[Any] = None, options: Optional[Options] = None, ) -> None: if not hasattr(self, "_sections"): self._sections = self.get_default_sections() # The GoogleDocstring is using the implied optional `config: Config = None` # and mypy complains that these shouldn't be optional super().__init__( docstring, config, # type: ignore app, # type: ignore what, name, obj, options, )
[docs] def get_default_sections(self) -> Dict[str, Callable]: """ Creates the dictionary that should be used in :attr:`_sections` for this instance. If one wants to extend this class simply do:: class MyDocString(CAutoDocString): def get_default_sections(self) -> Dict[str, Callable]: sections = super().get_default_sections() sections["my_custom_section"] = self._some_method Returns: Dict[str, Callable]: The dictionary of sections to methods that should be used :attr:`_sections`. """ default_sections: Dict[str, Callable] = { "args": self._parse_parameters_section, "arguments": self._parse_parameters_section, "attention": partial(self._parse_admonition, "attention"), "attributes": self._parse_attributes_section, "caution": partial(self._parse_admonition, "caution"), "danger": partial(self._parse_admonition, "danger"), "enumerators": partial(self._parse_nested_section, "enumerator"), "error": partial(self._parse_admonition, "error"), "example": self._parse_examples_section, "examples": self._parse_examples_section, "hint": partial(self._parse_admonition, "hint"), "important": partial(self._parse_admonition, "important"), "members": partial(self._parse_nested_section, "member"), "note": partial(self._parse_admonition, "note"), "notes": self._parse_notes_section, "parameters": self._parse_parameters_section, "return": self._parse_returns_section, "returns": self._parse_returns_section, "references": self._parse_references_section, "see also": self._parse_see_also_section, "tip": partial(self._parse_admonition, "tip"), "todo": partial(self._parse_admonition, "todo"), "warning": partial(self._parse_admonition, "warning"), "warnings": partial(self._parse_admonition, "warning"), "warns": self._parse_warns_section, "yield": self._parse_yields_section, "yields": self._parse_yields_section, } return default_sections
# pylint: disable=unused-argument def _parse_nested_section(self, nested_title: str, section: str) -> List[str]: """ Parse a members section of a comment. The members section is only expected to be seen in processing of C files. Each item will be formatted using the ``.. c:member:: <name>`` syntax. Args: section (str): The name of the parsed section. Unused. nested_title (str): The name to give to the nested items. Returns: List[str]: The list of lines from `section` converted to the appropriate reST. """ # Place a blank line prior to the section this ensures there is a # newline prior to the first `.. c:member::` section and thus it # doesn't get treated as a sentence in the same paragraph lines = [""] # Type should be unused, it's not normal in c to do `var (type)` it's # usually `type var` for name, _, desc in self._consume_fields(): lines.extend([f".. c:{nested_title}:: {name}", ""]) fields = self._format_field("", "", desc) lines.extend(self._indent(fields, 3)) lines.append("") return lines
# pylint: disable=too-many-positional-arguments
[docs] def process_autodoc_docstring( app: Any, what: str, name: str, obj: Any, options: Optional[Options], lines: List[str], ) -> None: """ Call back for autodoc's ``autodoc-process-docstring`` event. Args: app (:class:`Sphinx`): The Sphinx application object what (str): The type of the object which the comment belongs to. One of "cmodule", "cmember", "ctype", "cfunction", "cstruct". name (str): The fully qualified name of the object. For C files this may be a little polluted as it will be ``my_file.c.some_item.some_items_member``. obj (any): The object itself options (dict): The options given to the directive. lines (List[str]): The lines of the comment. This is modified in place. """ docstring = CAutoDocString(lines, app.config, app, what, name, obj, options) result_lines = docstring.lines() lines[:] = result_lines[:]
[docs] def setup(app: Sphinx) -> None: """ Extend sphinx to assist sphinx_c_autodocs to allow Google style docstrings for C constructs. Args: app (:class:`Sphinx`): The Sphinx application object """ app.setup_extension("sphinx.ext.napoleon") app.connect("autodoc-process-docstring", process_autodoc_docstring)