diff options
Diffstat (limited to 'lab/parser.py')
-rw-r--r-- | lab/parser.py | 76 |
1 files changed, 50 insertions, 26 deletions
diff --git a/lab/parser.py b/lab/parser.py index 662183a7..1a679e8c 100644 --- a/lab/parser.py +++ b/lab/parser.py @@ -1,3 +1,6 @@ +# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 +# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt + """Parser.py: a main for invoking code in coverage/parser.py""" from __future__ import division @@ -14,6 +17,7 @@ from coverage.python import get_python_source opcode_counts = collections.Counter() + class ParserMain(object): """A main for code parsing experiments.""" @@ -62,10 +66,9 @@ class ParserMain(object): if options.histogram: total = sum(opcode_counts.values()) - print("{} total opcodes".format(total)) + print("{0} total opcodes".format(total)) for opcode, number in opcode_counts.most_common(): - print("{:20s} {:6d} {:.1%}".format(opcode, number, number/total)) - + print("{0:20s} {1:6d} {2:.1%}".format(opcode, number, number/total)) def one_file(self, options, filename): """Process just one file.""" @@ -82,7 +85,7 @@ class ParserMain(object): self.disassemble(bp, histogram=options.histogram) arcs = bp._all_arcs() - if options.chunks:# and not options.dis: + if options.chunks: chunks = bp._all_chunks() if options.recursive: print("%6d: %s" % (len(chunks), filename)) @@ -93,33 +96,35 @@ class ParserMain(object): if options.source or options.tokens: cp = PythonParser(filename=filename, exclude=r"no\s*cover") cp.show_tokens = options.tokens - cp._raw_parse() + cp.parse_source() if options.source: + arc_width = 0 + arc_chars = {} if options.chunks: - arc_width, arc_chars = self.arc_ascii_art(arcs) - else: - arc_width, arc_chars = 0, {} + arc_chars = self.arc_ascii_art(arcs) + if arc_chars: + arc_width = max(len(a) for a in arc_chars.values()) exit_counts = cp.exit_counts() for lineno, ltext in enumerate(cp.lines, start=1): m0 = m1 = m2 = m3 = a = ' ' - if lineno in cp.statement_starts: + if lineno in cp.statements: + m0 = '=' + elif lineno in cp.raw_statements: m0 = '-' exits = exit_counts.get(lineno, 0) if exits > 1: m1 = str(exits) - if lineno in cp.docstrings: + if lineno in cp.raw_docstrings: m2 = '"' - if lineno in cp.classdefs: + if lineno in cp.raw_classdefs: m2 = 'C' - if lineno in cp.excluded: + if lineno in cp.raw_excluded: m3 = 'x' a = arc_chars[lineno].ljust(arc_width) - print("%4d %s%s%s%s%s %s" % - (lineno, m0, m1, m2, m3, a, ltext) - ) + print("%4d %s%s%s%s%s %s" % (lineno, m0, m1, m2, m3, a, ltext)) def disassemble(self, byte_parser, histogram=False): """Disassemble code, for ad-hoc experimenting.""" @@ -158,10 +163,11 @@ class ParserMain(object): def arc_ascii_art(self, arcs): """Draw arcs as ascii art. - Returns a width of characters needed to draw all the arcs, and a - dictionary mapping line numbers to ascii strings to draw for that line. + Returns a dictionary mapping line numbers to ascii strings to draw for + that line. """ + arc_chars = collections.defaultdict(str) for lfrom, lto in sorted(arcs): if lfrom < 0: @@ -176,7 +182,8 @@ class ParserMain(object): l1, l2 = lfrom, lto else: l1, l2 = lto, lfrom - w = max(len(arc_chars[l]) for l in range(l1, l2+1)) + #w = max(len(arc_chars[l]) for l in range(l1, l2+1)) + w = first_all_blanks(arc_chars[l] for l in range(l1, l2+1)) for l in range(l1, l2+1): if l == lfrom: ch = '<' @@ -184,16 +191,33 @@ class ParserMain(object): ch = '>' else: ch = '|' - arc_chars[l] = arc_chars[l].ljust(w) + ch - arc_width = 0 + arc_chars[l] = set_char(arc_chars[l], w, ch) - if arc_chars: - arc_width = max(len(a) for a in arc_chars.values()) - else: - arc_width = 0 + return arc_chars + + +def set_char(s, n, c): + """Set the nth char of s to be c, extending s if needed.""" + s = s.ljust(n) + return s[:n] + c + s[n+1:] + + +def blanks(s): + """Return the set of positions where s is blank.""" + return set(i for i, c in enumerate(s) if c == " ") + + +def first_all_blanks(ss): + """Find the first position that is all blank in the strings ss.""" + ss = list(ss) + blankss = blanks(ss[0]) + for s in ss[1:]: + blankss &= blanks(s) + if blankss: + return min(blankss) + else: + return max(len(s) for s in ss) - return arc_width, arc_chars if __name__ == '__main__': ParserMain().main(sys.argv[1:]) - |