Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(390)

Side by Side Diff: tools/telemetry/third_party/coverage/lab/parser.py

Issue 1366913004: Add coverage Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
3
4 """Parser.py: a main for invoking code in coverage/parser.py"""
5
6 from __future__ import division
7
8 import glob, os, sys
9 import collections
10 from optparse import OptionParser
11
12 import disgen
13
14 from coverage.misc import CoverageException
15 from coverage.parser import ByteParser, PythonParser
16 from coverage.python import get_python_source
17
18 opcode_counts = collections.Counter()
19
20 class ParserMain(object):
21 """A main for code parsing experiments."""
22
23 def main(self, args):
24 """A main function for trying the code from the command line."""
25
26 parser = OptionParser()
27 parser.add_option(
28 "-c", action="store_true", dest="chunks",
29 help="Show basic block chunks"
30 )
31 parser.add_option(
32 "-d", action="store_true", dest="dis",
33 help="Disassemble"
34 )
35 parser.add_option(
36 "-H", action="store_true", dest="histogram",
37 help="Count occurrences of opcodes"
38 )
39 parser.add_option(
40 "-R", action="store_true", dest="recursive",
41 help="Recurse to find source files"
42 )
43 parser.add_option(
44 "-s", action="store_true", dest="source",
45 help="Show analyzed source"
46 )
47 parser.add_option(
48 "-t", action="store_true", dest="tokens",
49 help="Show tokens"
50 )
51
52 options, args = parser.parse_args()
53 if options.recursive:
54 if args:
55 root = args[0]
56 else:
57 root = "."
58 for root, _, _ in os.walk(root):
59 for f in glob.glob(root + "/*.py"):
60 self.one_file(options, f)
61 elif not args:
62 parser.print_help()
63 else:
64 self.one_file(options, args[0])
65
66 if options.histogram:
67 total = sum(opcode_counts.values())
68 print("{} total opcodes".format(total))
69 for opcode, number in opcode_counts.most_common():
70 print("{:20s} {:6d} {:.1%}".format(opcode, number, number/total ))
71
72
73 def one_file(self, options, filename):
74 """Process just one file."""
75
76 try:
77 text = get_python_source(filename)
78 bp = ByteParser(text, filename=filename)
79 except Exception as err:
80 print("%s" % (err,))
81 return
82
83 if options.dis:
84 print("Main code:")
85 self.disassemble(bp, histogram=options.histogram)
86
87 arcs = bp._all_arcs()
88 if options.chunks:# and not options.dis:
89 chunks = bp._all_chunks()
90 if options.recursive:
91 print("%6d: %s" % (len(chunks), filename))
92 else:
93 print("Chunks: %r" % chunks)
94 print("Arcs: %r" % sorted(arcs))
95
96 if options.source or options.tokens:
97 cp = PythonParser(filename=filename, exclude=r"no\s*cover")
98 cp.show_tokens = options.tokens
99 cp._raw_parse()
100
101 if options.source:
102 if options.chunks:
103 arc_width, arc_chars = self.arc_ascii_art(arcs)
104 else:
105 arc_width, arc_chars = 0, {}
106
107 exit_counts = cp.exit_counts()
108
109 for lineno, ltext in enumerate(cp.lines, start=1):
110 m0 = m1 = m2 = m3 = a = ' '
111 if lineno in cp.statement_starts:
112 m0 = '-'
113 exits = exit_counts.get(lineno, 0)
114 if exits > 1:
115 m1 = str(exits)
116 if lineno in cp.docstrings:
117 m2 = '"'
118 if lineno in cp.classdefs:
119 m2 = 'C'
120 if lineno in cp.excluded:
121 m3 = 'x'
122 a = arc_chars[lineno].ljust(arc_width)
123 print("%4d %s%s%s%s%s %s" %
124 (lineno, m0, m1, m2, m3, a, ltext)
125 )
126
127 def disassemble(self, byte_parser, histogram=False):
128 """Disassemble code, for ad-hoc experimenting."""
129
130 for bp in byte_parser.child_parsers():
131 chunks = bp._split_into_chunks()
132 chunkd = dict((chunk.byte, chunk) for chunk in chunks)
133 if bp.text:
134 srclines = bp.text.splitlines()
135 else:
136 srclines = None
137 print("\n%s: " % bp.code)
138 upto = None
139 for disline in disgen.disgen(bp.code):
140 if histogram:
141 opcode_counts[disline.opcode] += 1
142 continue
143 if disline.first:
144 if srclines:
145 upto = upto or disline.lineno-1
146 while upto <= disline.lineno-1:
147 print("%100s%s" % ("", srclines[upto]))
148 upto += 1
149 elif disline.offset > 0:
150 print("")
151 line = disgen.format_dis_line(disline)
152 chunk = chunkd.get(disline.offset)
153 if chunk:
154 chunkstr = ":: %r" % chunk
155 else:
156 chunkstr = ""
157 print("%-70s%s" % (line, chunkstr))
158
159 print("")
160
161 def arc_ascii_art(self, arcs):
162 """Draw arcs as ascii art.
163
164 Returns a width of characters needed to draw all the arcs, and a
165 dictionary mapping line numbers to ascii strings to draw for that line.
166
167 """
168 arc_chars = collections.defaultdict(str)
169 for lfrom, lto in sorted(arcs):
170 if lfrom < 0:
171 arc_chars[lto] += 'v'
172 elif lto < 0:
173 arc_chars[lfrom] += '^'
174 else:
175 if lfrom == lto - 1:
176 # Don't show obvious arcs.
177 continue
178 if lfrom < lto:
179 l1, l2 = lfrom, lto
180 else:
181 l1, l2 = lto, lfrom
182 w = max(len(arc_chars[l]) for l in range(l1, l2+1))
183 for l in range(l1, l2+1):
184 if l == lfrom:
185 ch = '<'
186 elif l == lto:
187 ch = '>'
188 else:
189 ch = '|'
190 arc_chars[l] = arc_chars[l].ljust(w) + ch
191 arc_width = 0
192
193 if arc_chars:
194 arc_width = max(len(a) for a in arc_chars.values())
195 else:
196 arc_width = 0
197
198 return arc_width, arc_chars
199
200 if __name__ == '__main__':
201 ParserMain().main(sys.argv[1:])
202
OLDNEW
« no previous file with comments | « tools/telemetry/third_party/coverage/lab/new-data.js ('k') | tools/telemetry/third_party/coverage/lab/platform_info.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698