mkinit.static_analysis module¶
A paired down version of static_anslysis from xdoctest
- mkinit.static_analysis._parse_static_node_value(node)[source]¶
Extract a constant value from a node if possible
- mkinit.static_analysis.parse_static_value(key, source=None, fpath=None)[source]¶
Statically parse a constant variable’s value from python code.
TODO: This does not belong here. Move this to an external static analysis library.
- Parameters:
key (str) – name of the variable
source (str | None) – python text
fpath (str | None) – filepath to read if source is not specified
Example
>>> key = 'foo' >>> source = 'foo = 123' >>> assert parse_static_value(key, source=source) == 123 >>> source = 'foo = "123"' >>> assert parse_static_value(key, source=source) == '123' >>> source = 'foo = [1, 2, 3]' >>> assert parse_static_value(key, source=source) == [1, 2, 3] >>> source = 'foo = (1, 2, "3")' >>> assert parse_static_value(key, source=source) == (1, 2, "3") >>> source = 'foo = {1: 2, 3: 4}' >>> assert parse_static_value(key, source=source) == {1: 2, 3: 4} >>> #parse_static_value('bar', source=source) >>> #parse_static_value('bar', source='foo=1; bar = [1, foo]')
- mkinit.static_analysis.package_modpaths(pkgpath, with_pkg=False, with_mod=True, followlinks=True, recursive=True, with_libs=False, check=True)[source]¶
Finds sub-packages and sub-modules belonging to a package.
- Parameters:
pkgpath (str) – path to a module or package
with_pkg (bool) – if True includes package __init__ files (default = False)
with_mod (bool) – if True includes module files (default = True)
exclude (list) – ignores any module that matches any of these patterns
recursive (bool) – if False, then only child modules are included
with_libs (bool) – if True then compiled shared libs will be returned as well
check (bool) – if False, then then pkgpath is considered a module even if it does not contain an __init__ file.
- Yields:
str – module names belonging to the package
References
http://stackoverflow.com/questions/1707709/list-modules-in-py-package
Example
>>> from mkinit.static_analysis import * >>> pkgpath = util_import.modname_to_modpath('mkinit') >>> paths = list(package_modpaths(pkgpath)) >>> print('\n'.join(paths)) >>> names = list(map(util_import.modpath_to_modname, paths)) >>> assert 'mkinit.static_mkinit' in names >>> assert 'mkinit.__main__' in names >>> assert 'mkinit' not in names >>> print('\n'.join(names))
- mkinit.static_analysis.is_balanced_statement(lines)[source]¶
Checks if the lines have balanced parens, brakets, curlies and strings
- Parameters:
lines (list) – list of strings
- Returns:
False if the statement is not balanced
- Return type:
Doctest
>>> assert is_balanced_statement(['print(foobar)']) >>> assert is_balanced_statement(['foo = bar']) is True >>> assert is_balanced_statement(['foo = (']) is False >>> assert is_balanced_statement(['foo = (', "')(')"]) is True >>> assert is_balanced_statement( ... ['foo = (', "'''", ")]'''", ')']) is True >>> #assert is_balanced_statement(['foo = ']) is False >>> #assert is_balanced_statement(['== ']) is False
- mkinit.static_analysis._locate_ps1_linenos(source_lines)[source]¶
Determines which lines in the source begin a “logical block” of code.
Note
implementation taken from xdoctest.parser
- Parameters:
source_lines (list) – lines belonging only to the doctest src these will be unindented, prefixed, and without any want.
- Returns:
- a list of indices indicating which lines
are considered “PS1” and a flag indicating if the final line should be considered for a got/want assertion.
- Return type:
Example
>>> source_lines = ['>>> def foo():', '>>> return 0', '>>> 3'] >>> linenos, eval_final = _locate_ps1_linenos(source_lines) >>> assert linenos == [0, 2] >>> assert eval_final is True
Example
>>> source_lines = ['>>> x = [1, 2, ', '>>> 3, 4]', '>>> print(len(x))'] >>> linenos, eval_final = _locate_ps1_linenos(source_lines) >>> assert linenos == [0, 2] >>> assert eval_final is True
- mkinit.static_analysis._workaround_16806(ps1_linenos, exec_source_lines)[source]¶
workaround for python issue 16806 (https://bugs.python.org/issue16806)
Issue causes lineno for multiline strings to give the line they end on, not the line they start on. A patch for this issue exists https://github.com/python/cpython/pull/1800
Note
Starting from the end look at consecutive pairs of indices to inspect the statment it corresponds to. (the first statment goes from ps1_linenos[-1] to the end of the line list.
Implementation taken from xdoctest.parser