From b17f27672208a07318f8aa62a1bd64b18e9961d1 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Thu, 24 Dec 2015 08:49:50 -0500 Subject: WIP: measure branches with ast instead of bytecode --HG-- branch : ast-branch --- lab/parser.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'lab/parser.py') diff --git a/lab/parser.py b/lab/parser.py index 1a679e8c..9a064257 100644 --- a/lab/parser.py +++ b/lab/parser.py @@ -82,7 +82,7 @@ class ParserMain(object): if options.dis: print("Main code:") - self.disassemble(bp, histogram=options.histogram) + self.disassemble(bp, chunks=options.chunks, histogram=options.histogram) arcs = bp._all_arcs() if options.chunks: @@ -123,15 +123,20 @@ class ParserMain(object): m2 = 'C' if lineno in cp.raw_excluded: m3 = 'x' - a = arc_chars[lineno].ljust(arc_width) + + if arc_chars: + a = arc_chars[lineno].ljust(arc_width) + else: + a = "" + print("%4d %s%s%s%s%s %s" % (lineno, m0, m1, m2, m3, a, ltext)) - def disassemble(self, byte_parser, histogram=False): + def disassemble(self, byte_parser, chunks=False, histogram=False): """Disassemble code, for ad-hoc experimenting.""" for bp in byte_parser.child_parsers(): - chunks = bp._split_into_chunks() - chunkd = dict((chunk.byte, chunk) for chunk in chunks) + if chunks: + chunkd = dict((chunk.byte, chunk) for chunk in bp._split_into_chunks()) if bp.text: srclines = bp.text.splitlines() else: @@ -151,11 +156,11 @@ class ParserMain(object): elif disline.offset > 0: print("") line = disgen.format_dis_line(disline) - chunk = chunkd.get(disline.offset) - if chunk: - chunkstr = ":: %r" % chunk - else: - chunkstr = "" + chunkstr = "" + if chunks: + chunk = chunkd.get(disline.offset) + if chunk: + chunkstr = ":: %r" % chunk print("%-70s%s" % (line, chunkstr)) print("") -- cgit v1.2.1 From eda903304b8ea1fd72d2a33fe794df45c7d92127 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Mon, 4 Jan 2016 19:40:12 -0500 Subject: lab/parser.py shows arcs more usefully One-plus lines (that just go to the next line) now show + Raw statements (-) and official statements (=) don't collide. --HG-- branch : ast-branch --- lab/parser.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'lab/parser.py') diff --git a/lab/parser.py b/lab/parser.py index 9a064257..717fbbf9 100644 --- a/lab/parser.py +++ b/lab/parser.py @@ -72,7 +72,6 @@ class ParserMain(object): def one_file(self, options, filename): """Process just one file.""" - try: text = get_python_source(filename) bp = ByteParser(text, filename=filename) @@ -109,27 +108,30 @@ class ParserMain(object): exit_counts = cp.exit_counts() for lineno, ltext in enumerate(cp.lines, start=1): - m0 = m1 = m2 = m3 = a = ' ' + marks = [' ', ' ', ' ', ' ', ' '] + a = ' ' + if lineno in cp.raw_statements: + marks[0] = '-' if lineno in cp.statements: - m0 = '=' - elif lineno in cp.raw_statements: - m0 = '-' + marks[1] = '=' exits = exit_counts.get(lineno, 0) if exits > 1: - m1 = str(exits) + marks[2] = str(exits) if lineno in cp.raw_docstrings: - m2 = '"' + marks[3] = '"' if lineno in cp.raw_classdefs: - m2 = 'C' + marks[3] = 'C' + if lineno in cp.raw_funcdefs: + marks[3] = 'f' if lineno in cp.raw_excluded: - m3 = 'x' + marks[4] = 'x' if arc_chars: a = arc_chars[lineno].ljust(arc_width) else: a = "" - print("%4d %s%s%s%s%s %s" % (lineno, m0, m1, m2, m3, a, ltext)) + print("%4d %s%s %s" % (lineno, "".join(marks), a, ltext)) def disassemble(self, byte_parser, chunks=False, histogram=False): """Disassemble code, for ad-hoc experimenting.""" @@ -173,6 +175,7 @@ class ParserMain(object): """ + plus_ones = set() arc_chars = collections.defaultdict(str) for lfrom, lto in sorted(arcs): if lfrom < 0: @@ -181,13 +184,12 @@ class ParserMain(object): arc_chars[lfrom] += '^' else: if lfrom == lto - 1: - # Don't show obvious arcs. + plus_ones.add(lfrom) continue if lfrom < lto: l1, l2 = lfrom, lto else: l1, l2 = lto, lfrom - #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: @@ -198,6 +200,13 @@ class ParserMain(object): ch = '|' arc_chars[l] = set_char(arc_chars[l], w, ch) + # Add the plusses as the first character + for lineno, arcs in arc_chars.items(): + arc_chars[lineno] = ( + ("+" if lineno in plus_ones else " ") + + arcs + ) + return arc_chars -- cgit v1.2.1 From fcc18ffcb11bca315c6c0690414e817d5c22b4dd Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Thu, 7 Jan 2016 19:42:09 -0500 Subject: Make lab/parser.py usable on snippets within larger Python files. --HG-- branch : ast-branch --- lab/parser.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'lab/parser.py') diff --git a/lab/parser.py b/lab/parser.py index 717fbbf9..08b50921 100644 --- a/lab/parser.py +++ b/lab/parser.py @@ -5,9 +5,13 @@ from __future__ import division -import glob, os, sys import collections -from optparse import OptionParser +import glob +import optparse +import os +import re +import sys +import textwrap import disgen @@ -24,7 +28,7 @@ class ParserMain(object): def main(self, args): """A main function for trying the code from the command line.""" - parser = OptionParser() + parser = optparse.OptionParser() parser.add_option( "-c", action="store_true", dest="chunks", help="Show basic block chunks" @@ -72,8 +76,20 @@ class ParserMain(object): def one_file(self, options, filename): """Process just one file.""" + # `filename` can have a line number suffix. In that case, extract those + # lines, dedent them, and use that. + match = re.search(r"^(.*):(\d+)-(\d+)$", filename) + if match: + filename, start, end = match.groups() + start, end = int(start), int(end) + else: + start = end = None + try: text = get_python_source(filename) + if start is not None: + lines = text.splitlines(True) + text = textwrap.dedent("".join(lines[start-1:end])) bp = ByteParser(text, filename=filename) except Exception as err: print("%s" % (err,)) -- cgit v1.2.1 From d93ddb9524a3e3535541812bbeade8e8ff822409 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Thu, 7 Jan 2016 19:46:57 -0500 Subject: When extracting snippets, also need to undo backslashing --HG-- branch : ast-branch --- lab/parser.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lab/parser.py') diff --git a/lab/parser.py b/lab/parser.py index 08b50921..5e5b4b36 100644 --- a/lab/parser.py +++ b/lab/parser.py @@ -77,7 +77,8 @@ class ParserMain(object): def one_file(self, options, filename): """Process just one file.""" # `filename` can have a line number suffix. In that case, extract those - # lines, dedent them, and use that. + # lines, dedent them, and use that. This is for trying test cases + # embedded in the test files. match = re.search(r"^(.*):(\d+)-(\d+)$", filename) if match: filename, start, end = match.groups() @@ -89,7 +90,7 @@ class ParserMain(object): text = get_python_source(filename) if start is not None: lines = text.splitlines(True) - text = textwrap.dedent("".join(lines[start-1:end])) + text = textwrap.dedent("".join(lines[start-1:end]).replace("\\\\", "\\")) bp = ByteParser(text, filename=filename) except Exception as err: print("%s" % (err,)) -- cgit v1.2.1