17757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch"""Imposter encodings module that installs a coverage-style tracer. 27757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 37757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochThis is NOT the encodings module; it is an imposter that sets up tracing 47757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochinstrumentation and then replaces itself with the real encodings module. 57757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 67757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochIf the directory that holds this file is placed first in the PYTHONPATH when 77757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochusing "coverage" to run Python's tests, then this file will become the very 87757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochfirst module imported by the internals of Python 3. It installs a 97757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochcoverage-compatible trace function that can watch Standard Library modules 107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochexecute from the very earliest stages of Python's own boot process. This fixes 117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdocha problem with coverage - that it starts too late to trace the coverage of many 127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochof the most fundamental modules in the Standard Library. 137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch""" 157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochimport sys 177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochclass FullCoverageTracer(object): 197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch def __init__(self): 207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # `traces` is a list of trace events. Frames are tricky: the same 217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # frame object is used for a whole scope, with new line numbers 227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # written into it. So in one scope, all the frame objects are the 237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # same object, and will eventually all will point to the last line 247757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # executed. So we keep the line numbers alongside the frames. 257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # The list looks like: 267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # 277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # traces = [ 287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # ((frame, event, arg), lineno), ... 297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # ] 307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # 317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self.traces = [] 327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch def fullcoverage_trace(self, *args): 347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch frame, event, arg = args 357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch self.traces.append((args, frame.f_lineno)) 367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return self.fullcoverage_trace 377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochsys.settrace(FullCoverageTracer().fullcoverage_trace) 397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch# Finally, remove our own directory from sys.path; remove ourselves from 417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch# sys.modules; and re-import "encodings", which will be the real package 427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch# this time. Note that the delete from sys.modules dictionary has to 437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch# happen last, since all of the symbols in this module will become None 447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch# at that exact moment, including "sys". 457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochparentdirs = [ d for d in sys.path if __file__.startswith(d) ] 477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochparentdirs.sort(key=len) 487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochsys.path.remove(parentdirs[-1]) 497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochdel sys.modules['encodings'] 507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochimport encodings 51