i2.doc_mint

Meta-interfaces

Functions

assert_wants(example, *args, **kwargs)

Render a doctest.Example as an assert comparing its source to its want.

convert_string(s, converters)

Convert s with the first converter that matches (a dict containing s as a key, or a callable returning something other than None); return s if none does.

docstring_to_params(docstring, *[, ...])

Parse a docstring and extract parameter specifications.

doctest_string(obj[, example_callback, recurse])

Extract the doctests found in given object.

doctest_string_print(obj[, ...])

Extract the doctests found in given object.

doctest_string_trans_lines(doctest_obj[, ...])

Yield example_callback(example) for each example of a doctest.DocTest.

find_in_params(query, params, *[, search_in])

Find parameters in a list of parameter specifications.

indent_lines(string, indent)

Indent each line of a string.

inject_docstring_content(to_inject, *[, ...])

Inject content into the docstring of a function.

literal_eval_converter(s[, max_length])

Evaluate s as a Python literal, or return None when it is not one (or is longer than max_length, or contains a newline or ;).

mk_example_wants_callback(source_want_func)

Make a doctest.Example callback from a (source, want) -> str function.

most_common_indent(string[, ignore_first_line])

Find the most common indentation in a string.

non_doctest_lines(doc)

Generator of lines of the doc string that are not in a doctest scope.

old_doctest_string(obj[, output_prefix, ...])

Extract the doctests found in given object.

output_prefix(example, *args, **kwargs)

Render a doctest.Example as its source followed by a # OUTPUT: line.

params_to_docstring(params, *[, doc_style, ...])

Generate a docstring from a list of parameter specifications.

register_converter(converter)

Register a new converter.

split_line_comments(s)

Split a single line into its code and its # comment (empty if none).

split_text_and_doctests(doc_string)

Generates alternating blocks of "text" (string) and "doctest blocks" (DoctestBlock instances, which are essentially a list of ExampleX instances).

string_param_to_obj(string_to_object_mapping)

Convert a string representation of a parameter to an object.

strip_comments(code)

Remove whole-line # comments from code (inline comments are kept).

Classes

DoctestBlock([seq])

A list that (should) contain doctest Example instances

ExampleX(source[, want, exc_msg, lineno, ...])

doctest.Example eXtended to have more convenient methods

class i2.doc_mint.DoctestBlock(seq=())[source]

Bases: list

A list that (should) contain doctest Example instances

class i2.doc_mint.ExampleX(source, want=None, exc_msg=None, lineno=0, indent=0, options=None)[source]

Bases: Example

doctest.Example eXtended to have more convenient methods

i2.doc_mint.assert_wants(example, *args, **kwargs)

Render a doctest.Example as an assert comparing its source to its want.

>>> import doctest
>>> assert_wants(doctest.Example(source='1 + 1\n', want='2\n'))
'assert (1 + 1) == 2 #'
i2.doc_mint.convert_string(s, converters)[source]

Convert s with the first converter that matches (a dict containing s as a key, or a callable returning something other than None); return s if none does.

Return type:

object

>>> convert_string("None", dflt_str_to_obj_converters), convert_string("3.5", dflt_str_to_obj_converters)
(None, 3.5)
>>> convert_string("hello", dflt_str_to_obj_converters)
'hello'
i2.doc_mint.docstring_to_params(docstring, *, doc_style='numpy', converters=[{'-inf': -inf, 'False': False, 'None': None, 'True': True, 'bool': <class 'bool'>, 'complex': <class 'complex'>, 'dict': <class 'dict'>, 'float': <class 'float'>, 'inf': inf, 'int': <class 'int'>, 'list': <class 'list'>, 'nan': nan, 'set': <class 'set'>, 'str': <class 'str'>, 'tuple': <class 'tuple'>}, <function literal_eval_converter>])[source]

Parse a docstring and extract parameter specifications.

Parameters:
  • docstring (str) – The docstring to parse.

  • doc_style (Literal['numpy', 'google', 'rest']) – The style of the docstring to parse. One of ‘numpy’, ‘google’, or ‘rest’.

Return type:

list[dict]

Returns:

