diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2009-12-03 08:54:27 -0500 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2009-12-03 08:54:27 -0500 |
commit | 3b6e8394c3e50cb733caafb275d2ae85c0397565 (patch) | |
tree | dd960443f9ef3772020d74c102d785968bb44dce /coverage/collector.py | |
parent | 3416380e8e46d839c3111d9f82a5f7d93a218821 (diff) | |
parent | 9e4908f37c370250ebc7836e744a59170720a9e3 (diff) | |
download | python-coveragepy-git-3b6e8394c3e50cb733caafb275d2ae85c0397565.tar.gz |
Merged default onto config.
--HG--
branch : config
Diffstat (limited to 'coverage/collector.py')
-rw-r--r-- | coverage/collector.py | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/coverage/collector.py b/coverage/collector.py index 5bbd02e0..29dddf6b 100644 --- a/coverage/collector.py +++ b/coverage/collector.py @@ -12,7 +12,7 @@ except ImportError: class PyTracer(object): """Python implementation of the raw data tracer.""" - + # Because of poor implementations of trace-function-manipulating tools, # the Python trace function must be kept very simple. In particular, there # must be only one function ever set as the trace function, both through @@ -41,10 +41,10 @@ class PyTracer(object): def _trace(self, frame, event, arg_unused): """The trace function passed to sys.settrace.""" - + #print "trace event: %s %r @%d" % ( # event, frame.f_code.co_filename, frame.f_lineno) - + if self.last_exc_back: if frame == self.last_exc_back: # Someone forgot a return event. @@ -52,7 +52,7 @@ class PyTracer(object): self.cur_file_data[(self.last_line, -1)] = None self.cur_file_data, self.last_line = self.data_stack.pop() self.last_exc_back = None - + if event == 'call': # Entering a new function context. Decide if we should trace # in this file. @@ -85,7 +85,7 @@ class PyTracer(object): #print "exc", self.last_line, frame.f_lineno self.last_exc_back = frame.f_back return self._trace - + def start(self): """Start this Tracer.""" sys.settrace(self._trace) @@ -102,18 +102,19 @@ class PyTracer(object): class Collector(object): """Collects trace data. - Creates a Tracer object for each thread, since they track stack information. - Each Tracer points to the same shared data, contributing traced data points. - + Creates a Tracer object for each thread, since they track stack + information. Each Tracer points to the same shared data, contributing + traced data points. + When the Collector is started, it creates a Tracer for the current thread, and installs a function to create Tracers for each new thread started. When the Collector is stopped, all active Tracers are stopped. - + Threads started while the Collector is stopped will never have Tracers associated with them. - + """ - + # The stack of active Collectors. Collectors are added here when started, # and popped when stopped. Collectors on the stack are paused when not # the top, and resumed when they become the top again. @@ -121,20 +122,20 @@ class Collector(object): def __init__(self, should_trace, timid, branch): """Create a collector. - + `should_trace` is a function, taking a filename, and returning a canonicalized filename, or False depending on whether the file should be traced or not. - + If `timid` is true, then a slower simpler trace function will be used. This is important for some environments where manipulation of tracing functions make the faster more sophisticated trace function not operate properly. - + If `branch` is true, then branches will be measured. This involves collecting data on which statements followed each other (arcs). Use `get_arc_data` to get the arc data. - + """ self.should_trace = should_trace self.branch = branch @@ -148,6 +149,9 @@ class Collector(object): # trace function. self._trace_class = Tracer or PyTracer + def __repr__(self): + return "<Collector at 0x%x>" % id(self) + def tracer_name(self): """Return the class name of the tracer we're using.""" return self._trace_class.__name__ @@ -157,7 +161,7 @@ class Collector(object): # A dictionary mapping filenames to dicts with linenumber keys, # or mapping filenames to dicts with linenumber pairs as keys. self.data = {} - + # 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 # False). @@ -196,6 +200,7 @@ class Collector(object): if self._collectors: self._collectors[-1].pause() self._collectors.append(self) + #print >>sys.stderr, "Started: %r" % self._collectors # Install the tracer on this thread. self._start_tracer() # Install our installation tracer in threading, to jump start other @@ -204,12 +209,13 @@ class Collector(object): def stop(self): """Stop collecting trace information.""" + #print >>sys.stderr, "Stopping: %r" % self._collectors assert self._collectors assert self._collectors[-1] is self self.pause() self.tracers = [] - + # Remove this Collector from the stack, and resume the one underneath # (if any). self._collectors.pop() @@ -226,7 +232,7 @@ class Collector(object): for k in sorted(stats.keys()): print("%16s: %s" % (k, stats[k])) threading.settrace(None) - + def resume(self): """Resume tracing after a `pause`.""" for tracer in self.tracers: @@ -235,9 +241,9 @@ class Collector(object): def get_line_data(self): """Return the line data collected. - + Data is { filename: { lineno: None, ...}, ...} - + """ if self.branch: # If we were measuring branches, then we have to re-build the dict @@ -254,7 +260,7 @@ class Collector(object): def get_arc_data(self): """Return the arc data collected. - + Data is { filename: { (l1, l2): None, ...}, ...} Note that no data is collected or returned if the Collector wasn't |