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

Side by Side Diff: third_party/pycoverage/coverage/misc.py

Issue 727003004: Add python coverage module to third_party (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month 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 """Miscellaneous stuff for Coverage."""
2
3 import errno
4 import inspect
5 import os
6 import sys
7
8 from coverage.backward import md5, sorted # pylint: disable=W0622
9 from coverage.backward import string_class, to_bytes
10
11
12 def nice_pair(pair):
13 """Make a nice string representation of a pair of numbers.
14
15 If the numbers are equal, just return the number, otherwise return the pair
16 with a dash between them, indicating the range.
17
18 """
19 start, end = pair
20 if start == end:
21 return "%d" % start
22 else:
23 return "%d-%d" % (start, end)
24
25
26 def format_lines(statements, lines):
27 """Nicely format a list of line numbers.
28
29 Format a list of line numbers for printing by coalescing groups of lines as
30 long as the lines represent consecutive statements. This will coalesce
31 even if there are gaps between statements.
32
33 For example, if `statements` is [1,2,3,4,5,10,11,12,13,14] and
34 `lines` is [1,2,5,10,11,13,14] then the result will be "1-2, 5-11, 13-14".
35
36 """
37 pairs = []
38 i = 0
39 j = 0
40 start = None
41 statements = sorted(statements)
42 lines = sorted(lines)
43 while i < len(statements) and j < len(lines):
44 if statements[i] == lines[j]:
45 if start == None:
46 start = lines[j]
47 end = lines[j]
48 j += 1
49 elif start:
50 pairs.append((start, end))
51 start = None
52 i += 1
53 if start:
54 pairs.append((start, end))
55 ret = ', '.join(map(nice_pair, pairs))
56 return ret
57
58
59 def short_stack():
60 """Return a string summarizing the call stack."""
61 stack = inspect.stack()[:0:-1]
62 return "\n".join(["%30s : %s @%d" % (t[3],t[1],t[2]) for t in stack])
63
64
65 def expensive(fn):
66 """A decorator to cache the result of an expensive operation.
67
68 Only applies to methods with no arguments.
69
70 """
71 attr = "_cache_" + fn.__name__
72 def _wrapped(self):
73 """Inner fn that checks the cache."""
74 if not hasattr(self, attr):
75 setattr(self, attr, fn(self))
76 return getattr(self, attr)
77 return _wrapped
78
79
80 def bool_or_none(b):
81 """Return bool(b), but preserve None."""
82 if b is None:
83 return None
84 else:
85 return bool(b)
86
87
88 def join_regex(regexes):
89 """Combine a list of regexes into one that matches any of them."""
90 if len(regexes) > 1:
91 return "|".join(["(%s)" % r for r in regexes])
92 elif regexes:
93 return regexes[0]
94 else:
95 return ""
96
97
98 def file_be_gone(path):
99 """Remove a file, and don't get annoyed if it doesn't exist."""
100 try:
101 os.remove(path)
102 except OSError:
103 _, e, _ = sys.exc_info()
104 if e.errno != errno.ENOENT:
105 raise
106
107
108 class Hasher(object):
109 """Hashes Python data into md5."""
110 def __init__(self):
111 self.md5 = md5()
112
113 def update(self, v):
114 """Add `v` to the hash, recursively if needed."""
115 self.md5.update(to_bytes(str(type(v))))
116 if isinstance(v, string_class):
117 self.md5.update(to_bytes(v))
118 elif v is None:
119 pass
120 elif isinstance(v, (int, float)):
121 self.md5.update(to_bytes(str(v)))
122 elif isinstance(v, (tuple, list)):
123 for e in v:
124 self.update(e)
125 elif isinstance(v, dict):
126 keys = v.keys()
127 for k in sorted(keys):
128 self.update(k)
129 self.update(v[k])
130 else:
131 for k in dir(v):
132 if k.startswith('__'):
133 continue
134 a = getattr(v, k)
135 if inspect.isroutine(a):
136 continue
137 self.update(k)
138 self.update(a)
139
140 def digest(self):
141 """Retrieve the digest of the hash."""
142 return self.md5.digest()
143
144
145 class CoverageException(Exception):
146 """An exception specific to Coverage."""
147 pass
148
149 class NoSource(CoverageException):
150 """We couldn't find the source for a module."""
151 pass
152
153 class NoCode(NoSource):
154 """We couldn't find any code at all."""
155 pass
156
157 class NotPython(CoverageException):
158 """A source file turned out not to be parsable Python."""
159 pass
160
161 class ExceptionDuringRun(CoverageException):
162 """An exception happened while running customer code.
163
164 Construct it with three arguments, the values from `sys.exc_info`.
165
166 """
167 pass
OLDNEW
« no previous file with comments | « third_party/pycoverage/coverage/htmlfiles/style.css ('k') | third_party/pycoverage/coverage/parser.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698