A list of parameter specifications, where each specification is a dictionary containing:

  • name: The name of the parameter (str).

  • default: The default value of the parameter (str, optional).

  • annotation: The type annotation for the parameter (str, optional).

  • description: A description of the parameter (str).

Examples

>>> docstring = '''
... Parameters
... ----------
... x : int, default=1
...     An integer value.
... y : str, default=None
...     An optional string.
... '''
>>> params = docstring_to_params(docstring)
>>> params  == [
...     {'name': 'x', 'default': 1, 'annotation': int, 'description': 'An integer value.'},
...     {'name': 'y', 'default': None, 'annotation': str, 'description': 'An optional string.'}
... ]
True
>>> docstring = '''
... Args:
...     x (int, optional): An integer value. Defaults to 1.
...     y (str, optional): An optional string. Defaults to None.
... '''
>>> params = docstring_to_params(docstring, doc_style='google')
>>> params == [
...     {"name": "x", "default": 1, "annotation": int, "description": "An integer value."},
...     {"name": "y", "default": None, "annotation": str, "description": "An optional string."},
... ]
True
>>> docstring = '''
... :param x: An integer value. (Default: 1)
... :type x: int
... :param y: An optional string. (Default: None)
... :type y: str
... '''
>>> params = docstring_to_params(docstring, doc_style='rest')
>>> params == [
...     {"name": "x", "default": 1, "annotation": int, "description": "An integer value."},
...     {"name": "y", "default": None, "annotation": str, "description": "An optional string."},
... ]
True
i2.doc_mint.doctest_string(obj, example_callback=<function mk_example_wants_callback.<locals>.example_wants_callback>, recurse=True)[source]

Extract the doctests found in given object.

Parameters:
  • obj – Object (module, class, function, etc.) you want to extract doctests from.

  • recurse – Whether the process should find doctests in the attributes of the object, recursively.

Params output_prefix:

Returns:

A string containing the doctests, with output lines prefixed by ‘# Output:’

i2.doc_mint.doctest_string_print(obj, example_callback=<function mk_example_wants_callback.<locals>.example_wants_callback>, recurse=True)[source]

Extract the doctests found in given object.

Parameters:
  • obj – Object (module, class, function, etc.) you want to extract doctests from.

  • recurse – Whether the process should find doctests in the attributes of the object, recursively.

Returns:

A string containing the doctests, with output lines prefixed by ‘# Output:’

i2.doc_mint.doctest_string_trans_lines(doctest_obj, example_callback=<function mk_example_wants_callback.<locals>.example_wants_callback>)[source]

Yield example_callback(example) for each example of a doctest.DocTest.

i2.doc_mint.find_in_params(query, params, *, search_in=('name', 'description'))[source]

Find parameters in a list of parameter specifications.

Parameters:
  • query (str) – The query to search for.

  • params (Callable | str) –

    The list of parameter specifications. Params can be provided in two formats:

    • A function, from which the params will be extracted from the docstring.

    • A list of dictionaries where each dictionary specifies a parameter, containing:

      • name: The name of the parameter (str).

      • default: The default value of the parameter (any, optional).

      • annotation: The type annotation for the parameter (str, optional).

      • description: A description of the parameter (str).

    If a callable is provided, it will be used to generate the list of parameter specifications.

  • search_in – The fields to search in each parameter specification.

Return type:

list[dict]

Returns:

A list of parameter specifications that match the query.

Examples

>>> params = [
...     {"name": "x", "default": 1, "annotation": "int", "description": "An integer value."},
...     {"name": "y", "default": None, "annotation": "str", "description": "An optional string."},
... ]
>>> find_in_params('int', params)
[{'name': 'x', 'default': 1, 'annotation': 'int', 'description': 'An integer value.'}]
i2.doc_mint.indent_lines(string, indent)[source]

Indent each line of a string.

Parameters:
  • string (str) – The string to indent.

  • indent (str) – The string to use for indentation.

Return type:

str

Returns:

The indented string.

Examples

>>> print(indent_lines('This is a test.\nAnother line.', ' ' * 8))
        This is a test.
        Another line.
