@@ -234,16 +234,29 @@ def generator_example():
234
234
235
235
236
236
class Tracer :
237
- def __init__ (self ):
237
+ def __init__ (self , trace_line_events = None , trace_opcode_events = None ):
238
+ self .trace_line_events = trace_line_events
239
+ self .trace_opcode_events = trace_opcode_events
238
240
self .events = []
241
+
242
+ def _reconfigure_frame (self , frame ):
243
+ if self .trace_line_events is not None :
244
+ frame .f_trace_lines = self .trace_line_events
245
+ if self .trace_opcode_events is not None :
246
+ frame .f_trace_opcodes = self .trace_opcode_events
247
+
239
248
def trace (self , frame , event , arg ):
249
+ self ._reconfigure_frame (frame )
240
250
self .events .append ((frame .f_lineno , event ))
241
251
return self .trace
252
+
242
253
def traceWithGenexp (self , frame , event , arg ):
254
+ self ._reconfigure_frame (frame )
243
255
(o for o in [1 ])
244
256
self .events .append ((frame .f_lineno , event ))
245
257
return self .trace
246
258
259
+
247
260
class TraceTestCase (unittest .TestCase ):
248
261
249
262
# Disable gc collection when tracing, otherwise the
@@ -257,6 +270,11 @@ def tearDown(self):
257
270
if self .using_gc :
258
271
gc .enable ()
259
272
273
+ @staticmethod
274
+ def make_tracer ():
275
+ """Helper to allow test subclasses to configure tracers differently"""
276
+ return Tracer ()
277
+
260
278
def compare_events (self , line_offset , events , expected_events ):
261
279
events = [(l - line_offset , e ) for (l , e ) in events ]
262
280
if events != expected_events :
@@ -266,7 +284,7 @@ def compare_events(self, line_offset, events, expected_events):
266
284
[str (x ) for x in events ])))
267
285
268
286
def run_and_compare (self , func , events ):
269
- tracer = Tracer ()
287
+ tracer = self . make_tracer ()
270
288
sys .settrace (tracer .trace )
271
289
func ()
272
290
sys .settrace (None )
@@ -277,7 +295,7 @@ def run_test(self, func):
277
295
self .run_and_compare (func , func .events )
278
296
279
297
def run_test2 (self , func ):
280
- tracer = Tracer ()
298
+ tracer = self . make_tracer ()
281
299
func (tracer .trace )
282
300
sys .settrace (None )
283
301
self .compare_events (func .__code__ .co_firstlineno ,
@@ -329,7 +347,7 @@ def test_13_genexp(self):
329
347
# and if the traced function contains another generator
330
348
# that is not completely exhausted, the trace stopped.
331
349
# Worse: the 'finally' clause was not invoked.
332
- tracer = Tracer ()
350
+ tracer = self . make_tracer ()
333
351
sys .settrace (tracer .traceWithGenexp )
334
352
generator_example ()
335
353
sys .settrace (None )
@@ -398,6 +416,34 @@ def func():
398
416
(1 , 'line' )])
399
417
400
418
419
+ class SkipLineEventsTraceTestCase (TraceTestCase ):
420
+ """Repeat the trace tests, but with per-line events skipped"""
421
+
422
+ def compare_events (self , line_offset , events , expected_events ):
423
+ skip_line_events = [e for e in expected_events if e [1 ] != 'line' ]
424
+ super ().compare_events (line_offset , events , skip_line_events )
425
+
426
+ @staticmethod
427
+ def make_tracer ():
428
+ return Tracer (trace_line_events = False )
429
+
430
+
431
+ @support .cpython_only
432
+ class TraceOpcodesTestCase (TraceTestCase ):
433
+ """Repeat the trace tests, but with per-opcodes events enabled"""
434
+
435
+ def compare_events (self , line_offset , events , expected_events ):
436
+ skip_opcode_events = [e for e in events if e [1 ] != 'opcode' ]
437
+ if len (events ) > 1 :
438
+ self .assertLess (len (skip_opcode_events ), len (events ),
439
+ msg = "No 'opcode' events received by the tracer" )
440
+ super ().compare_events (line_offset , skip_opcode_events , expected_events )
441
+
442
+ @staticmethod
443
+ def make_tracer ():
444
+ return Tracer (trace_opcode_events = True )
445
+
446
+
401
447
class RaisingTraceFuncTestCase (unittest .TestCase ):
402
448
def setUp (self ):
403
449
self .addCleanup (sys .settrace , sys .gettrace ())
@@ -846,6 +892,8 @@ class fake_function:
846
892
def test_main ():
847
893
support .run_unittest (
848
894
TraceTestCase ,
895
+ SkipLineEventsTraceTestCase ,
896
+ TraceOpcodesTestCase ,
849
897
RaisingTraceFuncTestCase ,
850
898
JumpTestCase
851
899
)
0 commit comments