34
34
CTracer = None
35
35
36
36
37
- def should_start_context (frame ):
38
- """Who-Tests-What hack: Determine whether this frame begins a new who-context."""
39
- fn_name = frame .f_code .co_name
40
- if fn_name .startswith ("test" ):
41
- return fn_name
42
- return None
43
-
44
-
45
37
class Collector (object ):
46
38
"""Collects trace data.
47
39
@@ -66,7 +58,10 @@ class Collector(object):
66
58
# The concurrency settings we support here.
67
59
SUPPORTED_CONCURRENCIES = set (["greenlet" , "eventlet" , "gevent" , "thread" ])
68
60
69
- def __init__ (self , should_trace , check_include , timid , branch , warn , concurrency ):
61
+ def __init__ (
62
+ self , should_trace , check_include , should_start_context ,
63
+ timid , branch , warn , concurrency ,
64
+ ):
70
65
"""Create a collector.
71
66
72
67
`should_trace` is a function, taking a file name and a frame, and
@@ -75,6 +70,11 @@ def __init__(self, should_trace, check_include, timid, branch, warn, concurrency
75
70
`check_include` is a function taking a file name and a frame. It returns
76
71
a boolean: True if the file should be traced, False if not.
77
72
73
+ `should_start_context` is a function taking a frame, and returning a
74
+ string. If the frame should be the start of a new context, the string
75
+ is the new context. If the frame should not be the start of a new
76
+ context, return None.
77
+
78
78
If `timid` is true, then a slower simpler trace function will be
79
79
used. This is important for some environments where manipulation of
80
80
tracing functions make the faster more sophisticated trace function not
@@ -96,6 +96,7 @@ def __init__(self, should_trace, check_include, timid, branch, warn, concurrency
96
96
"""
97
97
self .should_trace = should_trace
98
98
self .check_include = check_include
99
+ self .should_start_context = should_start_context
99
100
self .warn = warn
100
101
self .branch = branch
101
102
self .threading = None
@@ -139,10 +140,6 @@ def __init__(self, should_trace, check_include, timid, branch, warn, concurrency
139
140
)
140
141
)
141
142
142
- # Who-Tests-What is just a hack at the moment, so turn it on with an
143
- # environment variable.
144
- self .wtw = int (os .getenv ('COVERAGE_WTW' , 0 ))
145
-
146
143
self .reset ()
147
144
148
145
if timid :
@@ -175,7 +172,11 @@ def tracer_name(self):
175
172
176
173
def _clear_data (self ):
177
174
"""Clear out existing data, but stay ready for more collection."""
178
- self .data .clear ()
175
+ # We used to used self.data.clear(), but that would remove filename
176
+ # keys and data values that were still in use higher up the stack
177
+ # when we are called as part of switch_context.
178
+ for d in self .data .values ():
179
+ d .clear ()
179
180
180
181
for tracer in self .tracers :
181
182
tracer .reset_activity ()
@@ -187,10 +188,6 @@ def reset(self):
187
188
# pairs as keys (if branch coverage).
188
189
self .data = {}
189
190
190
- # A dict mapping contexts to data dictionaries.
191
- self .contexts = {}
192
- self .contexts [None ] = self .data
193
-
194
191
# A dictionary mapping file names to file tracer plugin names that will
195
192
# handle them.
196
193
self .file_tracers = {}
@@ -252,11 +249,13 @@ def _start_tracer(self):
252
249
tracer .threading = self .threading
253
250
if hasattr (tracer , 'check_include' ):
254
251
tracer .check_include = self .check_include
255
- if self .wtw :
256
- if hasattr (tracer , 'should_start_context' ):
257
- tracer .should_start_context = should_start_context
258
- if hasattr (tracer , 'switch_context' ):
259
- tracer .switch_context = self .switch_context
252
+ if hasattr (tracer , 'should_start_context' ):
253
+ tracer .should_start_context = self .should_start_context
254
+ tracer .switch_context = self .switch_context
255
+ elif self .should_start_context :
256
+ raise CoverageException (
257
+ "Can't support dynamic contexts with {}" .format (self .tracer_name ())
258
+ )
260
259
261
260
fn = tracer .start ()
262
261
self .tracers .append (tracer )
@@ -372,12 +371,9 @@ def _activity(self):
372
371
return any (tracer .activity () for tracer in self .tracers )
373
372
374
373
def switch_context (self , new_context ):
375
- """Who-Tests-What hack: switch to a new who-context."""
376
- # Make a new data dict, or find the existing one, and switch all the
377
- # tracers to use it.
378
- data = self .contexts .setdefault (new_context , {})
379
- for tracer in self .tracers :
380
- tracer .data = data
374
+ """Switch to a new dynamic context."""
375
+ self .flush_data ()
376
+ self .covdata .set_context (new_context )
381
377
382
378
def cached_abs_file (self , filename ):
383
379
"""A locally cached version of `abs_file`."""
@@ -415,20 +411,13 @@ def abs_file_dict(d):
415
411
else :
416
412
raise runtime_err # pylint: disable=raising-bad-type
417
413
418
- return dict ((self .cached_abs_file (k ), v ) for k , v in items )
414
+ return dict ((self .cached_abs_file (k ), v ) for k , v in items if v )
419
415
420
416
if self .branch :
421
417
self .covdata .add_arcs (abs_file_dict (self .data ))
422
418
else :
423
419
self .covdata .add_lines (abs_file_dict (self .data ))
424
420
self .covdata .add_file_tracers (abs_file_dict (self .file_tracers ))
425
421
426
- if self .wtw :
427
- # Just a hack, so just hack it.
428
- import pprint
429
- out_file = "coverage_wtw_{:06}.py" .format (os .getpid ())
430
- with open (out_file , "w" ) as wtw_out :
431
- pprint .pprint (self .contexts , wtw_out )
432
-
433
422
self ._clear_data ()
434
423
return True
0 commit comments