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

Side by Side Diff: sky/tools/webkitpy/thirdparty/coverage/results.py

Issue 946753002: Delete a bunch of dead python code. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 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 """Results of coverage measurement."""
2
3 import os
4
5 from coverage.backward import set, sorted # pylint: disable=W0622
6 from coverage.misc import format_lines, join_regex, NoSource
7 from coverage.parser import CodeParser
8
9
10 class Analysis(object):
11 """The results of analyzing a code unit."""
12
13 def __init__(self, cov, code_unit):
14 self.coverage = cov
15 self.code_unit = code_unit
16
17 self.filename = self.code_unit.filename
18 ext = os.path.splitext(self.filename)[1]
19 source = None
20 if ext == '.py':
21 if not os.path.exists(self.filename):
22 source = self.coverage.file_locator.get_zip_data(self.filename)
23 if not source:
24 raise NoSource("No source for code: %r" % self.filename)
25
26 self.parser = CodeParser(
27 text=source, filename=self.filename,
28 exclude=self.coverage._exclude_regex('exclude')
29 )
30 self.statements, self.excluded = self.parser.parse_source()
31
32 # Identify missing statements.
33 executed = self.coverage.data.executed_lines(self.filename)
34 exec1 = self.parser.first_lines(executed)
35 self.missing = sorted(set(self.statements) - set(exec1))
36
37 if self.coverage.data.has_arcs():
38 self.no_branch = self.parser.lines_matching(
39 join_regex(self.coverage.config.partial_list),
40 join_regex(self.coverage.config.partial_always_list)
41 )
42 n_branches = self.total_branches()
43 mba = self.missing_branch_arcs()
44 n_missing_branches = sum(
45 [len(v) for k,v in mba.items() if k not in self.missing]
46 )
47 else:
48 n_branches = n_missing_branches = 0
49 self.no_branch = set()
50
51 self.numbers = Numbers(
52 n_files=1,
53 n_statements=len(self.statements),
54 n_excluded=len(self.excluded),
55 n_missing=len(self.missing),
56 n_branches=n_branches,
57 n_missing_branches=n_missing_branches,
58 )
59
60 def missing_formatted(self):
61 """The missing line numbers, formatted nicely.
62
63 Returns a string like "1-2, 5-11, 13-14".
64
65 """
66 return format_lines(self.statements, self.missing)
67
68 def has_arcs(self):
69 """Were arcs measured in this result?"""
70 return self.coverage.data.has_arcs()
71
72 def arc_possibilities(self):
73 """Returns a sorted list of the arcs in the code."""
74 arcs = self.parser.arcs()
75 return arcs
76
77 def arcs_executed(self):
78 """Returns a sorted list of the arcs actually executed in the code."""
79 executed = self.coverage.data.executed_arcs(self.filename)
80 m2fl = self.parser.first_line
81 executed = [(m2fl(l1), m2fl(l2)) for (l1,l2) in executed]
82 return sorted(executed)
83
84 def arcs_missing(self):
85 """Returns a sorted list of the arcs in the code not executed."""
86 possible = self.arc_possibilities()
87 executed = self.arcs_executed()
88 missing = [
89 p for p in possible
90 if p not in executed
91 and p[0] not in self.no_branch
92 ]
93 return sorted(missing)
94
95 def arcs_unpredicted(self):
96 """Returns a sorted list of the executed arcs missing from the code."""
97 possible = self.arc_possibilities()
98 executed = self.arcs_executed()
99 # Exclude arcs here which connect a line to itself. They can occur
100 # in executed data in some cases. This is where they can cause
101 # trouble, and here is where it's the least burden to remove them.
102 unpredicted = [
103 e for e in executed
104 if e not in possible
105 and e[0] != e[1]
106 ]
107 return sorted(unpredicted)
108
109 def branch_lines(self):
110 """Returns a list of line numbers that have more than one exit."""
111 exit_counts = self.parser.exit_counts()
112 return [l1 for l1,count in exit_counts.items() if count > 1]
113
114 def total_branches(self):
115 """How many total branches are there?"""
116 exit_counts = self.parser.exit_counts()
117 return sum([count for count in exit_counts.values() if count > 1])
118
119 def missing_branch_arcs(self):
120 """Return arcs that weren't executed from branch lines.
121
122 Returns {l1:[l2a,l2b,...], ...}
123
124 """
125 missing = self.arcs_missing()
126 branch_lines = set(self.branch_lines())
127 mba = {}
128 for l1, l2 in missing:
129 if l1 in branch_lines:
130 if l1 not in mba:
131 mba[l1] = []
132 mba[l1].append(l2)
133 return mba
134
135 def branch_stats(self):
136 """Get stats about branches.
137
138 Returns a dict mapping line numbers to a tuple:
139 (total_exits, taken_exits).
140 """
141
142 exit_counts = self.parser.exit_counts()
143 missing_arcs = self.missing_branch_arcs()
144 stats = {}
145 for lnum in self.branch_lines():
146 exits = exit_counts[lnum]
147 try:
148 missing = len(missing_arcs[lnum])
149 except KeyError:
150 missing = 0
151 stats[lnum] = (exits, exits - missing)
152 return stats
153
154
155 class Numbers(object):
156 """The numerical results of measuring coverage.
157
158 This holds the basic statistics from `Analysis`, and is used to roll
159 up statistics across files.
160
161 """
162 # A global to determine the precision on coverage percentages, the number
163 # of decimal places.
164 _precision = 0
165 _near0 = 1.0 # These will change when _precision is changed.
166 _near100 = 99.0
167
168 def __init__(self, n_files=0, n_statements=0, n_excluded=0, n_missing=0,
169 n_branches=0, n_missing_branches=0
170 ):
171 self.n_files = n_files
172 self.n_statements = n_statements
173 self.n_excluded = n_excluded
174 self.n_missing = n_missing
175 self.n_branches = n_branches
176 self.n_missing_branches = n_missing_branches
177
178 def set_precision(cls, precision):
179 """Set the number of decimal places used to report percentages."""
180 assert 0 <= precision < 10
181 cls._precision = precision
182 cls._near0 = 1.0 / 10**precision
183 cls._near100 = 100.0 - cls._near0
184 set_precision = classmethod(set_precision)
185
186 def _get_n_executed(self):
187 """Returns the number of executed statements."""
188 return self.n_statements - self.n_missing
189 n_executed = property(_get_n_executed)
190
191 def _get_n_executed_branches(self):
192 """Returns the number of executed branches."""
193 return self.n_branches - self.n_missing_branches
194 n_executed_branches = property(_get_n_executed_branches)
195
196 def _get_pc_covered(self):
197 """Returns a single percentage value for coverage."""
198 if self.n_statements > 0:
199 pc_cov = (100.0 * (self.n_executed + self.n_executed_branches) /
200 (self.n_statements + self.n_branches))
201 else:
202 pc_cov = 100.0
203 return pc_cov
204 pc_covered = property(_get_pc_covered)
205
206 def _get_pc_covered_str(self):
207 """Returns the percent covered, as a string, without a percent sign.
208
209 Note that "0" is only returned when the value is truly zero, and "100"
210 is only returned when the value is truly 100. Rounding can never
211 result in either "0" or "100".
212
213 """
214 pc = self.pc_covered
215 if 0 < pc < self._near0:
216 pc = self._near0
217 elif self._near100 < pc < 100:
218 pc = self._near100
219 else:
220 pc = round(pc, self._precision)
221 return "%.*f" % (self._precision, pc)
222 pc_covered_str = property(_get_pc_covered_str)
223
224 def pc_str_width(cls):
225 """How many characters wide can pc_covered_str be?"""
226 width = 3 # "100"
227 if cls._precision > 0:
228 width += 1 + cls._precision
229 return width
230 pc_str_width = classmethod(pc_str_width)
231
232 def __add__(self, other):
233 nums = Numbers()
234 nums.n_files = self.n_files + other.n_files
235 nums.n_statements = self.n_statements + other.n_statements
236 nums.n_excluded = self.n_excluded + other.n_excluded
237 nums.n_missing = self.n_missing + other.n_missing
238 nums.n_branches = self.n_branches + other.n_branches
239 nums.n_missing_branches = (self.n_missing_branches +
240 other.n_missing_branches)
241 return nums
242
243 def __radd__(self, other):
244 # Implementing 0+Numbers allows us to sum() a list of Numbers.
245 if other == 0:
246 return self
247 return NotImplemented
OLDNEW
« no previous file with comments | « sky/tools/webkitpy/thirdparty/coverage/report.py ('k') | sky/tools/webkitpy/thirdparty/coverage/summary.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698