29
29
context_manager : Optional [ContextManager ] = None
30
30
write_line : Optional [Callable [[dict ], None ]] = None
31
31
32
- FUNCTION_CALL_OP_NAMES = {
33
- "CALL_METHOD" ,
34
- "CALL_FUNCTION" ,
35
- "CALL_FUNCTION_KW" ,
36
- "CALL_FUNCTION_EX" ,
37
- "LOAD_ATTR" ,
38
- "BINARY_SUBSCR" ,
39
- }
40
-
41
32
42
33
def get_tracer () -> Tracer :
43
34
global TRACER
@@ -282,7 +273,6 @@ def log_call(
282
273
fn : Callable ,
283
274
args : Iterable = (),
284
275
kwargs : Mapping [str , Any ] = {},
285
- return_type : Any = None ,
286
276
) -> None :
287
277
bound = Bound .create (fn , args , kwargs )
288
278
line : Dict = {"location" : location , "function" : preprocess (fn )}
@@ -294,8 +284,6 @@ def log_call(
294
284
line ["params" ]["kwargs" ] = {k : preprocess (v ) for k , v in kwargs .items ()}
295
285
else :
296
286
line ["bound_params" ] = bound .as_dict ()
297
- if return_type :
298
- line ['return_type' ] = return_type
299
287
assert write_line
300
288
write_line (line )
301
289
@@ -307,16 +295,11 @@ class Stack:
307
295
NULL : ClassVar [object ] = object ()
308
296
current_i : int = dataclasses .field (init = False , default = 0 )
309
297
opcode : int = dataclasses .field (init = False )
310
- previous_stack : Optional [Stack ] = None
311
- log_call_args : Tuple = ()
312
298
313
299
def __post_init__ (self ):
314
300
self .op_stack = get_stack .OpStack (self .frame )
315
301
self .opcode = self .frame .f_code .co_code [self .frame .f_lasti ]
316
302
317
- if self .previous_stack and self .previous_stack .previous_stack :
318
- del self .previous_stack .previous_stack
319
-
320
303
@property
321
304
def oparg (self ):
322
305
# sort of replicates logic in dis._unpack_opargs but doesn't account for extended
@@ -377,24 +360,14 @@ def pop_n(self, n: int) -> List:
377
360
return l
378
361
379
362
def process (
380
- self ,
381
- keyed_args : Tuple ,
382
- fn : Callable ,
383
- args : Iterable ,
384
- kwargs : Mapping = {},
385
- delay : bool = False
363
+ self , keyed_args : Tuple , fn : Callable , args : Iterable , kwargs : Mapping = {}
386
364
) -> None :
387
-
388
- # Note: This take args as an iterable, instead of as a varargs, so that if
389
- # we don't trace we don't have to expand the iterable
365
+ # Note: This take args as an iterable, instead of as a varargs, so that if we don't trace we don't have to expand the iterable
390
366
if self .tracer .should_trace (* keyed_args ):
391
367
filename = self .frame .f_code .co_filename
392
368
line = self .frame .f_lineno
393
369
# Don't pass kwargs if not used, so we can more easily test mock calls
394
- if not delay :
395
- log_call (f"{ filename } :{ line } " , fn , tuple (args ), * ((kwargs ,) if kwargs else ()))
396
- else :
397
- self .log_call_args = (filename , line , fn , tuple (args ), kwargs )
370
+ log_call (f"{ filename } :{ line } " , fn , tuple (args ), * ((kwargs ,) if kwargs else ()))
398
371
399
372
def __call__ (self ) -> None :
400
373
"""
@@ -410,34 +383,14 @@ def __call__(self) -> None:
410
383
(self .TOS , self .TOS1 ), BINARY_OPS [opname ], (self .TOS1 , self .TOS )
411
384
)
412
385
413
- if self .previous_stack and self .previous_stack .opname in FUNCTION_CALL_OP_NAMES :
414
- self .log_called_method ()
415
-
416
386
method_name = f"op_{ opname } "
417
387
if hasattr (self , method_name ):
418
388
getattr (self , method_name )()
419
389
return None
420
390
421
- def log_called_method (self ):
422
- if self .previous_stack .log_call_args :
423
- tos = self .TOS
424
- if type (tos ) is type and issubclass (tos , Exception ):
425
- # Don't record exception
426
- return
427
- return_type = type (tos ) if type (tos ) != type else tos
428
- filename , line , fn , args , * kwargs = self .previous_stack .log_call_args
429
- kwargs = kwargs [0 ] if kwargs else {}
430
- log_call (
431
- f"{ filename } :{ line } " ,
432
- fn ,
433
- tuple (args ),
434
- * ((kwargs ,) if kwargs else ()),
435
- return_type = return_type ,
436
- )
437
-
438
391
# special case subscr b/c we only check first arg, not both
439
392
def op_BINARY_SUBSCR (self ):
440
- self .process ((self .TOS1 ,), op .getitem , (self .TOS1 , self .TOS ), delay = True )
393
+ self .process ((self .TOS1 ,), op .getitem , (self .TOS1 , self .TOS ))
441
394
442
395
def op_STORE_SUBSCR (self ):
443
396
self .process ((self .TOS1 ,), op .setitem , (self .TOS1 , self .TOS , self .TOS2 ))
@@ -446,7 +399,7 @@ def op_DELETE_SUBSCR(self):
446
399
self .process ((self .TOS1 ,), op .delitem , (self .TOS1 , self .TOS ))
447
400
448
401
def op_LOAD_ATTR (self ):
449
- self .process ((self .TOS ,), getattr , (self .TOS , self .opvalname ), delay = True )
402
+ self .process ((self .TOS ,), getattr , (self .TOS , self .opvalname ))
450
403
451
404
def op_STORE_ATTR (self ):
452
405
self .process ((self .TOS ,), setattr , (self .TOS , self .opvalname , self .TOS1 ))
@@ -505,7 +458,7 @@ def op_COMPARE_OP(self):
505
458
def op_CALL_FUNCTION (self ):
506
459
args = self .pop_n (self .oparg )
507
460
fn = self .pop ()
508
- self .process ((fn ,), fn , args , delay = True )
461
+ self .process ((fn ,), fn , args )
509
462
510
463
def op_CALL_FUNCTION_KW (self ):
511
464
kwargs_keys = self .pop ()
@@ -515,7 +468,7 @@ def op_CALL_FUNCTION_KW(self):
515
468
args = self .pop_n (self .oparg - n_kwargs )
516
469
fn = self .pop ()
517
470
518
- self .process ((fn ,), fn , args , kwargs , delay = True )
471
+ self .process ((fn ,), fn , args , kwargs )
519
472
520
473
def op_CALL_FUNCTION_EX (self ):
521
474
has_kwarg = self .oparg & int ("01" , 2 )
@@ -529,21 +482,20 @@ def op_CALL_FUNCTION_EX(self):
529
482
fn = self .pop ()
530
483
if inspect .isgenerator (args ):
531
484
return
532
- self .process ((fn ,), fn , args , kwargs , delay = True )
485
+ self .process ((fn ,), fn , args , kwargs )
533
486
534
487
def op_CALL_METHOD (self ):
535
488
args = self .pop_n (self .oparg )
536
489
function_or_self = self .pop ()
537
490
null_or_method = self .pop ()
538
491
if null_or_method is self .NULL :
539
492
function = function_or_self
540
- self .process ((function ,), function , args , delay = True )
493
+ self .process ((function ,), function , args )
541
494
else :
542
495
self_ = function_or_self
543
496
method = null_or_method
544
497
self .process (
545
498
(self_ ,), method , itertools .chain ((self_ ,), args ),
546
- delay = True
547
499
)
548
500
549
501
@@ -596,7 +548,6 @@ class Tracer:
596
548
calls_to_modules : List [str ]
597
549
# the modules we should trace calls from
598
550
calls_from_modules : List [str ]
599
- previous_stack : Optional [Stack ] = None
600
551
601
552
def __enter__ (self ):
602
553
sys .settrace (self )
@@ -626,13 +577,7 @@ def __call__(self, frame, event, arg) -> Optional[Tracer]:
626
577
return None
627
578
628
579
if self .should_trace_frame (frame ):
629
- stack = Stack (
630
- self ,
631
- frame ,
632
- previous_stack = self .previous_stack ,
633
- )
634
- stack ()
635
- self .previous_stack = stack if stack .log_call_args else None
580
+ Stack (self , frame )()
636
581
return None
637
582
638
583
def should_trace_frame (self , frame ) -> bool :
0 commit comments