@@ -13,90 +13,14 @@ use crate::service::query_handler::QueryHandlerSpec;
1313use crate :: settings:: Settings ;
1414use crate :: setup:: { self } ;
1515use pyo3:: IntoPyObjectExt ;
16- use pyo3:: types :: { PyDict , PyModule , PyString } ;
17- use pyo3:: { exceptions :: PyException , prelude :: * } ;
16+ use pyo3:: prelude :: * ;
17+ use pyo3:: types :: PyModule ;
1818use pyo3_async_runtimes:: tokio:: future_into_py;
19- use std:: fmt:: Write ;
2019use std:: sync:: Arc ;
2120
2221mod convert;
2322pub ( crate ) use convert:: * ;
24- pub mod future;
25-
26- pub struct PythonExecutionContext {
27- pub event_loop : Py < PyAny > ,
28- }
29-
30- impl PythonExecutionContext {
31- pub fn new ( _py : Python < ' _ > , event_loop : Py < PyAny > ) -> Self {
32- Self { event_loop }
33- }
34- }
35-
36- pub trait ToResultWithPyTrace < T > {
37- fn to_result_with_py_trace ( self , py : Python < ' _ > ) -> anyhow:: Result < T > ;
38- }
39-
40- impl < T > ToResultWithPyTrace < T > for Result < T , PyErr > {
41- fn to_result_with_py_trace ( self , py : Python < ' _ > ) -> anyhow:: Result < T > {
42- match self {
43- Ok ( value) => Ok ( value) ,
44- Err ( err) => {
45- // Attempt to render a full Python-style traceback including cause/context chain
46- let full_trace: PyResult < String > = ( || {
47- let exc = err. value ( py) ;
48- let traceback = PyModule :: import ( py, "traceback" ) ?;
49- let tbe_class = traceback. getattr ( "TracebackException" ) ?;
50- let tbe = tbe_class. call_method1 ( "from_exception" , ( exc, ) ) ?;
51- let kwargs = PyDict :: new ( py) ;
52- kwargs. set_item ( "chain" , true ) ?;
53- let lines = tbe. call_method ( "format" , ( ) , Some ( & kwargs) ) ?;
54- let joined = PyString :: new ( py, "" ) . call_method1 ( "join" , ( lines, ) ) ?;
55- joined. extract :: < String > ( )
56- } ) ( ) ;
57-
58- let err_str = match full_trace {
59- Ok ( trace) => format ! ( "Error calling Python function:\n {trace}" ) ,
60- Err ( _) => {
61- // Fallback: include the PyErr display and available traceback formatting
62- let mut s = format ! ( "Error calling Python function: {err}" ) ;
63- if let Some ( tb) = err. traceback ( py) {
64- write ! ( & mut s, "\n {}" , tb. format( ) ?) . ok ( ) ;
65- }
66- s
67- }
68- } ;
69-
70- Err ( anyhow:: anyhow!( err_str) )
71- }
72- }
73- }
74- }
75- pub trait IntoPyResult < T > {
76- fn into_py_result ( self ) -> PyResult < T > ;
77- }
78-
79- impl < T , E : std:: error:: Error > IntoPyResult < T > for Result < T , E > {
80- fn into_py_result ( self ) -> PyResult < T > {
81- match self {
82- Ok ( value) => Ok ( value) ,
83- Err ( err) => Err ( PyException :: new_err ( format ! ( "{err:?}" ) ) ) ,
84- }
85- }
86- }
87-
88- pub trait AnyhowIntoPyResult < T > {
89- fn into_py_result ( self ) -> PyResult < T > ;
90- }
91-
92- impl < T > AnyhowIntoPyResult < T > for anyhow:: Result < T > {
93- fn into_py_result ( self ) -> PyResult < T > {
94- match self {
95- Ok ( value) => Ok ( value) ,
96- Err ( err) => Err ( PyException :: new_err ( format ! ( "{err:?}" ) ) ) ,
97- }
98- }
99- }
23+ pub ( crate ) use py_utils:: * ;
10024
10125#[ pyfunction]
10226fn set_settings_fn ( get_settings_fn : Py < PyAny > ) -> PyResult < ( ) > {
@@ -480,7 +404,7 @@ impl Flow {
480404 let task_locals = pyo3_async_runtimes:: TaskLocals :: new (
481405 py_exec_ctx. event_loop . bind ( py) . clone ( ) ,
482406 ) ;
483- Ok ( future :: from_py_future (
407+ Ok ( py_utils :: from_py_future (
484408 py,
485409 & task_locals,
486410 result_coro. into_bound ( py) ,
0 commit comments