1- use anyhow:: { anyhow, Result } ;
1+ //use anyhow::{anyhow};
2+ use pyo3:: Py ;
3+ use pyo3:: types:: PyAny ;
24use pyo3:: prelude:: * ;
35use pyo3:: types:: { PyList , PyModule } ;
6+ use crate :: bridge:: error:: { BridgeError , Result } ;
7+ pub mod error;
48
59pub struct PythonBridge {
610 initialized : bool ,
@@ -12,7 +16,7 @@ impl PythonBridge {
1216 }
1317
1418 pub fn initialize ( & mut self ) -> Result < ( ) > {
15- Python :: with_gil ( |py| {
19+ Python :: try_attach ( |py| {
1620 let sys = py. import ( "sys" ) ?;
1721 let path_attr = sys. getattr ( "path" ) ?;
1822 let path = path_attr. downcast :: < PyList > ( ) ?;
@@ -24,18 +28,20 @@ impl PythonBridge {
2428 path. insert ( 0 , nexum_ai_path) ?;
2529
2630 Ok :: < ( ) , PyErr > ( ( ) )
27- } ) ?;
28-
31+ } )
32+ //.ok_or(BridgeError::PythonError("Python interpreter not available.".into()))?;
33+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
34+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) ) ?;
2935 self . initialized = true ;
3036 Ok ( ( ) )
3137 }
3238
3339 pub fn vectorize ( & self , text : & str ) -> Result < Vec < f32 > > {
3440 if !self . initialized {
35- return Err ( anyhow ! ( "Python bridge not initialized" ) ) ;
41+ return Err ( BridgeError :: NotInitialized ) ;
3642 }
3743
38- Python :: with_gil ( |py| {
44+ Python :: try_attach ( |py| {
3945 let nexum_ai = PyModule :: import ( py, "nexum_ai.optimizer" ) ?;
4046 let semantic_cache = nexum_ai. getattr ( "SemanticCache" ) ?;
4147 let cache_instance = semantic_cache. call0 ( ) ?;
@@ -46,24 +52,28 @@ impl PythonBridge {
4652
4753 Ok ( vector)
4854 } )
49- . map_err ( |e : PyErr | anyhow ! ( "Python error: {}" , e) )
55+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
56+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) )
57+ //.map_err(|e: PyErr| BridgeError::PythonError(e.to_string()))
5058 }
5159
5260 pub fn test_integration ( & self ) -> Result < String > {
53- Python :: with_gil ( |py| {
61+ Python :: try_attach ( |py| {
5462 let nexum_ai = PyModule :: import ( py, "nexum_ai.optimizer" ) ?;
5563 let test_func = nexum_ai. getattr ( "test_vectorization" ) ?;
5664 let result = test_func. call0 ( ) ?;
5765 let result_str: String = result. str ( ) ?. extract ( ) ?;
5866 Ok ( result_str)
5967 } )
60- . map_err ( |e : PyErr | anyhow ! ( "Python error: {}" , e) )
68+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
69+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) )
70+ //.map_err(|e: PyErr| BridgeError::PythonError(e.to_string()))
6171 }
6272}
6373
6474pub struct SemanticCache {
6575 bridge : PythonBridge ,
66- cache : PyObject ,
76+ cache : Py < PyAny > ,
6777}
6878
6979impl SemanticCache {
@@ -75,18 +85,23 @@ impl SemanticCache {
7585 let mut bridge = PythonBridge :: new ( ) ?;
7686 bridge. initialize ( ) ?;
7787
78- let cache = Python :: with_gil ( |py| {
88+ let cache = Python :: try_attach ( |py| {
7989 let nexum_ai = PyModule :: import ( py, "nexum_ai.optimizer" ) ?;
8090 let semantic_cache_class = nexum_ai. getattr ( "SemanticCache" ) ?;
8191 let cache_instance = semantic_cache_class. call1 ( ( 0.95 , cache_file) ) ?;
82- Ok :: < PyObject , PyErr > ( cache_instance. unbind ( ) )
83- } ) ?;
92+ Ok :: < Py < PyAny > , PyErr > ( cache_instance. unbind ( ) )
93+ } )
94+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
95+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) ) ?;
8496
85- Ok ( Self { bridge, cache } )
97+ Ok ( Self {
98+ bridge,
99+ cache,
100+ } )
86101 }
87102
88103 pub fn get ( & self , query : & str ) -> Result < Option < String > > {
89- Python :: with_gil ( |py| {
104+ Python :: try_attach ( |py| {
90105 let cache_bound = self . cache . bind ( py) ;
91106 let result = cache_bound. call_method1 ( "get" , ( query, ) ) ?;
92107
@@ -97,86 +112,103 @@ impl SemanticCache {
97112 Ok ( Some ( value) )
98113 }
99114 } )
100- . map_err ( |e : PyErr | anyhow ! ( "Python error: {}" , e) )
115+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
116+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) )
117+ //.map_err(|e: PyErr| BridgeError::PythonError(e.to_string()))
101118 }
102119
103120 pub fn put ( & self , query : & str , result : & str ) -> Result < ( ) > {
104- Python :: with_gil ( |py| {
121+ Python :: try_attach ( |py| {
105122 let cache_bound = self . cache . bind ( py) ;
106123 cache_bound. call_method1 ( "put" , ( query, result) ) ?;
107124 Ok :: < ( ) , PyErr > ( ( ) )
108125 } )
109- . map_err ( |e : PyErr | anyhow ! ( "Python error: {}" , e) )
126+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
127+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) )
128+ //.map_err(|e: PyErr| BridgeError::PythonError(e.to_string()))
110129 }
111130
112131 pub fn vectorize ( & self , text : & str ) -> Result < Vec < f32 > > {
113132 self . bridge . vectorize ( text)
114133 }
115134
116135 pub fn save_cache ( & self ) -> Result < ( ) > {
117- Python :: with_gil ( |py| {
136+ Python :: try_attach ( |py| {
118137 let cache_bound = self . cache . bind ( py) ;
119138 cache_bound. call_method0 ( "save_cache" ) ?;
120139 Ok :: < ( ) , PyErr > ( ( ) )
121140 } )
122- . map_err ( |e : PyErr | anyhow ! ( "Python error: {}" , e) )
141+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
142+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) )
143+ //.map_err(|e: PyErr| BridgeError::PythonError(e.to_string()))
123144 }
124145
125146 pub fn load_cache ( & self ) -> Result < ( ) > {
126- Python :: with_gil ( |py| {
147+ Python :: try_attach ( |py| {
127148 let cache_bound = self . cache . bind ( py) ;
128149 cache_bound. call_method0 ( "load_cache" ) ?;
129150 Ok :: < ( ) , PyErr > ( ( ) )
130151 } )
131- . map_err ( |e : PyErr | anyhow ! ( "Python error: {}" , e) )
152+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
153+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) )
154+ //.map_err(|e: PyErr| BridgeError::PythonError(e.to_string()))
132155 }
133156
134157 pub fn clear_cache ( & self ) -> Result < ( ) > {
135- Python :: with_gil ( |py| {
158+ Python :: try_attach ( |py| {
136159 let cache_bound = self . cache . bind ( py) ;
137160 cache_bound. call_method0 ( "clear" ) ?;
138161 Ok :: < ( ) , PyErr > ( ( ) )
139162 } )
140- . map_err ( |e : PyErr | anyhow ! ( "Python error: {}" , e) )
163+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
164+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) )
165+ //.map_err(|e: PyErr| BridgeError::PythonError(e.to_string()))
141166 }
142167
143168 pub fn get_cache_stats ( & self ) -> Result < String > {
144- Python :: with_gil ( |py| {
169+ Python :: try_attach ( |py| {
145170 let cache_bound = self . cache . bind ( py) ;
146171 let result = cache_bound. call_method0 ( "get_cache_stats" ) ?;
147172 let stats_str: String = result. str ( ) ?. extract ( ) ?;
148173 Ok ( stats_str)
149174 } )
150- . map_err ( |e : PyErr | anyhow ! ( "Python error: {}" , e) )
175+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
176+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) )
177+ //.map_err(|e: PyErr| BridgeError::PythonError(e.to_string()))
151178 }
152179
153180 pub fn explain_query ( & self , query : & str ) -> Result < String > {
154- Python :: with_gil ( |py| {
181+ Python :: try_attach ( |py| {
155182 let cache_bound = self . cache . bind ( py) ;
156183 let result = cache_bound. call_method1 ( "explain_query" , ( query, ) ) ?;
157184 let explain_str: String = result. str ( ) ?. extract ( ) ?;
158185 Ok ( explain_str)
159186 } )
160- . map_err ( |e : PyErr | anyhow ! ( "Python error: {}" , e) )
187+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
188+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) )
189+ //.map_err(|e: PyErr| BridgeError::PythonError(e.to_string()))
161190 }
162191}
163192
164193pub struct NLTranslator {
165194 _bridge : PythonBridge ,
166- translator : PyObject ,
195+ translator : Py < PyAny > ,
167196}
168197
169198impl NLTranslator {
170199 pub fn new ( ) -> Result < Self > {
171200 let mut bridge = PythonBridge :: new ( ) ?;
172201 bridge. initialize ( ) ?;
173202
174- let translator = Python :: with_gil ( |py| {
203+ let translator = Python :: try_attach ( |py| {
175204 let nexum_ai = PyModule :: import ( py, "nexum_ai.translator" ) ?;
176205 let translator_class = nexum_ai. getattr ( "NLTranslator" ) ?;
177206 let translator_instance = translator_class. call0 ( ) ?;
178- Ok :: < PyObject , PyErr > ( translator_instance. unbind ( ) )
179- } ) ?;
207+ Ok :: < Py < PyAny > , PyErr > ( translator_instance. unbind ( ) )
208+ } )
209+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
210+ . map_err ( |e| BridgeError :: PythonError ( e. to_string ( ) ) ) ?;
211+
180212
181213 Ok ( Self {
182214 _bridge : bridge,
@@ -185,14 +217,16 @@ impl NLTranslator {
185217 }
186218
187219 pub fn translate ( & self , natural_query : & str , schema : & str ) -> Result < String > {
188- Python :: with_gil ( |py| {
220+ Python :: try_attach ( |py| {
189221 let translator_bound = self . translator . bind ( py) ;
190222 let result = translator_bound. call_method1 ( "translate" , ( natural_query, schema) ) ?;
191223
192224 let sql: String = result. extract ( ) ?;
193225 Ok ( sql)
194226 } )
195- . map_err ( |e : PyErr | anyhow ! ( "Python error: {}" , e) )
227+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
228+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) )
229+
196230 }
197231}
198232
@@ -208,7 +242,7 @@ impl QueryExplainer {
208242 }
209243
210244 pub fn explain ( & self , query : & str ) -> Result < String > {
211- Python :: with_gil ( |py| {
245+ Python :: try_attach ( |py| {
212246 let nexum_ai = PyModule :: import ( py, "nexum_ai.optimizer" ) ?;
213247 let explain_func = nexum_ai. getattr ( "explain_query_plan" ) ?;
214248 let format_func = nexum_ai. getattr ( "format_explain_output" ) ?;
@@ -218,19 +252,22 @@ impl QueryExplainer {
218252 let output: String = formatted. extract ( ) ?;
219253 Ok ( output)
220254 } )
221- . map_err ( |e : PyErr | anyhow ! ( "Python error: {}" , e) )
255+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
256+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) )
222257 }
223258
224259 pub fn explain_raw ( & self , query : & str ) -> Result < String > {
225- Python :: with_gil ( |py| {
260+ Python :: try_attach ( |py| {
226261 let nexum_ai = PyModule :: import ( py, "nexum_ai.optimizer" ) ?;
227262 let explain_func = nexum_ai. getattr ( "explain_query_plan" ) ?;
228263
229264 let result = explain_func. call1 ( ( query, ) ) ?;
230265 let output: String = result. str ( ) ?. extract ( ) ?;
231266 Ok ( output)
232267 } )
233- . map_err ( |e : PyErr | anyhow ! ( "Python error: {}" , e) )
268+ . ok_or_else ( || BridgeError :: PythonError ( "Python interpreter not available" . into ( ) ) ) ?
269+ . map_err ( |e : PyErr | BridgeError :: PythonError ( e. to_string ( ) ) )
270+ //.map_err(|e: PyErr| BridgeError::PythonError(e.to_string()))
234271 }
235272}
236273
@@ -241,11 +278,15 @@ mod tests {
241278 fn check_python_available ( ) -> bool {
242279 let mut bridge = PythonBridge :: new ( ) . unwrap ( ) ;
243280 bridge. initialize ( ) . is_ok ( )
244- && Python :: with_gil ( |py| PyModule :: import ( py, "nexum_ai.optimizer" ) . is_ok ( ) )
281+ && Python :: try_attach ( |py| PyModule :: import ( py, "nexum_ai.optimizer" ) . is_ok ( ) ) . unwrap_or ( false )
245282 }
246283
247284 #[ test]
248285 fn test_python_bridge_initialization ( ) {
286+ if !check_python_available ( ) {
287+ println ! ( "Skipping test: Python environment not available" ) ;
288+ return ;
289+ }
249290 let mut bridge = PythonBridge :: new ( ) . unwrap ( ) ;
250291 bridge. initialize ( ) . unwrap ( ) ;
251292 assert ! ( bridge. initialized) ;
0 commit comments