summaryrefslogtreecommitdiff
path: root/coverage/collector.py
diff options
context:
space:
mode:
Diffstat (limited to 'coverage/collector.py')
-rw-r--r--coverage/collector.py95
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