Ejemplo n.º 1
0
    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()
        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)
Ejemplo n.º 2
0
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[:]
Ejemplo n.º 3
0
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[:]
Ejemplo n.º 4
0
    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

   Quick description of attr1

   :type: Arbitrary type

.. attribute:: attr2

   Quick description of attr2

   :type: Another arbitrary type

.. attribute:: attr3

   Adds a newline after the type

   :type: Type
"""

        self.assertEqual(expected, actual)
Ejemplo n.º 5
0
 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)
Ejemplo n.º 6
0
def _parse_doc(func):
    """Extract documentation from a function's docstring."""
    doc = inspect.getdoc(func)
    if doc is None:
        return _Doc('', {})

    # Convert Google- or Numpy-style docstrings to RST.
    # (Should do nothing if not in either style.)
    doc = str(GoogleDocstring(doc))
    doc = str(NumpyDocstring(doc))

    dom = publish_doctree(doc).asdom()
    etree = ElementTree.fromstring(dom.toxml())
    doctext = []
    for element in etree:
        if element.tag == 'paragraph':
            doctext.append(_get_text(element))
        elif element.tag == 'literal_block':
            doctext.append(_indent(_get_text(element)))
    doctext = '\n\n'.join(doctext)
    fields = etree.findall('.//field')

    params = defaultdict(dict)
    for field in fields:
        field_name = field.find('field_name')
        field_body = field.find('field_body')
        parts = field_name.text.split()
        if len(parts) == 2:
            doctype, name = parts
        elif len(parts) == 3:
            doctype, type_, name = parts
            if doctype not in _PARAM_TYPES:
                log.debug('ignoring field %s', field_name.text)
                continue
            log.debug('inline param type %s', type_)
            if 'type' in params[name]:
                raise ValueError('type defined twice for {}'.format(name))
            params[name]['type'] = type_
        else:
            log.debug('ignoring field %s', field_name.text)
            continue
        if doctype in _PARAM_TYPES:
            doctype = 'param'
        if doctype in _TYPE_NAMES:
            doctype = 'type'
        text = _get_text(field_body)
        log.debug('%s %s: %s', doctype, name, text)
        if doctype in params[name]:
            raise ValueError('{} defined twice for {}'.format(doctype, name))
        params[name][doctype] = text

    tuples = {}
    for name, values in params.items():
        tuples[name] = _Param(values.get('param'), values.get('type'))
    return _Doc(doctext, tuples)
Ejemplo n.º 7
0
def _process_docstring(app, what, name, obj, options, lines):
    result_lines = lines
    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[:]
Ejemplo n.º 8
0
    def __get_class_docs__(cls):

        output = list()

        class_docs = {}
        if cls.__doc__:
            lines = inspect.getdoc(cls).split('\n')

            lines = list(filter(lambda x: len(x.strip()) > 0, lines))

            section = 'Desc'
            class_docs[section] = []

            for i in range(len(lines)):
                if '---' in lines[i]:
                    del class_docs[section][-1]
                    section = lines[i - 1].strip()
                    class_docs[section] = []
                line = lines[i].strip()
                class_docs[section].append(line)

        class_docs['Parameters'] = []

        docparam = ''
        for key in cls.SECTIONS:
            if key in class_docs.keys():
                value = class_docs[key]
                if key == 'Desc':
                    docparam += '\n'.join(value)
                elif key == 'Parameters':
                    params = cls.__parameters__()
                    if len(params) > 0:
                        docparam += '\nParameters\n'
                        docparam += '---------\n'
                        for p in params:
                            docparam += p + ' : ' + str(type(p)) + '\n'
                            if hasattr(cls, p):
                                param_attr = getattr(cls, p)
                                if hasattr(param_attr, '__doc__'):
                                    docparam += '\t' + param_attr.__doc__ + '\n'
                else:
                    docparam += '{}\n{}\n'.format(key, '\n'.join(value))
                docparam += '\n'

        from sphinxcontrib.napoleon import Config
        config = Config(napoleon_use_param=True, napoleon_use_rtype=True)
        from sphinxcontrib.napoleon.docstring import NumpyDocstring
        lines = NumpyDocstring(docparam, config).lines()

        output.extend(lines)

        return output
