1 """Imposter encodings module that installs a coverage-style tracer.
3 This is NOT the encodings module; it is an imposter that sets up tracing
4 instrumentation and then replaces itself with the real encodings module.
6 If the directory that holds this file is placed first in the PYTHONPATH when
7 using "coverage" to run Python's tests, then this file will become the very
8 first module imported by the internals of Python 3. It installs a
9 coverage-compatible trace function that can watch Standard Library modules
10 execute from the very earliest stages of Python's own boot process. This fixes
11 a problem with coverage - that it starts too late to trace the coverage of many
12 of the most fundamental modules in the Standard Library.
18 class FullCoverageTracer(object):
20 # `traces` is a list of trace events. Frames are tricky: the same
21 # frame object is used for a whole scope, with new line numbers
22 # written into it. So in one scope, all the frame objects are the
23 # same object, and will eventually all will point to the last line
24 # executed. So we keep the line numbers alongside the frames.
25 # The list looks like:
28 # ((frame, event, arg), lineno), ...
33 def fullcoverage_trace(self
, *args
):
34 frame
, event
, arg
= args
35 self
.traces
.append((args
, frame
.f_lineno
))
36 return self
.fullcoverage_trace
38 sys
.settrace(FullCoverageTracer().fullcoverage_trace
)
40 # In coverage/files.py is actual_filename(), which uses glob.glob. I don't
41 # understand why, but that use of glob borks everything if fullcoverage is in
42 # effect. So here we make an ugly hail-mary pass to switch off glob.glob over
43 # there. This means when using fullcoverage, Windows path names will not be
46 #sys.fullcoverage = True
48 # Finally, remove our own directory from sys.path; remove ourselves from
49 # sys.modules; and re-import "encodings", which will be the real package
50 # this time. Note that the delete from sys.modules dictionary has to
51 # happen last, since all of the symbols in this module will become None
52 # at that exact moment, including "sys".
54 parentdir
= max(filter(__file__
.startswith
, sys
.path
), key
=len)
55 sys
.path
.remove(parentdir
)
56 del sys
.modules
['encodings']