xdoctest.docstr.docscrape_google module

Handles parsing of information out of google style docstrings

It is not clear which of these GoogleStyleDocs1 GoogleStyleDocs2 is the standard or if there is one.

This code has been exported to a standalone package

This is similar to:

It hasn’t been decided if this will remain vendored in xdoctest or pulled in as a dependency.

References

class xdoctest.docstr.docscrape_google.DocBlock(text, offset)

Bases: tuple

Create new instance of DocBlock(text, offset)

offset

Alias for field number 1

text

Alias for field number 0

xdoctest.docstr.docscrape_google.split_google_docblocks(docstr)[source]

Breaks a docstring into parts defined by google style

Parameters:

docstr (str) – a docstring

Returns:

list of 2-tuples where the first item is a google style docstring tag and the second item is the bock corresponding to that tag. The block itself is a 2-tuple where the first item is the unindented text and the second item is the line offset indicating that blocks location in the docstring.

Return type:

List[Tuple[str, DocBlock]]

Note

Unknown or “freeform” sections are given a generic “__DOC__” tag. A section tag may be specified multiple times.

CommandLine

xdoctest xdoctest.docstr.docscrape_google split_google_docblocks:2

Example

>>> from xdoctest.docstr.docscrape_google import *  # NOQA
>>> from xdoctest import utils
>>> docstr = utils.codeblock(
...     '''
...     one line description
...
...     multiline
...     description
...
...     Args:
...         foo: bar
...
...     Returns:
...         None
...
...     Example:
...         >>> print('eg1')
...         eg1
...
...     Example:
...         >>> print('eg2')
...         eg2
...     ''')
>>> groups = split_google_docblocks(docstr)
>>> assert len(groups) == 5
>>> [g[0] for g in groups]
['__DOC__', 'Args', 'Returns', 'Example', 'Example']

Example

>>> from xdoctest.docstr.docscrape_google import *  # NOQA
>>> docstr = split_google_docblocks.__doc__
>>> groups = split_google_docblocks(docstr)

Example

>>> from xdoctest.docstr.docscrape_google import *  # NOQA
>>> from xdoctest import utils
>>> docstr = utils.codeblock(
...     '''
...      a description with a leading space
...
...     Example:
...         >>> foobar
...     ''')
>>> groups = split_google_docblocks(docstr)
>>> print('groups = {!r}'.format(groups))

Example

>>> from xdoctest.docstr.docscrape_google import *  # NOQA
>>> from xdoctest import utils
>>> docstr = utils.codeblock(
...     '''
...     Example:
...         >>> foobar
...     ''')
>>> # Check that line offsets are valid if the first line is not blank
>>> groups = split_google_docblocks(docstr)
>>> offset = groups[0][1][1]
>>> print('offset = {!r}'.format(offset))
>>> assert offset == 0
>>> # Check that line offsets are valid if the first line is blank
>>> groups = split_google_docblocks(chr(10) + docstr)
>>> offset = groups[0][1][1]
>>> print('offset = {!r}'.format(offset))
>>> assert offset == 1
xdoctest.docstr.docscrape_google.parse_google_args(docstr)[source]

Generates dictionaries of argument hints based on a google docstring

Parameters:

docstr (str) – a google-style docstring

Yields:

Dict[str, str] – dictionaries of parameter hints

Example

>>> docstr = parse_google_args.__doc__
>>> argdict_list = list(parse_google_args(docstr))
>>> print([sorted(d.items()) for d in argdict_list])
[[('desc', 'a google-style docstring'), ('name', 'docstr'), ('type', 'str')]]
xdoctest.docstr.docscrape_google.parse_google_returns(docstr, return_annot=None)[source]

Generates dictionaries of possible return hints based on a google docstring

Parameters:
  • docstr (str) – a google-style docstring

  • return_annot (str | None) – the return type annotation (if one exists)

Yields:

Dict[str, str] – dictionaries of return value hints

Example

>>> docstr = parse_google_returns.__doc__
>>> retdict_list = list(parse_google_returns(docstr))
>>> print([sorted(d.items()) for d in retdict_list])
[[('desc', 'dictionaries of return value hints'), ('type', 'Dict[str, str]')]]