Ejemplo n.º 9
0
    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"
                                "{}\n"
                                "    this is the first line\n"
                                "\n"
                                "    and this is the second line\n").format(
                                    section, '-' * len(section)), config))
            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"
                                "{}\n"
                                "    this is a single line\n").format(
                                    section, '-' * len(section)), config))
            expect = (".. {}:: this is a single line\n").format(admonition)
            self.assertEqual(expect, actual)
Ejemplo n.º 10
0
    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 = """\
:param param1:
:type param1: :class:`MyClass <name.space.MyClass>` instance
"""
        self.assertEqual(expected, actual)
Ejemplo n.º 11
0
    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 = """\
:param param1:
:type param1: MyClass instance
"""
        self.assertEqual(expected, actual)
Ejemplo n.º 12
0
    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)
Ejemplo n.º 13
0
    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)
Ejemplo n.º 14
0
    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)
Ejemplo n.º 15
0
 def convert_docstring(docstring):
     if is_google_style(docstring):
         return str(GoogleDocstring(docstring, CONFIG))
     elif is_numpy_style(docstring):
         return str(NumpyDocstring(docstring, CONFIG))
     return docstring
Ejemplo n.º 16
0
 def test_docstrings(self):
     for docstring, expected in self.docstrings:
         actual = str(NumpyDocstring(textwrap.dedent(docstring)))
         expected = textwrap.dedent(expected)
         self.assertEqual(expected, actual)
Ejemplo n.º 17
0
    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)
Ejemplo n.º 18
0
    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)
Ejemplo n.º 19
0
    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)