i2.doc_mint.inject_docstring_content(to_inject, *, position=-1, indent=True)[source]

Inject content into the docstring of a function.

Note

If you use the decorator on a string, it will assume that string is the doc string you want to transform and return the modified string directly.

Parameters:
  • to_inject – The content to inject.

  • position – The position in the docstring to inject the content. If an integer, the content is injected at that line number (pushing the rest down). If a string, will consider it as a regex pattern to match the line to inject after. Default is -1, to inject at the end.

  • indent – Control on indent. If True, will use the most common indent of the input docstrings. If a string, it will use that specific string.

Returns:

A decorator that injects the content into the docstring of the decorated function.

Examples

>>> @inject_docstring_content('This is a test.')
... def test_func():
...     '''This is the docstring.'''
...     pass
>>> test_func.__doc__
'This is the docstring.\nThis is a test.'
>>> @inject_docstring_content('This is a test.', position='###INSERT HERE###')
... def test_func():
...     '''This is the docstring.
...     ###INSERT HERE###
...     More blah.
...     '''
...     pass
>>> test_func.__doc__
'This is the docstring.\n    ###INSERT HERE###\n    More blah.\n    '
i2.doc_mint.literal_eval_converter(s, max_length=1000)[source]

Evaluate s as a Python literal, or return None when it is not one (or is longer than max_length, or contains a newline or ;).

>>> literal_eval_converter("[1, 2]"), literal_eval_converter("foo")
([1, 2], None)
i2.doc_mint.mk_example_wants_callback(source_want_func)[source]

Make a doctest.Example callback from a (source, want) -> str function.

The callback returns the example’s source untouched when the example expects no output.

i2.doc_mint.most_common_indent(string, ignore_first_line=True)[source]

Find the most common indentation in a string.

Parameters:
  • string (str) – The string to analyze.

  • ignore_first_line – Whether to ignore the first line when determining the indentation. Default is True since the first line often has no indentation because of the way python strings appear in code.

Return type:

str

Returns:

The most common indentation string.

Examples

>>> most_common_indent('    This is a test.\n    Another line.')
'    '
i2.doc_mint.non_doctest_lines(doc)[source]

Generator of lines of the doc string that are not in a doctest scope.

>>> def _test_func():
...     '''Line 1
...     Another
...     >>> doctest_1
...     >>> doctest_2
...     line_after_a_doc_test
...     another_line_that_is_in_the_doc_test scope
...
...     But now we're out of a doctest's scope
...
...     >>> Oh no, another doctest!
...     '''
>>> from inspect import getdoc
>>>
>>> list(non_doctest_lines(getdoc(_test_func)))
['Line 1', 'Another', "But now we're out of a doctest's scope", '']
Parameters:

doc

Returns:

i2.doc_mint.old_doctest_string(obj, output_prefix='# OUTPUT: ', include_attr_without_doctests=False, recurse=True)[source]

Extract the doctests found in given object.

Parameters:
  • obj – Object (module, class, function, etc.) you want to extract doctests from.

  • output_prefix

  • recurse – Whether the process should find doctests in the attributes of the object, recursively.

Returns:

A string containing the doctests, with output lines prefixed by ‘# Output:’

i2.doc_mint.output_prefix(example, *args, **kwargs)

Render a doctest.Example as its source followed by a # OUTPUT: line.

>>> import doctest
>>> output_prefix(doctest.Example(source='1 + 1\n', want='2\n'))
'1 + 1\n# OUTPUT: 2\n'
i2.doc_mint.params_to_docstring(params, *, doc_style='numpy', take_name_of_types=False, quote_string_defaults=True)[source]

Generate a docstring from a list of parameter specifications.

Parameters:
  • params (list[dict]) –

    A list of dictionaries where each dictionary specifies a parameter. Each dictionary should contain:

    • name: The name of the parameter (str).

    • default: The default value of the parameter (any, optional).

    • annotation: The type annotation for the parameter (str, optional).

    • description: A description of the parameter (str).

  • doc_style (str) – The style of the docstring to generate. One of ‘numpy’, ‘google’, or ‘rest’.

  • take_name_of_types (bool) – Whether to use the name of the type as the annotation (bool).

  • quote_string_defaults (bool) – Whether to quote string defaults (bool).