Example

>>> docstr = split_google_docblocks.__doc__
>>> retdict_list = list(parse_google_returns(docstr))
>>> print([sorted(d.items())[1] for d in retdict_list])
[('type', 'List[Tuple[str, DocBlock]]')]
xdoctest.docstr.docscrape_google.parse_google_retblock(lines, return_annot=None)[source]

Parse information out of a returns or yeilds block.

A returns or yeids block should be formatted as one or more '{type}:{description}' strings. The description can occupy multiple lines, but the indentation should increase.

Parameters:
  • lines (str) – unindented lines from a Returns or Yields section

  • return_annot (str | None) – the return type annotation (if one exists)

Yields:

Dict[str, str] – each dict specifies the return type and its description

Example

>>> # Test various ways that retlines can be written
>>> assert len(list(parse_google_retblock('list: a desc'))) == 1
>>> # ---
>>> hints = list(parse_google_retblock('\n'.join([
...     'entire line can be desc',
...     ' ',
...     ' if a return type annotation is given',
... ]), return_annot='int'))
>>> assert len(hints) == 1
>>> # ---
>>> hints = list(parse_google_retblock('\n'.join([
...     'bool: a description',
...     ' with a newline',
... ])))
>>> assert len(hints) == 1
>>> # ---
>>> hints = list(parse_google_retblock('\n'.join([
...     'int or bool: a description',
...     ' ',
...     ' with a separated newline',
...     ' ',
... ])))
>>> assert len(hints) == 1
>>> # ---
>>> hints = list(parse_google_retblock('\n'.join([
...     # Multiple types can be specified
...     'threading.Thread: a description',
...     '(int, str): a tuple of int and str',
...     'tuple: a tuple of int and str',
...     'Tuple[int, str]: a tuple of int and str',
... ])))
>>> assert len(hints) == 4
>>> # ---
>>> # If the colon is not specified nothing will be parsed
>>> # according to the "official" spec, but lets try and do it anyway
>>> hints = list(parse_google_retblock('\n'.join([
...     'list',
...     'Tuple[int, str]',
... ])))
>>> assert len(hints) == 2
>>> assert len(list(parse_google_retblock('no type, just desc'))) == 1
...
xdoctest.docstr.docscrape_google.parse_google_argblock(lines, clean_desc=True)[source]

Parse out individual items from google-style args blocks.

Parameters:
  • lines (str) – the unindented lines from an Args docstring section

  • clean_desc (bool) – if True, will strip the description of newlines and indents. Defaults to True.

Yields:

Dict[str, str | None] – A dictionary containing keys, “name”, “type”, and “desc” corresponding to an argument in the Args block.

Example

>>> # Test various ways that arglines can be written
>>> line_list = [
...     '',
...     'foo1 (int): a description',
...     'foo2: a description\n    with a newline',
...     'foo3 (int or str): a description',
...     'foo4 (int or threading.Thread): a description',
...     #
...     # this is sphynx-like typing style
...     'param1 (:obj:`str`, optional): ',
...     'param2 (:obj:`list` of :obj:`str`):',
...     #
...     # the Type[type] syntax is defined by the python typeing module
...     'attr1 (Optional[int]): Description of `attr1`.',
...     'attr2 (List[str]): Description of `attr2`.',
...     'attr3 (Dict[str, str]): Description of `attr3`.',
...     '*args : variable positional args description',
...     '**kwargs : keyword arguments description',
...     'malformed and unparseable',
...     'param_no_desc1',  # todo: this should be parseable
...     'param_no_desc2:',
...     'param_no_desc3 ()',  # todo: this should be parseable
...     'param_no_desc4 ():',
...     'param_no_desc5 (str)',  # todo: this should be parseable
...     'param_no_desc6 (str):',
... ]
>>> lines = '\n'.join(line_list)
>>> argdict_list = list(parse_google_argblock(lines))
>>> # All lines except the first should be accepted
>>> assert len(argdict_list) == len(line_list) - 5
>>> assert argdict_list[1]['desc'] == 'a description with a newline'