@startuml Rustpy Macro Execution Sequence
!theme plain
title Rustpy: Python Code Execution Flow
actor "Rust Code" as Rust
participant "python! Macro" as Macro
participant "Runtime" as Runtime
participant "Global State" as State
participant "PyO3" as PyO3
participant "CPython" as Python
== Initialization (First Call) ==
Rust -> Macro: python! { code }
activate Macro
Macro -> Runtime: execute_python(code)
activate Runtime
Runtime -> State: get_or_init()
activate State
State -> PyO3: prepare_freethreaded_python()
activate PyO3
PyO3 -> Python: initialize interpreter
activate Python
Python --> PyO3: interpreter ready
deactivate Python
PyO3 --> State: Python instance
deactivate PyO3
State --> Runtime: Python guard
deactivate State
== Code Execution ==
Runtime -> PyO3: Python::with_gil(|py| {...})
activate PyO3
PyO3 -> Python: acquire GIL
activate Python
Runtime -> Python: PyModule::from_code(code)
Python -> Python: compile & execute
alt Success
Python --> Runtime: Ok(())
else Python Error
Python --> Runtime: Err(PyErr)
Runtime -> Runtime: convert to RustpyError
end
Python -> PyO3: release GIL
deactivate Python
PyO3 --> Runtime: result
deactivate PyO3
Runtime --> Macro: Result<(), RustpyError>
deactivate Runtime
Macro --> Rust: result
deactivate Macro
== Subsequent Calls (Reuse Interpreter) ==
Rust -> Macro: python! { code2 }
activate Macro
Macro -> Runtime: execute_python(code2)
activate Runtime
Runtime -> State: get() [already initialized]
activate State
State --> Runtime: Python guard
deactivate State
Runtime -> PyO3: Python::with_gil(|py| {...})
activate PyO3
PyO3 -> Python: acquire GIL
activate Python
Runtime -> Python: execute code2
Python --> Runtime: result
Python -> PyO3: release GIL
deactivate Python
PyO3 --> Runtime: result
deactivate PyO3
Runtime --> Macro: result
deactivate Runtime
Macro --> Rust: result
deactivate Macro
note right of State
Global Python instance
persists across calls
for variable sharing
end note
@enduml