Return type:

str

Returns:

A formatted docstring (str).

Examples

>>> params = [
...     {"name": "x", "default": 1, "annotation": "int", "description": "An integer value."},
...     {"name": "y", "default": None, "annotation": "str", "description": "An optional string."},
... ]
>>> print(params_to_docstring(params))
:param x: An integer value.
:type x: int, default=1
:param y: An optional string.
:type y: str, default=None
:param <BLANKLINE>:
:param >>> print(params_to_docstring(params:
:type >>> print(params_to_docstring(params: +NORMALIZE_WHITESPACE
:param doc_style='google'))  # doctest:
:type doc_style='google'))
:param Args: x (int, optional): An integer value. Defaults to 1.
             y (str, optional): An optional string. Defaults to None.
:param <BLANKLINE>:
:param >>> print(params_to_docstring(params:
:type >>> print(params_to_docstring(params: +NORMALIZE_WHITESPACE
:param doc_style='rest'))  # doctest:
:type doc_style='rest'))
:param :
:type : param x: An integer value. (Default: 1)
:param :
:type : type x: int
:param :
:type : param y: An optional string. (Default: None)
:param :
:type : type y: str
:param <BLANKLINE>:
i2.doc_mint.register_converter(converter)[source]

Register a new converter. A converter can be:

  • A dict: { “None”: None, “int”: int, … }

  • A callable: lambda s: attempt to parse s and return object or None

i2.doc_mint.split_line_comments(s)[source]

Split a single line into its code and its # comment (empty if none).

>>> split_line_comments("f(1)  # a comment")
('f(1)  ', ' a comment')
i2.doc_mint.split_text_and_doctests(doc_string)[source]

Generates alternating blocks of “text” (string) and “doctest blocks” (DoctestBlock instances, which are essentially a list of ExampleX instances).

>>> example = '''
...     This is to test the doctest splitter.
...     Until now, we're in a text block.
...     The following is a doctest block:
...
...     >>> 2 + 3
...     5
...     >>> t = 5
...     >>> tt = 10
...
...     This is another text block, followed with another doctest block:
...
...     >>> def foo():
...     ...     return 42
...     >>> foo()
...     42
...
... '''
>>>
>>> blocks = list(split_text_and_doctests(example))

There are 5 blocks:

>>> len(blocks)
5

The first block is a string, corresponding to explanatory text of the doc string:

>>> isinstance(blocks[0], str)
True
>>> print(blocks[0])

This is to test the doctest splitter.
Until now, we're in a text block.
The following is a doctest block:

The next block is a DoctestBlock instance.

>>> block = blocks[1]
>>> isinstance(block, DoctestBlock)
True

This block has 3 elements (ExampleX instances)

>>> len(block)
3

If you ask for the string representation of this block, you’ll get a doctest string:

>>> str(block)
'    >>> 2 + 3\n    5\n    >>> t = 5\n    >>> tt = 10\n'
i2.doc_mint.string_param_to_obj(string_to_object_mapping, string=None)[source]

Convert a string representation of a parameter to an object.

Use Case: When parsing a docstring, you get values as strings, but these values may need to be converted to their actual object types (in the case of default and annotatios for example). This is a helper function to do that conversion.

Parameters:
  • string – The string representation of the parameter.

  • string_to_object_mapping (dict) – A mapping from string representations to objects.

Returns:

The object corresponding to the string representation.

Examples

>>> string_to_object_mapping = {
...     'None': None,
...     'list': list,
...     'int': int,
... }
>>> string_to_obj = string_param_to_obj(string_to_object_mapping)
>>> string_to_obj('None')
>>> string_to_obj('list')
<class 'list'>
>>> string_to_obj('int')
<class 'int'>
>>> string_to_obj('not something listed')
'not something listed'
i2.doc_mint.strip_comments(code)[source]

Remove whole-line # comments from code (inline comments are kept).

>>> strip_comments("# header\nx = 1  # set x\n")
'x = 1  # set x\n'