@@ -404,6 +404,38 @@ impl Runtime {
404404 }
405405 }
406406
407+ /// Execute a string of Python code **without** restoring the
408+ /// snapshot first. Python state (globals, imports, variables)
409+ /// persists across consecutive `run_code_stateful` calls on the
410+ /// same `Runtime` instance.
411+ ///
412+ /// The very first call on a freshly-constructed `Runtime` still
413+ /// performs the initial restore (the sandbox is in the raw
414+ /// snapshot-loaded state and needs one restore to become runnable).
415+ /// All subsequent calls skip the restore entirely.
416+ ///
417+ /// This is the building block for stateful / REPL-like sessions
418+ /// where a sequence of exec calls should share a single Python
419+ /// interpreter lifetime.
420+ pub fn run_code_stateful ( & mut self , code : & str ) -> Result < RunTiming > {
421+ let mut t = RunTiming :: default ( ) ;
422+ // The very first call after construction needs the initial
423+ // restore to transition from "snapshot loaded" to "runnable".
424+ if self . first_run {
425+ let tr = Instant :: now ( ) ;
426+ self . sandbox . restore ( ) ?;
427+ t. restore_ms = tr. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ;
428+ self . first_run = false ;
429+ }
430+ self . sandbox . reset_exit_code ( ) ;
431+
432+ let tc = Instant :: now ( ) ;
433+ let _: ( ) = self . sandbox . call_named ( "run" , code. to_string ( ) ) ?;
434+ t. call_ms = tc. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ;
435+ t. exit_code = self . sandbox . last_exit_code ( ) ;
436+ Ok ( t)
437+ }
438+
407439 /// Convenience: read a file and run its contents.
408440 pub fn run_script ( & mut self , path : & Path ) -> Result < RunTiming > {
409441 let code =
0 commit comments