summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2011-08-07 22:09:40 -0400
committerNed Batchelder <ned@nedbatchelder.com>2011-08-07 22:09:40 -0400
commitced439588b3b3a66d5e68f00e8542d56250844d3 (patch)
treeb16efb803a71ddd2e3ad6ca90b63c99ce367fd48
parent02c995d45f7114df741bbd644b5810645df98740 (diff)
downloadpython-coveragepy-ced439588b3b3a66d5e68f00e8542d56250844d3.tar.gz
An enormous hack to try to get stdlib measurement from the very beginning of the process.
-rw-r--r--coverage/collector.py19
-rw-r--r--coverage/fullcoverage/encodings.py41
2 files changed, 59 insertions, 1 deletions
diff --git a/coverage/collector.py b/coverage/collector.py
index 9c40d16..9752e53 100644
--- a/coverage/collector.py
+++ b/coverage/collector.py
@@ -233,8 +233,25 @@ class Collector(object):
self._collectors[-1].pause()
self._collectors.append(self)
#print >>sys.stderr, "Started: %r" % self._collectors
+
+ # Check to see whether we had a fullcoverage tracer installed.
+ traces0 = None
+ if hasattr(sys, "gettrace"):
+ fn0 = sys.gettrace()
+ if fn0:
+ tracer0 = getattr(fn0, '__self__', None)
+ if tracer0:
+ traces0 = getattr(tracer0, 'traces', None)
+
# Install the tracer on this thread.
- self._start_tracer()
+ fn = self._start_tracer()
+
+ if traces0:
+ #print("traces0 has %d" % len(traces0))
+ for args in traces0:
+ frame, event, arg = args
+ fn(*args)
+
# Install our installation tracer in threading, to jump start other
# threads.
threading.settrace(self._installation_trace)
diff --git a/coverage/fullcoverage/encodings.py b/coverage/fullcoverage/encodings.py
new file mode 100644
index 0000000..48b2b2e
--- /dev/null
+++ b/coverage/fullcoverage/encodings.py
@@ -0,0 +1,41 @@
+"""Imposter encodings module that installs a coverage-style tracer.
+
+This is NOT the encodings module; it is an imposter that sets up tracing
+instrumentation and then replaces itself with the real encodings module.
+
+If the directory that holds this file is placed first in the PYTHONPATH when
+using "coverage" to run Python's tests, then this file will become the very
+first module imported by the internals of Python 3. It installs a
+coverage-compatible trace function that can watch Standard Library modules
+execute from the very earliest stages of Python's own boot process. This fixes
+a problem with coverage - that it starts too late to trace the coverage of many
+of the most fundamental modules in the Standard Library.
+
+"""
+
+import sys
+
+class FullCoverageTracer(object):
+ def __init__(self):
+ self.traces = []
+
+ def fullcoverage_trace(self, *args):
+ frame, event, arg = args
+ #if "os.py" in frame.f_code.co_filename:
+ # print("%s @ %d" % (frame.f_code.co_filename, frame.f_lineno))
+ self.traces.append(args)
+ return self.fullcoverage_trace
+
+sys.settrace(FullCoverageTracer().fullcoverage_trace)
+
+# Finally, remove our own directory from sys.path; remove ourselves from
+# sys.modules; and re-import "encodings", which will be the real package
+# this time. Note that the delete from sys.modules dictionary has to
+# happen last, since all of the symbols in this module will become None
+# at that exact moment, including "sys".
+
+import os
+this = os.path.dirname(__file__)
+sys.path.remove(this)
+del sys.modules['encodings']
+import encodings