1+ use std:: any:: Any ;
2+ use std:: sync:: Mutex ;
3+
14use crate :: code_object:: { CodeObjectRegistry , CodeObjectWrapper } ;
25use pyo3:: {
36 exceptions:: PyRuntimeError ,
47 prelude:: * ,
5- types:: { PyAny , PyCFunction , PyCode , PyModule } ,
8+ types:: { PyAny , PyCode , PyModule } ,
69} ;
7- use std:: any:: Any ;
8- use std:: sync:: { Mutex , OnceLock } ;
9-
10- const MONITORING_TOOL_NAME : & str = "codetracer" ;
11-
12- #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
13- #[ repr( transparent) ]
14- pub struct EventId ( pub i32 ) ;
15-
16- #[ allow( non_snake_case) ]
17- #[ derive( Clone , Copy , Debug ) ]
18- pub struct MonitoringEvents {
19- pub BRANCH : EventId ,
20- pub CALL : EventId ,
21- pub C_RAISE : EventId ,
22- pub C_RETURN : EventId ,
23- pub EXCEPTION_HANDLED : EventId ,
24- pub INSTRUCTION : EventId ,
25- pub JUMP : EventId ,
26- pub LINE : EventId ,
27- pub PY_RESUME : EventId ,
28- pub PY_RETURN : EventId ,
29- pub PY_START : EventId ,
30- pub PY_THROW : EventId ,
31- pub PY_UNWIND : EventId ,
32- pub PY_YIELD : EventId ,
33- pub RAISE : EventId ,
34- pub RERAISE : EventId ,
35- //pub STOP_ITERATION: EventId, //See comment in Tracer trait
36- }
37-
38- #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
39- pub struct ToolId {
40- pub id : u8 ,
41- }
42-
43- pub type CallbackFn < ' py > = Bound < ' py , PyCFunction > ;
44-
45- #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
46- pub struct EventSet ( pub i32 ) ;
47-
48- pub const NO_EVENTS : EventSet = EventSet ( 0 ) ;
49-
50- /// Outcome returned by tracer callbacks to control CPython monitoring.
51- #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
52- pub enum CallbackOutcome {
53- /// Continue receiving events for the current location.
54- Continue ,
55- /// Disable future events for the current location by returning
56- /// `sys.monitoring.DISABLE`.
57- DisableLocation ,
58- }
59-
60- /// Result type shared by tracer callbacks.
61- pub type CallbackResult = PyResult < CallbackOutcome > ;
62-
63- impl EventSet {
64- pub const fn empty ( ) -> Self {
65- NO_EVENTS
66- }
67- pub fn contains ( & self , ev : & EventId ) -> bool {
68- ( self . 0 & ev. 0 ) != 0
69- }
70- }
71-
72- pub fn acquire_tool_id ( py : Python < ' _ > ) -> PyResult < ToolId > {
73- let monitoring = py. import ( "sys" ) ?. getattr ( "monitoring" ) ?;
74- const FALLBACK_ID : u8 = 5 ;
75- monitoring. call_method1 ( "use_tool_id" , ( FALLBACK_ID , MONITORING_TOOL_NAME ) ) ?;
76- Ok ( ToolId { id : FALLBACK_ID } )
77- }
78-
79- pub fn load_monitoring_events ( py : Python < ' _ > ) -> PyResult < MonitoringEvents > {
80- let monitoring = py. import ( "sys" ) ?. getattr ( "monitoring" ) ?;
81- let events = monitoring. getattr ( "events" ) ?;
82- Ok ( MonitoringEvents {
83- BRANCH : EventId ( events. getattr ( "BRANCH" ) ?. extract ( ) ?) ,
84- CALL : EventId ( events. getattr ( "CALL" ) ?. extract ( ) ?) ,
85- C_RAISE : EventId ( events. getattr ( "C_RAISE" ) ?. extract ( ) ?) ,
86- C_RETURN : EventId ( events. getattr ( "C_RETURN" ) ?. extract ( ) ?) ,
87- EXCEPTION_HANDLED : EventId ( events. getattr ( "EXCEPTION_HANDLED" ) ?. extract ( ) ?) ,
88- INSTRUCTION : EventId ( events. getattr ( "INSTRUCTION" ) ?. extract ( ) ?) ,
89- JUMP : EventId ( events. getattr ( "JUMP" ) ?. extract ( ) ?) ,
90- LINE : EventId ( events. getattr ( "LINE" ) ?. extract ( ) ?) ,
91- PY_RESUME : EventId ( events. getattr ( "PY_RESUME" ) ?. extract ( ) ?) ,
92- PY_RETURN : EventId ( events. getattr ( "PY_RETURN" ) ?. extract ( ) ?) ,
93- PY_START : EventId ( events. getattr ( "PY_START" ) ?. extract ( ) ?) ,
94- PY_THROW : EventId ( events. getattr ( "PY_THROW" ) ?. extract ( ) ?) ,
95- PY_UNWIND : EventId ( events. getattr ( "PY_UNWIND" ) ?. extract ( ) ?) ,
96- PY_YIELD : EventId ( events. getattr ( "PY_YIELD" ) ?. extract ( ) ?) ,
97- RAISE : EventId ( events. getattr ( "RAISE" ) ?. extract ( ) ?) ,
98- RERAISE : EventId ( events. getattr ( "RERAISE" ) ?. extract ( ) ?) ,
99- //STOP_ITERATION: EventId(events.getattr("STOP_ITERATION")?.extract()?), //See comment in Tracer trait
100- } )
101- }
102-
103- static MONITORING_EVENTS : OnceLock < MonitoringEvents > = OnceLock :: new ( ) ;
10410
105- pub fn monitoring_events ( py : Python < ' _ > ) -> PyResult < & ' static MonitoringEvents > {
106- if let Some ( ev) = MONITORING_EVENTS . get ( ) {
107- return Ok ( ev) ;
108- }
109- let ev = load_monitoring_events ( py) ?;
110- let _ = MONITORING_EVENTS . set ( ev) ;
111- Ok ( MONITORING_EVENTS . get ( ) . unwrap ( ) )
112- }
113-
114- pub fn register_callback (
115- py : Python < ' _ > ,
116- tool : & ToolId ,
117- event : & EventId ,
118- cb : Option < & CallbackFn < ' _ > > ,
119- ) -> PyResult < ( ) > {
120- let monitoring = py. import ( "sys" ) ?. getattr ( "monitoring" ) ?;
121- match cb {
122- Some ( cb) => {
123- monitoring. call_method ( "register_callback" , ( tool. id , event. 0 , cb) , None ) ?;
124- }
125- None => {
126- monitoring. call_method ( "register_callback" , ( tool. id , event. 0 , py. None ( ) ) , None ) ?;
127- }
128- }
129- Ok ( ( ) )
130- }
131-
132- pub fn events_union ( ids : & [ EventId ] ) -> EventSet {
133- let mut bits = 0i32 ;
134- for id in ids {
135- bits |= id. 0 ;
136- }
137- EventSet ( bits)
138- }
139-
140- pub fn set_events ( py : Python < ' _ > , tool : & ToolId , set : EventSet ) -> PyResult < ( ) > {
141- let monitoring = py. import ( "sys" ) ?. getattr ( "monitoring" ) ?;
142- monitoring. call_method1 ( "set_events" , ( tool. id , set. 0 ) ) ?;
143- Ok ( ( ) )
144- }
145-
146- pub fn free_tool_id ( py : Python < ' _ > , tool : & ToolId ) -> PyResult < ( ) > {
147- let monitoring = py. import ( "sys" ) ?. getattr ( "monitoring" ) ?;
148- monitoring. call_method1 ( "free_tool_id" , ( tool. id , ) ) ?;
149- Ok ( ( ) )
150- }
11+ use super :: {
12+ acquire_tool_id, free_tool_id, monitoring_events, register_callback, set_events,
13+ CallbackOutcome , CallbackResult , EventSet , MonitoringEvents , ToolId , NO_EVENTS ,
14+ } ;
15115
15216/// Trait implemented by tracing backends.
15317///
@@ -545,7 +409,6 @@ pub fn uninstall_tracer(py: Python<'_>) -> PyResult<()> {
545409 if global. mask . contains ( & events. EXCEPTION_HANDLED ) {
546410 register_callback ( py, & global. tool , & events. EXCEPTION_HANDLED , None ) ?;
547411 }
548- // See comment in tracer trait
549412 // if global.mask.contains(&events.STOP_ITERATION) {
550413 // register_callback(py, &global.tool, &events.STOP_ITERATION, None)?;
551414 // }
@@ -556,7 +419,6 @@ pub fn uninstall_tracer(py: Python<'_>) -> PyResult<()> {
556419 register_callback ( py, & global. tool , & events. C_RAISE , None ) ?;
557420 }
558421
559- global. registry . clear ( ) ;
560422 set_events ( py, & global. tool , NO_EVENTS ) ?;
561423 free_tool_id ( py, & global. tool ) ?;
562424 }
@@ -658,14 +520,7 @@ fn callback_py_start(
658520 if let Some ( global) = GLOBAL . lock ( ) . unwrap ( ) . as_mut ( ) {
659521 let wrapper = global. registry . get_or_insert ( py, & code) ;
660522 let result = global. tracer . on_py_start ( py, & wrapper, instruction_offset) ;
661- return match result {
662- Ok ( outcome) => global. handle_callback ( py, Ok ( outcome) ) ,
663- Err ( err) => {
664- let _ = set_events ( py, & global. tool , NO_EVENTS ) ;
665- log:: error!( "Event monitoring turned off due to exception. No new events will be recorded! {}" , err) ;
666- Err ( err)
667- }
668- } ;
523+ return global. handle_callback ( py, result) ;
669524 }
670525 Ok ( py. None ( ) )
671526}
0 commit comments