@@ -33,12 +33,16 @@ class _MonitoringTracer:
33
33
E .INSTRUCTION : 'opcode' ,
34
34
}
35
35
36
+ GLOBAL_EVENTS = E .PY_START | E .PY_RESUME | E .PY_THROW | E .PY_UNWIND | E .RAISE
37
+ LOCAL_EVENTS = E .LINE | E .JUMP | E .PY_RETURN | E .PY_YIELD | E .STOP_ITERATION
38
+
36
39
def __init__ (self ):
37
40
self ._tool_id = sys .monitoring .DEBUGGER_ID
38
41
self ._name = 'bdbtracer'
39
42
self ._tracefunc = None
40
43
self ._disable_current_event = False
41
44
self ._tracing_thread = None
45
+ self ._enabled = False
42
46
43
47
def start_trace (self , tracefunc ):
44
48
self ._tracefunc = tracefunc
@@ -47,7 +51,7 @@ def start_trace(self, tracefunc):
47
51
if curr_tool is None :
48
52
sys .monitoring .use_tool_id (self ._tool_id , self ._name )
49
53
elif curr_tool == self ._name :
50
- sys .monitoring .set_events (self ._tool_id , 0 )
54
+ sys .monitoring .clear_tool_id (self ._tool_id )
51
55
else :
52
56
raise ValueError ('Another debugger is using the monitoring tool' )
53
57
E = sys .monitoring .events
@@ -57,17 +61,18 @@ def start_trace(self, tracefunc):
57
61
sys .monitoring .register_callback (self ._tool_id , event , callback )
58
62
if event != E .INSTRUCTION :
59
63
all_events |= event
64
+ self .check_trace_func ()
60
65
self .check_trace_opcodes ()
61
- sys .monitoring .set_events (self ._tool_id , all_events )
66
+ sys .monitoring .set_events (self ._tool_id , self .GLOBAL_EVENTS )
67
+ self ._enabled = True
62
68
63
69
def stop_trace (self ):
70
+ self ._enabled = False
64
71
self ._tracing_thread = None
65
72
curr_tool = sys .monitoring .get_tool (self ._tool_id )
66
73
if curr_tool != self ._name :
67
74
return
68
- for event in self .EVENT_CALLBACK_MAP .keys ():
69
- sys .monitoring .register_callback (self ._tool_id , event , None )
70
- sys .monitoring .set_events (self ._tool_id , 0 )
75
+ sys .monitoring .clear_tool_id (self ._tool_id )
71
76
self .check_trace_opcodes ()
72
77
sys .monitoring .free_tool_id (self ._tool_id )
73
78
@@ -88,6 +93,8 @@ def wrapper(self, *args):
88
93
try :
89
94
frame = sys ._getframe ().f_back
90
95
ret = func (self , frame , * args )
96
+ if self ._enabled and frame .f_trace :
97
+ self .check_trace_func ()
91
98
if self ._disable_current_event :
92
99
return sys .monitoring .DISABLE
93
100
else :
@@ -105,6 +112,8 @@ def call_callback(self, frame, code, *args):
105
112
local_tracefunc = self ._tracefunc (frame , 'call' , None )
106
113
if local_tracefunc is not None :
107
114
frame .f_trace = local_tracefunc
115
+ if self ._enabled :
116
+ sys .monitoring .set_local_events (self ._tool_id , code , self .LOCAL_EVENTS )
108
117
109
118
@callback_wrapper
110
119
def return_callback (self , frame , code , offset , retval ):
@@ -163,6 +172,14 @@ def set_trace_opcodes(self, frame, trace_opcodes):
163
172
else :
164
173
sys .monitoring .set_local_events (self ._tool_id , frame .f_code , 0 )
165
174
175
+ def check_trace_func (self , frame = None ):
176
+ if frame is None :
177
+ frame = sys ._getframe ().f_back
178
+ while frame is not None :
179
+ if frame .f_trace is not None :
180
+ sys .monitoring .set_local_events (self ._tool_id , frame .f_code , self .LOCAL_EVENTS )
181
+ frame = frame .f_back
182
+
166
183
def _get_lineno (self , code , offset ):
167
184
import dis
168
185
last_lineno = None
0 commit comments