diff options
Diffstat (limited to 'coverage/collector.py')
-rw-r--r-- | coverage/collector.py | 95 |
1 files changed, 70 insertions, 25 deletions
diff --git a/coverage/collector.py b/coverage/collector.py index 94af5df5..546525d2 100644 --- a/coverage/collector.py +++ b/coverage/collector.py @@ -41,17 +41,22 @@ class PyTracer(object): # used to force the use of this tracer. def __init__(self): + # Attributes set from the collector: self.data = None + self.arcs = False self.should_trace = None self.should_trace_cache = None self.warn = None + self.extensions = None + + self.extension = None + self.cur_tracename = None # TODO: This is only maintained for the if0 debugging output. Get rid of it eventually. self.cur_file_data = None self.last_line = 0 self.data_stack = [] self.data_stacks = collections.defaultdict(list) self.last_exc_back = None self.last_exc_firstlineno = 0 - self.arcs = False self.thread = None self.stopped = False self.coroutine_id_func = None @@ -64,9 +69,31 @@ class PyTracer(object): return if 0: - sys.stderr.write("trace event: %s %r @%d\n" % ( - event, frame.f_code.co_filename, frame.f_lineno + # A lot of debugging to try to understand why gevent isn't right. + import os.path, pprint + def short_ident(ident): + return "{}:{:06X}".format(ident.__class__.__name__, id(ident) & 0xFFFFFF) + + ident = None + if self.coroutine_id_func: + ident = short_ident(self.coroutine_id_func()) + sys.stdout.write("trace event: %s %s %r @%d\n" % ( + event, ident, frame.f_code.co_filename, frame.f_lineno )) + pprint.pprint( + dict( + ( + short_ident(ident), + [ + (os.path.basename(tn or ""), sorted((cfd or {}).keys()), ll) + for ex, tn, cfd, ll in data_stacks + ] + ) + for ident, data_stacks in self.data_stacks.items() + ) + , width=250) + pprint.pprint(sorted((self.cur_file_data or {}).keys()), width=250) + print("TRYING: {}".format(sorted(next((v for k,v in self.data.items() if k.endswith("try_it.py")), {}).keys()))) if self.last_exc_back: if frame == self.last_exc_back: @@ -76,7 +103,7 @@ class PyTracer(object): self.cur_file_data[pair] = None if self.coroutine_id_func: self.data_stack = self.data_stacks[self.coroutine_id_func()] - self.cur_file_data, self.last_line = self.data_stack.pop() + self.handler, _, self.cur_file_data, self.last_line = self.data_stack.pop() self.last_exc_back = None if event == 'call': @@ -85,19 +112,25 @@ class PyTracer(object): if self.coroutine_id_func: self.data_stack = self.data_stacks[self.coroutine_id_func()] self.last_coroutine = self.coroutine_id_func() - self.data_stack.append((self.cur_file_data, self.last_line)) + self.data_stack.append((self.extension, self.cur_tracename, self.cur_file_data, self.last_line)) filename = frame.f_code.co_filename - if filename not in self.should_trace_cache: - tracename = self.should_trace(filename, frame) - self.should_trace_cache[filename] = tracename - else: - tracename = self.should_trace_cache[filename] + disp = self.should_trace_cache.get(filename) + if disp is None: + disp = self.should_trace(filename, frame) + self.should_trace_cache[filename] = disp #print("called, stack is %d deep, tracename is %r" % ( # len(self.data_stack), tracename)) + tracename = disp.filename + if tracename and disp.extension: + tracename = disp.extension.file_name(frame) if tracename: if tracename not in self.data: self.data[tracename] = {} + if disp.extension: + self.extensions[tracename] = disp.extension.__name__ + self.cur_tracename = tracename self.cur_file_data = self.data[tracename] + self.extension = disp.extension else: self.cur_file_data = None # Set the last_line to -1 because the next arc will be entering a @@ -105,16 +138,24 @@ class PyTracer(object): self.last_line = -1 elif event == 'line': # Record an executed line. - #if self.coroutine_id_func: - # assert self.last_coroutine == self.coroutine_id_func() - if self.cur_file_data is not None: - if self.arcs: - #print("lin", self.last_line, frame.f_lineno) - self.cur_file_data[(self.last_line, frame.f_lineno)] = None - else: - #print("lin", frame.f_lineno) - self.cur_file_data[frame.f_lineno] = None - self.last_line = frame.f_lineno + if 0 and self.coroutine_id_func: + this_coroutine = self.coroutine_id_func() + if self.last_coroutine != this_coroutine: + print("mismatch: {0} != {1}".format(self.last_coroutine, this_coroutine)) + if self.extension: + lineno_from, lineno_to = self.extension.line_number_range(frame) + else: + lineno_from, lineno_to = frame.f_lineno, frame.f_lineno + if lineno_from != -1: + if self.cur_file_data is not None: + if self.arcs: + #print("lin", self.last_line, frame.f_lineno) + self.cur_file_data[(self.last_line, lineno_from)] = None + else: + #print("lin", frame.f_lineno) + for lineno in range(lineno_from, lineno_to+1): + self.cur_file_data[lineno] = None + self.last_line = lineno_to elif event == 'return': if self.arcs and self.cur_file_data: first = frame.f_code.co_firstlineno @@ -123,7 +164,7 @@ class PyTracer(object): if self.coroutine_id_func: self.data_stack = self.data_stacks[self.coroutine_id_func()] self.last_coroutine = self.coroutine_id_func() - self.cur_file_data, self.last_line = self.data_stack.pop() + self.extension, _, self.cur_file_data, self.last_line = self.data_stack.pop() #print("returned, stack is %d deep" % (len(self.data_stack))) elif event == 'exception': #print("exc", self.last_line, frame.f_lineno) @@ -240,6 +281,8 @@ class Collector(object): # or mapping filenames to dicts with linenumber pairs as keys. self.data = {} + self.extensions = {} + # A cache of the results from should_trace, the decision about whether # to trace execution in a file. A dict of filename to (filename or # None). @@ -258,6 +301,8 @@ class Collector(object): tracer.warn = self.warn if hasattr(tracer, 'coroutine_id_func'): tracer.coroutine_id_func = self.coroutine_id_func + if hasattr(tracer, 'extensions'): + tracer.extensions = self.extensions fn = tracer.start() self.tracers.append(tracer) return fn @@ -356,10 +401,7 @@ class Collector(object): # to show line data. line_data = {} for f, arcs in self.data.items(): - line_data[f] = ldf = {} - for l1, _ in list(arcs.keys()): - if l1: - ldf[l1] = None + line_data[f] = dict((l1, None) for l1, _ in arcs.keys() if l1) return line_data else: return self.data @@ -377,3 +419,6 @@ class Collector(object): return self.data else: return {} + + def get_extension_data(self): + return self.extensions |