Ejemplo n.º 20
0
    def test_raises_types(self):
        docstrings = [
            ("""
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:
            config = Config()
            app = Mock()
            actual = str(NumpyDocstring(docstring, config, app, "method"))
            self.assertEqual(expected, actual)
Ejemplo n.º 21
0
def _parse_docstring(doc):
    """Extract documentation from a function's docstring."""
    _cache_key = doc
    try:
        return _parse_docstring_cache[_cache_key]
    except KeyError:
        pass

    if doc is None:
        return _Doc('', '', {})

    # Convert Google- or Numpy-style docstrings to RST.
    # (Should do nothing if not in either style.)
    doc = str(GoogleDocstring(doc))
    doc = str(NumpyDocstring(doc))

    tree = publish_doctree(doc)

    class Visitor(NodeVisitor):
        optional = [
            'document', 'docinfo',
            'field_list', 'field_body',
            'literal', 'problematic']

        def __init__(self, document):
            NodeVisitor.__init__(self, document)
            self.paragraphs = []
            self.start_lines = []
            self.params = defaultdict(dict)
            self._current_paragraph = None
            self._indent_iterator_stack = []
            self._indent_stack = []

        def _do_nothing(self, node):
            pass

        def visit_paragraph(self, node):
            self.start_lines.append(node.line)
            self._current_paragraph = []

        def depart_paragraph(self, node):
            text = ''.join(self._current_paragraph)
            text = ''.join(self._indent_stack) + text
            self._indent_stack = [
                ' ' * len(item) for item in self._indent_stack]
            text = text.replace('\n', '\n' + ''.join(self._indent_stack))
            self.paragraphs.append(text)
            self._current_paragraph = None

        def visit_Text(self, node):
            self._current_paragraph.append(node)

        depart_Text = _do_nothing

        def visit_emphasis(self, node):
            self._current_paragraph.append('\033[3m')  # *foo*: italic

        def visit_strong(self, node):
            self._current_paragraph.append('\033[1m')  # **foo**: bold

        def visit_title_reference(self, node):
            self._current_paragraph.append('\033[4m')  # `foo`: underlined

        def _depart_markup(self, node):
            self._current_paragraph.append('\033[0m')

        depart_emphasis = depart_strong = depart_title_reference = \
            _depart_markup

        def visit_literal_block(self, node):
            text, = node
            self.start_lines.append(node.line)
            self.paragraphs.append(re.sub('^|\n', r'\g<0>    ', text))  # indent
            raise SkipNode

        def visit_bullet_list(self, node):
            self._indent_iterator_stack.append(
                (node['bullet'] + ' ' for _ in range(len(node))))

        def depart_bullet_list(self, node):
            self._indent_iterator_stack.pop()

        def visit_enumerated_list(self, node):
            enumtype = node['enumtype']
            fmt = {('(', ')'): 'parens',
                   ('', ')'): 'rparen',
                   ('', '.'): 'period'}[node['prefix'], node['suffix']]
            try:
                start = node['start']
            except KeyError:
                start = 1
            else:
                start = {
                    'arabic': int,
                    'loweralpha': lambda s: ord(s) - ord('a') + 1,
                    'upperalpha': lambda s: ord(s) - ord('A') + 1,
                    'lowerroman': lambda s: roman.fromRoman(s.upper()),
                    'upperroman': lambda s: roman.fromRoman(s),
                }[enumtype](start)
            enumerators = [Body(None).make_enumerator(i, enumtype, fmt)[0]
                           for i in range(start, start + len(node))]
            width = max(map(len, enumerators))
            enumerators = [enum.ljust(width) for enum in enumerators]
            self._indent_iterator_stack.append(iter(enumerators))

        def depart_enumerated_list(self, node):
            self._indent_iterator_stack.pop()

        def visit_list_item(self, node):
            self._indent_stack.append(next(self._indent_iterator_stack[-1]))

        def depart_list_item(self, node):
            self._indent_stack.pop()

        def visit_field(self, node):
            field_name_node, field_body_node = node
            field_name, = field_name_node
            parts = field_name.split()
            if len(parts) == 2:
                doctype, name = parts
            elif len(parts) == 3:
                doctype, type_, name = parts
                if doctype not in _PARAM_TYPES:
                    raise SkipNode
                if 'type' in self.params[name]:
                    raise ValueError('type defined twice for {}'.format(name))
                self.params[name]['type'] = type_
            else:
                raise SkipNode
            if doctype in _PARAM_TYPES:
                doctype = 'param'
            if doctype in _TYPE_NAMES:
                doctype = 'type'
            if doctype in self.params[name]:
                raise ValueError(
                    '{} defined twice for {}'.format(doctype, name))
            visitor = Visitor(self.document)
            field_body_node.walkabout(visitor)
            self.params[name][doctype] = ''.join(visitor.paragraphs)
            raise SkipNode

        def visit_comment(self, node):
            raise SkipNode

        def visit_system_message(self, node):
            raise SkipNode

    visitor = Visitor(tree)
    tree.walkabout(visitor)

    tuples = {name: _Param(values.get('param'), values.get('type'))
              for name, values in visitor.params.items()}
    if visitor.paragraphs:
        text = []
        for start, paragraph, next_start in zip(
                visitor.start_lines,
                visitor.paragraphs,
                visitor.start_lines[1:] + [0]):
            text.append(paragraph)
            # We insert a space before each newline to prevent argparse
            # from stripping consecutive newlines down to just two
            # (http://bugs.python.org/issue31330).
            text.append(' \n' * (next_start - start - paragraph.count('\n')))
        parsed = _Doc('', ''.join(text), tuples)
    else:
        parsed = _Doc('', '', tuples)
    _parse_docstring_cache[_cache_key] = parsed
    return parsed
Ejemplo n.º 22
0
def main(text=None):
    src = sys.stdin.read() if text is None else text
    rest_formatter.main(str(NumpyDocstring(textwrap.dedent(src))))