@@ -2,7 +2,7 @@ mod context;
22
33use :: cel:: objects:: { Key , TryIntoValue } ;
44use :: cel:: { Context as CelContext , ExecutionError , Program , Value } ;
5- use log:: debug ;
5+ use log:: warn ;
66use pyo3:: exceptions:: { PyRuntimeError , PyTypeError , PyValueError } ;
77use pyo3:: prelude:: * ;
88use pyo3:: BoundObject ;
@@ -32,10 +32,7 @@ impl<'py> IntoPyObject<'py> for RustyCelType {
3232 RustyCelType ( Value :: Int ( i64) ) => i64. into_pyobject ( py) ?. into_any ( ) ,
3333 RustyCelType ( Value :: UInt ( u64) ) => u64. into_pyobject ( py) ?. into_any ( ) ,
3434 RustyCelType ( Value :: Float ( f) ) => f. into_pyobject ( py) ?. into_any ( ) ,
35- RustyCelType ( Value :: Timestamp ( ts) ) => {
36- debug ! ( "Converting a fixed offset datetime to python type" ) ;
37- ts. into_pyobject ( py) ?. into_any ( )
38- }
35+ RustyCelType ( Value :: Timestamp ( ts) ) => ts. into_pyobject ( py) ?. into_any ( ) ,
3936 RustyCelType ( Value :: Duration ( d) ) => d. into_pyobject ( py) ?. into_any ( ) ,
4037 RustyCelType ( Value :: String ( s) ) => s. as_ref ( ) . to_string ( ) . into_pyobject ( py) ?. into_any ( ) ,
4138 RustyCelType ( Value :: List ( val) ) => {
@@ -200,19 +197,19 @@ impl TryIntoValue for RustyPyType<'_> {
200197 Ok ( Value :: Duration ( value) )
201198 } else if let Ok ( value) = pyobject. extract :: < String > ( ) {
202199 Ok ( Value :: String ( value. into ( ) ) )
203- } else if let Ok ( value) = pyobject. downcast :: < PyList > ( ) {
200+ } else if let Ok ( value) = pyobject. cast :: < PyList > ( ) {
204201 let list = value
205202 . iter ( )
206203 . map ( |item| RustyPyType ( & item) . try_into_value ( ) )
207204 . collect :: < Result < Vec < Value > , Self :: Error > > ( ) ;
208205 list. map ( |v| Value :: List ( Arc :: new ( v) ) )
209- } else if let Ok ( value) = pyobject. downcast :: < PyTuple > ( ) {
206+ } else if let Ok ( value) = pyobject. cast :: < PyTuple > ( ) {
210207 let list = value
211208 . iter ( )
212209 . map ( |item| RustyPyType ( & item) . try_into_value ( ) )
213210 . collect :: < Result < Vec < Value > , Self :: Error > > ( ) ;
214211 list. map ( |v| Value :: List ( Arc :: new ( v) ) )
215- } else if let Ok ( value) = pyobject. downcast :: < PyDict > ( ) {
212+ } else if let Ok ( value) = pyobject. cast :: < PyDict > ( ) {
216213 let mut map: HashMap < Key , Value > = HashMap :: new ( ) ;
217214 for ( key, value) in value. into_iter ( ) {
218215 let key = if key. is_none ( ) {
@@ -407,7 +404,7 @@ fn evaluate(src: String, evaluation_context: Option<&Bound<'_, PyAny>>) -> PyRes
407404 // Clone variables and functions into our local Context
408405 ctx. variables = py_context_ref. variables . clone ( ) ;
409406 ctx. functions = py_context_ref. functions . clone ( ) ;
410- } else if let Ok ( py_dict) = evaluation_context. downcast :: < PyDict > ( ) {
407+ } else if let Ok ( py_dict) = evaluation_context. cast :: < PyDict > ( ) {
411408 // User passed in a dict - let's process variables and functions from the dict
412409 ctx. update ( py_dict) ?;
413410 } else {
@@ -419,12 +416,10 @@ fn evaluate(src: String, evaluation_context: Option<&Bound<'_, PyAny>>) -> PyRes
419416 variables_for_env = ctx. variables . clone ( ) ;
420417 }
421418
422- // Strict mode only - preserve original expression without any preprocessing
423- let processed_src = src. clone ( ) ;
424-
425419 // Use panic::catch_unwind to handle parser panics gracefully
426- let program = panic:: catch_unwind ( || Program :: compile ( & processed_src ) )
420+ let program = panic:: catch_unwind ( || Program :: compile ( & src ) )
427421 . map_err ( |_| {
422+ warn ! ( "CEL parser panic for expression: '{}'" , src) ;
428423 PyValueError :: new_err ( format ! (
429424 "Failed to parse expression '{src}': Invalid syntax or malformed string"
430425 ) )
@@ -445,7 +440,7 @@ fn evaluate(src: String, evaluation_context: Option<&Bound<'_, PyAny>>) -> PyRes
445440 // Register Python functions
446441 for ( function_name, py_function) in ctx. functions . iter ( ) {
447442 // Create a wrapper function
448- let py_func_clone = Python :: with_gil ( |py| py_function. clone_ref ( py) ) ;
443+ let py_func_clone = Python :: attach ( |py| py_function. clone_ref ( py) ) ;
449444 let func_name_clone = function_name. clone ( ) ;
450445
451446 // Register a function that takes Arguments (variadic) and returns a Value
@@ -455,7 +450,7 @@ fn evaluate(src: String, evaluation_context: Option<&Bound<'_, PyAny>>) -> PyRes
455450 let py_func = py_func_clone. clone ( ) ;
456451 let func_name = func_name_clone. clone ( ) ;
457452
458- Python :: with_gil ( |py| {
453+ Python :: attach ( |py| {
459454 // Convert CEL arguments to Python objects
460455 let mut py_args = Vec :: new ( ) ;
461456 for cel_value in args. 0 . iter ( ) {
@@ -479,6 +474,7 @@ fn evaluate(src: String, evaluation_context: Option<&Bound<'_, PyAny>>) -> PyRes
479474
480475 // Call the Python function
481476 let py_result = py_func. call1 ( py, py_args_tuple) . map_err ( |e| {
477+ warn ! ( "Python function '{}' failed: {}" , func_name, e) ;
482478 ExecutionError :: FunctionError {
483479 function : func_name. clone ( ) ,
484480 message : format ! ( "Python function call failed: {e}" ) ,
@@ -508,18 +504,14 @@ fn evaluate(src: String, evaluation_context: Option<&Bound<'_, PyAny>>) -> PyRes
508504 // AssertUnwindSafe is needed because the environment contains function closures
509505 let result =
510506 panic:: catch_unwind ( AssertUnwindSafe ( || program. execute ( & environment) ) ) . map_err ( |_| {
507+ warn ! ( "CEL execution panic for expression: '{}'" , src) ;
511508 PyValueError :: new_err ( format ! (
512509 "Failed to execute expression '{src}': Internal parser error"
513510 ) )
514511 } ) ?;
515512
516513 match result {
517- Err ( error) => {
518- debug ! ( "An error occurred during execution" ) ;
519- debug ! ( "Execution error: {error:?}" ) ;
520- Err ( map_execution_error_to_python ( & error) )
521- }
522-
514+ Err ( error) => Err ( map_execution_error_to_python ( & error) ) ,
523515 Ok ( value) => Ok ( RustyCelType ( value) ) ,
524516 }
525517}
0 commit comments