@@ -5,10 +5,11 @@ use cel_interpreter::{ExecutionError, Program, Value};
55use log:: { debug, warn} ;
66use pyo3:: exceptions:: PyValueError ;
77use pyo3:: prelude:: * ;
8+ use pyo3:: BoundObject ;
89use std:: panic;
910
1011use chrono:: { DateTime , Duration as ChronoDuration , Offset , TimeZone } ;
11- use pyo3:: types:: { PyBytes , PyDict , PyList , PyTuple } ;
12+ use pyo3:: types:: { PyBool , PyBytes , PyDict , PyList , PyTuple } ;
1213
1314use std:: collections:: HashMap ;
1415use std:: error:: Error ;
@@ -18,57 +19,62 @@ use std::sync::Arc;
1819#[ derive( Debug ) ]
1920struct RustyCelType ( Value ) ;
2021
21- impl IntoPy < PyObject > for RustyCelType {
22- fn into_py ( self , py : Python < ' _ > ) -> PyObject {
23- // Just use the native rust type's existing
24- // IntoPy implementation
25- match self {
22+ impl < ' py > IntoPyObject < ' py > for RustyCelType {
23+ type Target = PyAny ;
24+ type Output = Bound < ' py , Self :: Target > ;
25+ type Error = PyErr ;
26+
27+ fn into_pyobject ( self , py : Python < ' py > ) -> Result < Self :: Output , Self :: Error > {
28+ let obj = match self {
2629 // Primitive Types
27- RustyCelType ( Value :: Null ) => py. None ( ) ,
28- RustyCelType ( Value :: Bool ( b) ) => b. into_py ( py) ,
29- RustyCelType ( Value :: Int ( i64) ) => i64. into_py ( py) ,
30- RustyCelType ( Value :: UInt ( u64) ) => u64. into_py ( py) ,
31- RustyCelType ( Value :: Float ( f) ) => f. into_py ( py) ,
30+ RustyCelType ( Value :: Null ) => py. None ( ) . into_bound ( py) ,
31+ RustyCelType ( Value :: Bool ( b) ) => {
32+ PyBool :: new ( py, b) . into_bound ( ) . into_any ( )
33+ }
34+ RustyCelType ( Value :: Int ( i64) ) => i64. into_pyobject ( py) ?. into_any ( ) ,
35+ RustyCelType ( Value :: UInt ( u64) ) => u64. into_pyobject ( py) ?. into_any ( ) ,
36+ RustyCelType ( Value :: Float ( f) ) => f. into_pyobject ( py) ?. into_any ( ) ,
3237 RustyCelType ( Value :: Timestamp ( ts) ) => {
3338 debug ! ( "Converting a fixed offset datetime to python type" ) ;
34- ts. into_py ( py)
39+ ts. into_pyobject ( py) ? . into_any ( )
3540 }
36- RustyCelType ( Value :: Duration ( d) ) => d. into_py ( py) ,
37- RustyCelType ( Value :: String ( s) ) => s. as_ref ( ) . to_string ( ) . into_py ( py) ,
41+ RustyCelType ( Value :: Duration ( d) ) => d. into_pyobject ( py) ? . into_any ( ) ,
42+ RustyCelType ( Value :: String ( s) ) => s. as_ref ( ) . to_string ( ) . into_pyobject ( py) ? . into_any ( ) ,
3843 RustyCelType ( Value :: List ( val) ) => {
39- let list = val
40- . as_ref ( )
41- . into_iter ( )
42- . map ( |v| RustyCelType ( v . clone ( ) ) . into_py ( py ) )
43- . collect :: < Vec < PyObject > > ( ) ;
44- list. into_py ( py )
44+ let list = PyList :: empty ( py ) ;
45+ for v in val . as_ref ( ) . into_iter ( ) {
46+ let item = RustyCelType ( v . clone ( ) ) . into_pyobject ( py ) ? ;
47+ list . append ( & item ) ? ;
48+ }
49+ list. into_any ( )
4550 }
46- RustyCelType ( Value :: Bytes ( val) ) => PyBytes :: new_bound ( py, & val) . into_py ( py ) ,
51+ RustyCelType ( Value :: Bytes ( val) ) => PyBytes :: new ( py, & val) . into_any ( ) ,
4752
4853 RustyCelType ( Value :: Map ( val) ) => {
4954 // Create a PyDict with the converted Python key and values.
50- let python_dict = PyDict :: new_bound ( py) ;
55+ let python_dict = PyDict :: new ( py) ;
5156
52- val. map . as_ref ( ) . into_iter ( ) . for_each ( | ( k , v ) | {
57+ for ( k , v ) in val. map . as_ref ( ) . into_iter ( ) {
5358 // Key is an enum with String, Uint, Int and Bool variants. Value is any RustyCelType
5459 let key = match k {
55- Key :: String ( s) => s. as_ref ( ) . into_py ( py) ,
56- Key :: Uint ( u64) => u64. into_py ( py) ,
57- Key :: Int ( i64) => i64. into_py ( py) ,
58- Key :: Bool ( b) => b. into_py ( py) ,
60+ Key :: String ( s) => s. as_ref ( ) . into_pyobject ( py) ?. into_any ( ) ,
61+ Key :: Uint ( u64) => u64. into_pyobject ( py) ?. into_any ( ) ,
62+ Key :: Int ( i64) => i64. into_pyobject ( py) ?. into_any ( ) ,
63+ Key :: Bool ( b) => {
64+ PyBool :: new ( py, * b) . into_bound ( ) . into_any ( )
65+ }
5966 } ;
60- let value = RustyCelType ( v. clone ( ) ) . into_py ( py) ;
61- python_dict
62- . set_item ( key, value)
63- . expect ( "Failed to set item in Python dict" ) ;
64- } ) ;
67+ let value = RustyCelType ( v. clone ( ) ) . into_pyobject ( py) ?;
68+ python_dict. set_item ( & key, & value) ?;
69+ }
6570
66- python_dict. into ( )
71+ python_dict. into_any ( )
6772 }
6873
6974 // Turn everything else into a String:
70- nonprimitive => format ! ( "{:?}" , nonprimitive) . into_py ( py) ,
71- }
75+ nonprimitive => format ! ( "{:?}" , nonprimitive) . into_pyobject ( py) ?. into_any ( ) ,
76+ } ;
77+ Ok ( obj)
7278 }
7379}
7480
@@ -435,10 +441,13 @@ fn evaluate(src: String, evaluation_context: Option<&Bound<'_, PyAny>>) -> PyRes
435441 let mut py_args = Vec :: new ( ) ;
436442 for arg_expr in & ftx. args {
437443 let arg_value = ftx. ptx . resolve ( arg_expr) ?;
438- let py_arg = RustyCelType ( arg_value) . into_py ( py) ;
444+ let py_arg = RustyCelType ( arg_value) . into_pyobject ( py)
445+ . map_err ( |e| ExecutionError :: function_error ( "argument_conversion" , format ! ( "Failed to convert argument: {}" , e) ) ) ?
446+ . into_any ( ) . unbind ( ) ;
439447 py_args. push ( py_arg) ;
440448 }
441- let py_args = PyTuple :: new_bound ( py, py_args) ;
449+ let py_args = PyTuple :: new ( py, py_args)
450+ . map_err ( |e| ExecutionError :: function_error ( "tuple_creation" , format ! ( "Failed to create tuple: {}" , e) ) ) ?;
442451
443452 // Call the Python function
444453 let py_result = py_function. call1 ( py, py_args) . map_err ( |e| {
0 commit comments