def _process_docstring(app, what, name, obj, options, lines): # type: (Sphinx, unicode, unicode, Any, Any, List[unicode]) -> None """Process the docstring for a given python object. Called when autodoc has read and processed a docstring. `lines` is a list of docstring lines that `_process_docstring` modifies in place to change what Sphinx outputs. The following settings in conf.py control what styles of docstrings will be parsed: * ``napoleon_google_docstring`` -- parse Google style docstrings * ``napoleon_numpy_docstring`` -- parse NumPy style docstrings Parameters ---------- app : sphinx.application.Sphinx Application object representing the Sphinx process. what : str A string specifying the type of the object to which the docstring belongs. Valid values: "module", "class", "exception", "function", "method", "attribute". name : str The fully qualified name of the object. obj : module, class, exception, function, method, or attribute The object to which the docstring belongs. options : sphinx.ext.autodoc.Options The options given to the directive: an object with attributes inherited_members, undoc_members, show_inheritance and noindex that are True if the flag option of same name was given to the auto directive. lines : list of str The lines of the docstring, see above. .. note:: `lines` is modified *in place* """ result_lines = lines docstring = None # type: GoogleDocstring if app.config.napoleon_numpy_docstring: docstring = NumpyDocstring(result_lines, app.config, app, what, name, obj, options) result_lines = docstring.lines() if app.config.napoleon_google_docstring: docstring = GoogleDocstring(result_lines, app.config, app, what, name, obj, options) result_lines = docstring.lines() lines[:] = result_lines[:]
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 get_googledocstring(view_cls, html=False): """Parses a docstring containing Google-style docs into HTML. This uses the Napoleon Sphinx extension to parse Google-style argument docstrings into reStructuredText, then convert these into HTML for django-rest-swagger. """ from docutils import core description = view_cls.__doc__ or '' config = Config(napoleon_use_param=False, napoleon_use_rtype=False) description = GoogleDocstring(description, config=config) description = formatting.dedent(smart_text(description)) if html: parts = core.publish_parts(source=description, writer_name='html') html = parts['body_pre_docinfo'] + parts['fragment'] return mark_safe(html) return description
def test_class_data_member(self): config = Config() docstring = """data member description: - a: b """ actual = str( GoogleDocstring(docstring, config=config, app=None, what='attribute', name='some_data', obj=0)) expected = """data member description: - a: b""" 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)
def test_parameters_with_class_reference(self): docstring = """\ Construct a new XBlock. This class should only be used by runtimes. Arguments: runtime (:class:`Runtime`): 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``. :type runtime: :class:`Runtime` :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 docutilize(obj): """Convert Numpy or Google style docstring into reStructuredText format. Args: obj (str or object): Takes an object and changes it's docstrings to a reStructuredText format. Returns: str or object: A converted string or an object with replaced docstring depending on the type of the input. """ from inspect import cleandoc, getdoc from sphinx.ext.napoleon.docstring import GoogleDocstring, NumpyDocstring if isinstance(obj, str): doc = cleandoc(obj) else: doc = getdoc(obj) doc = str(NumpyDocstring(doc)) doc = str(GoogleDocstring(doc)) if isinstance(obj, str): return doc obj.__doc__ = doc return obj
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_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_docstrings(self): config = Config(napoleon_use_param=False, napoleon_use_rtype=False) for docstring, expected in self.docstrings: actual = str(GoogleDocstring(dedent(docstring), config)) expected = dedent(expected) 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: * :exc:`RuntimeError` -- A setting wasn't specified, or was invalid. * :exc:`ValueError` -- Something something value error. """), ################################ (""" Example Function Raises: InvalidDimensionsError """, """ Example Function :raises: :exc:`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: :exc:`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: :class:`exc.InvalidDimensionsError` """), ################################ (""" Example Function Raises: :class:`exc.InvalidDimensionsError`: If the dimensions couldn't be parsed. """, """ Example Function :raises: :class:`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: :class:`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: * :class:`exc.InvalidDimensionsError` -- If the dimensions """ """couldn't be parsed. * :class:`exc.InvalidArgumentsError` -- If the arguments are invalid. """), ################################ (""" Example Function Raises: :class:`exc.InvalidDimensionsError` :class:`exc.InvalidArgumentsError` """, """ Example Function :raises: * :class:`exc.InvalidDimensionsError` * :class:`exc.InvalidArgumentsError` """)] for docstring, expected in docstrings: actual = str(GoogleDocstring(docstring)) self.assertEqual(expected, actual)
def test_docstrings(self): for docstring, expected in self.docstrings: actual = str(GoogleDocstring(textwrap.dedent(docstring))) expected = textwrap.dedent(expected) self.assertEqual(expected, actual)
def _parse_docstring(self, docstr): gds = GoogleDocstring(prepare_docstring(docstr)) doctree = publish_doctree(str(gds)) self._parse_doctree(doctree)
def doc(self): return "" if self._doc is None else str(GoogleDocstring(self._doc))