richreports module
Library that supports the construction of human-readable, interactive static analysis reports that consist of decorated concrete syntax representations of programs.
- class location(iterable=(), /)[source]
-
Data structure for representing a location within a report as a tuple of two integers: the line number and the column on that line.
Because this class is derived from the
tuple
type, relational operators can be used to determine whether one location appears before or after another.>>> location((12, 24)) < location((13, 24)) True >>> location((13, 23)) < location((13, 24)) True >>> location((13, 24)) < location((13, 24)) False >>> location((14, 0)) < location((13, 0)) False >>> location((14, 23)) < location((13, 41)) False >>> location((12, 24)) <= location((13, 24)) True >>> location((13, 23)) <= location((13, 24)) True >>> location((13, 24)) <= location((13, 24)) True >>> location((14, 0)) <= location((13, 0)) False >>> location((14, 23)) <= location((13, 41)) False
- class report(string: str, line: int = 1, column: int = 0)[source]
Bases:
object
Data structure that represents the raw concrete syntax string as a two-dimensional array of two-sided stacks. Each stack holds delimiters (left and right) that may appear before or after that character in the rendered version of the report.
>>> r = report( ... 'def f(x, y):\n' + ... ' return x + y' ... )
The individual lines in the supplied string can be retrieved via the
lines
attribute.>>> list(r.lines) ['def f(x, y):', ' return x + y']
Delimiters can be added around a range within the report by specifying the locations corresponding to the endpoints (inclusive) of the range.
>>> r.enrich((2, 11), (2, 15), '(', ')') >>> for line in r.render().split('\n'): ... print(line) def f(x, y): return (x + y)
The optional
enrich_intermediate_lines
parameter can be used to delimit all complete lines that appear between the supplied endpoints.>>> r.enrich((1, 0), (2, 15), '<b>', '</b>', enrich_intermediate_lines=True) >>> for line in r.render().split('\n'): ... print(line) <b>def f(x, y):</b> <b> return (x + y)</b>
By default, the
enrich_intermediate_lines
parameter is set toFalse
.>>> r.enrich((1, 0), (2, 15), '<div>\n', '\n</div>') >>> for line in r.render().split('\n'): ... print(line) <div> <b>def f(x, y):</b> <b> return (x + y)</b> </div>
The optional
skip_whitespace
parameter (which is set toFalse
by default) can be used to ensure that left-hand delimiters skip over whitespace (moving to the right and down) and, likewise, that right-hand delimiters skip over whitespace (moving to the left and up).>>> r = report( ... ' \n' + ... '\n' + ... ' \n' + ... ' def f(x, y):\n' + ... ' return x + y \n' + ... ' \n' + ... ' \n' + ... ' ' ... ) >>> r.enrich((2, 0), (5, 20), '<b>', '</b>', skip_whitespace=True) >>> for line in r.render().split('\n'): ... print(line) <b>def f(x, y): return x + y</b>
If the delimited text consists of whitespace and
skip_whitespace
isTrue
, no delimiters are added.>>> r.enrich((6, 0), (6, 20), '<i>', '</i>', skip_whitespace=True) >>> r.enrich((1, 0), (1, 3), '<i>', '</i>', skip_whitespace=True) >>> r.enrich((2, 0), (3, 3), '<i>', '</i>', skip_whitespace=True) >>> for line in r.render().split('\n'): ... print(line) <b>def f(x, y): return x + y</b>
If
enrich_intermediate_lines
andskip_whitespace
are bothTrue
, then individual lines between the first occurrence of a left-hand delimiter and the last occurrence of a right-hand delimiter are delimited as if each line was being enriched individually withskip_whitespace
set toTrue
.>>> r = report( ... ' \n' + ... '\n' + ... ' def f(x, y):\n' + ... ' \n' + ... '\n' + ... ' \n' + ... ' return x + y \n' + ... '\n' + ... ' \n' + ... ' ' ... ) >>> r.enrich( ... (1, 3), (10, 20), ... '<b>', '</b>', ... enrich_intermediate_lines=True, skip_whitespace=True ... ) >>> for line in r.render().split('\n'): ... print(line) <b>def f(x, y):</b> <b>return x + y</b>
It is possible to specify at what value the line and column numbering schemes begin by supplying the optional
line
andcolumn
arguments to the instance constructor.>>> r = report(' def f(x, y):\n return x + y', line=1, column=0) >>> r.enrich((1, 0), (2, 20), '<b>', '</b>', skip_whitespace=True) >>> list(r.render().split('\n')) [' <b>def f(x, y):', ' return x + y</b>'] >>> r = report(' def f(x, y):\n return x + y', line=0, column=0) >>> r.enrich((0, 0), (1, 20), '<b>', '</b>', skip_whitespace=True) >>> list(r.render().split('\n')) [' <b>def f(x, y):', ' return x + y</b>']
- enrich(start: Union[Tuple[int, int], location], end: Union[Tuple[int, int], location], left: str, right: str, enrich_intermediate_lines=False, skip_whitespace=False)[source]
Add a pair of left and right delimiters around a given range within this report instance.
>>> r = report( ... 'def f(x, y):\n' + ... ' return x + y' ... ) >>> r.enrich((1, 0), (2, 15), '<b>', '</b>', True) >>> for line in r.render().split('\n'): ... print(line) <b>def f(x, y):</b> <b> return x + y</b>