@@ -31,6 +31,7 @@ use ::biscuit_auth::{
3131use pyo3:: exceptions:: PyValueError ;
3232use pyo3:: prelude:: * ;
3333use pyo3:: types:: * ;
34+ use pyo3:: IntoPyObjectExt ;
3435
3536use pyo3:: create_exception;
3637
@@ -60,8 +61,7 @@ create_exception!(
6061 BiscuitBlockError ,
6162 pyo3:: exceptions:: PyException
6263) ;
63-
64- #[ pyclass( eq, eq_int, name = "Algorithm" ) ]
64+ #[ pyclass( eq, eq_int, name = "Algorithm" , from_py_object) ]
6565#[ derive( PartialEq , Eq , Clone , Copy ) ]
6666pub enum PyAlgorithm {
6767 Ed25519 ,
@@ -86,12 +86,12 @@ impl From<PyAlgorithm> for builder::Algorithm {
8686}
8787
8888struct PyKeyProvider {
89- py_value : PyObject ,
89+ py_value : Py < PyAny > ,
9090}
9191
9292impl RootKeyProvider for PyKeyProvider {
9393 fn choose ( & self , kid : Option < u32 > ) -> Result < PublicKey , error:: Format > {
94- Python :: with_gil ( |py| {
94+ Python :: attach ( |py| {
9595 let bound = self . py_value . bind ( py) ;
9696 if bound. is_callable ( ) {
9797 let result = bound
@@ -322,7 +322,7 @@ impl PyBiscuit {
322322 /// :return: the parsed and verified biscuit
323323 /// :rtype: Biscuit
324324 #[ classmethod]
325- pub fn from_bytes ( _: & Bound < PyType > , data : & [ u8 ] , root : PyObject ) -> PyResult < PyBiscuit > {
325+ pub fn from_bytes ( _: & Bound < PyType > , data : & [ u8 ] , root : Py < PyAny > ) -> PyResult < PyBiscuit > {
326326 match Biscuit :: from ( data, PyKeyProvider { py_value : root } ) {
327327 Ok ( biscuit) => Ok ( PyBiscuit ( biscuit) ) ,
328328 Err ( error) => Err ( BiscuitValidationError :: new_err ( error. to_string ( ) ) ) ,
@@ -340,7 +340,7 @@ impl PyBiscuit {
340340 /// :return: the parsed and verified biscuit
341341 /// :rtype: Biscuit
342342 #[ classmethod]
343- pub fn from_base64 ( _: & Bound < PyType > , data : & str , root : PyObject ) -> PyResult < PyBiscuit > {
343+ pub fn from_base64 ( _: & Bound < PyType > , data : & str , root : Py < PyAny > ) -> PyResult < PyBiscuit > {
344344 match Biscuit :: from_base64 ( data, PyKeyProvider { py_value : root } ) {
345345 Ok ( biscuit) => Ok ( PyBiscuit ( biscuit) ) ,
346346 Err ( error) => Err ( BiscuitValidationError :: new_err ( error. to_string ( ) ) ) ,
@@ -470,7 +470,7 @@ impl PyBiscuit {
470470#[ pyclass( name = "AuthorizerBuilder" ) ]
471471pub struct PyAuthorizerBuilder ( Option < AuthorizerBuilder > ) ;
472472
473- #[ pyclass( name = "AuthorizerLimits" ) ]
473+ #[ pyclass( name = "AuthorizerLimits" , from_py_object ) ]
474474#[ derive( Clone ) ]
475475pub struct PyAuthorizerLimits {
476476 #[ pyo3( get, set) ]
@@ -682,15 +682,15 @@ impl PyAuthorizerBuilder {
682682 Ok ( ( ) )
683683 }
684684
685- pub fn register_extern_func ( & mut self , name : & str , func : PyObject ) -> PyResult < ( ) > {
685+ pub fn register_extern_func ( & mut self , name : & str , func : Py < PyAny > ) -> PyResult < ( ) > {
686686 self . 0 = Some (
687687 self . 0
688688 . take ( )
689689 . expect ( "builder already consumed" )
690690 . register_extern_func (
691691 name. to_string ( ) ,
692692 ExternFunc :: new ( Arc :: new ( move |left, right| {
693- Python :: with_gil ( |py| {
693+ Python :: attach ( |py| {
694694 let bound = func. bind ( py) ;
695695 if bound. is_callable ( ) {
696696 let left = term_to_py ( & left) . map_err ( |e| e. to_string ( ) ) ?;
@@ -703,8 +703,8 @@ impl PyAuthorizerBuilder {
703703 None => bound. call1 ( ( left, ) ) . map_err ( |e| e. to_string ( ) ) ?,
704704 } ;
705705 let py_result: PyTerm =
706- result. extract ( ) . map_err ( |e| e. to_string ( ) ) ?;
707- Ok ( py_result. to_term ( ) . map_err ( |e| e. to_string ( ) ) ?)
706+ result. extract ( ) . map_err ( |e : PyErr | e. to_string ( ) ) ?;
707+ Ok ( py_result. to_term ( ) . map_err ( |e : PyErr | e. to_string ( ) ) ?)
708708 } else {
709709 Err ( "expected a function" . to_string ( ) )
710710 }
@@ -715,15 +715,15 @@ impl PyAuthorizerBuilder {
715715 Ok ( ( ) )
716716 }
717717
718- pub fn register_extern_funcs ( & mut self , funcs : HashMap < String , PyObject > ) -> PyResult < ( ) > {
718+ pub fn register_extern_funcs ( & mut self , funcs : HashMap < String , Py < PyAny > > ) -> PyResult < ( ) > {
719719 for ( name, func) in funcs {
720720 self . register_extern_func ( & name, func) ?;
721721 }
722722
723723 Ok ( ( ) )
724724 }
725725
726- pub fn set_extern_funcs ( & mut self , funcs : HashMap < String , PyObject > ) -> PyResult < ( ) > {
726+ pub fn set_extern_funcs ( & mut self , funcs : HashMap < String , Py < PyAny > > ) -> PyResult < ( ) > {
727727 self . 0 = Some (
728728 self . 0
729729 . take ( )
@@ -920,7 +920,7 @@ impl PyAuthorizer {
920920/// :type parameters: dict, optional
921921/// :param scope_parameters: public keys for the public key parameters in the datalog snippet
922922/// :type scope_parameters: dict, optional
923- #[ pyclass( name = "BlockBuilder" ) ]
923+ #[ pyclass( name = "BlockBuilder" , from_py_object ) ]
924924#[ derive( Clone ) ]
925925pub struct PyBlockBuilder ( Option < builder:: BlockBuilder > ) ;
926926
@@ -1146,7 +1146,7 @@ impl Default for PyKeyPair {
11461146
11471147/// ed25519 public key
11481148#[ derive( Clone ) ]
1149- #[ pyclass( name = "PublicKey" ) ]
1149+ #[ pyclass( name = "PublicKey" , from_py_object ) ]
11501150pub struct PyPublicKey ( PublicKey ) ;
11511151
11521152#[ pymethods]
@@ -1225,7 +1225,7 @@ impl PyPublicKey {
12251225}
12261226
12271227/// ed25519 private key
1228- #[ pyclass( name = "PrivateKey" ) ]
1228+ #[ pyclass( name = "PrivateKey" , from_py_object ) ]
12291229#[ derive( Clone ) ]
12301230pub struct PyPrivateKey ( PrivateKey ) ;
12311231
@@ -1314,26 +1314,24 @@ pub enum NestedPyTerm {
13141314 Bytes ( Vec < u8 > ) ,
13151315}
13161316
1317- // TODO follow up-to-date conversion methods from pyo3
13181317fn inner_term_to_py ( t : & builder:: Term , py : Python < ' _ > ) -> PyResult < Py < PyAny > > {
13191318 match t {
1320- builder:: Term :: Integer ( i) => Ok ( ( * i) . into_pyobject ( py) . unwrap ( ) . into_any ( ) . unbind ( ) ) ,
1321- builder:: Term :: Str ( s) => Ok ( s. into_pyobject ( py) . unwrap ( ) . into_any ( ) . unbind ( ) ) ,
1322- builder:: Term :: Date ( d) => Ok ( Utc
1323- . timestamp_opt ( * d as i64 , 0 )
1324- . unwrap ( )
1325- . into_pyobject ( py)
1326- . unwrap ( )
1327- . into_any ( )
1328- . unbind ( ) ) ,
1329- builder:: Term :: Bytes ( bs) => Ok ( bs. clone ( ) . into_pyobject ( py) . unwrap ( ) . into_any ( ) . unbind ( ) ) ,
1330- builder:: Term :: Bool ( b) => Ok ( b. into_py ( py) ) ,
1319+ builder:: Term :: Integer ( i) => ( * i) . into_py_any ( py) ,
1320+ builder:: Term :: Str ( s) => s. into_py_any ( py) ,
1321+ builder:: Term :: Date ( d) => {
1322+ Utc . timestamp_opt ( * d as i64 , 0 )
1323+ . single ( )
1324+ . ok_or_else ( || DataLogError :: new_err ( "Invalid timestamp" . to_string ( ) ) ) ?
1325+ . into_py_any ( py)
1326+ }
1327+ builder:: Term :: Bytes ( bs) => bs. clone ( ) . into_py_any ( py) ,
1328+ builder:: Term :: Bool ( b) => ( * b) . into_py_any ( py) ,
13311329 _ => Err ( DataLogError :: new_err ( "Invalid term value" . to_string ( ) ) ) ,
13321330 }
13331331}
13341332
13351333fn term_to_py ( t : & builder:: Term ) -> PyResult < Py < PyAny > > {
1336- Python :: with_gil ( |py| match t {
1334+ Python :: attach ( |py| match t {
13371335 builder:: Term :: Parameter ( _) => Err ( DataLogError :: new_err ( "Invalid term value" . to_string ( ) ) ) ,
13381336 builder:: Term :: Variable ( _) => Err ( DataLogError :: new_err ( "Invalid term value" . to_string ( ) ) ) ,
13391337 builder:: Term :: Set ( _vs) => todo ! ( ) ,
@@ -1345,7 +1343,7 @@ fn term_to_py(t: &builder::Term) -> PyResult<Py<PyAny>> {
13451343
13461344/// Wrapper for a non-naïve python date
13471345#[ derive( FromPyObject ) ]
1348- pub struct PyDate ( Py < PyDateTime > ) ;
1346+ pub struct PyDate ( pub Py < PyDateTime > ) ;
13491347
13501348impl PartialEq for PyDate {
13511349 fn eq ( & self , other : & Self ) -> bool {
@@ -1384,19 +1382,23 @@ impl NestedPyTerm {
13841382 NestedPyTerm :: Str ( s) => Ok ( builder:: Term :: Str ( s. to_string ( ) ) ) ,
13851383 NestedPyTerm :: Bytes ( b) => Ok ( b. clone ( ) . into ( ) ) ,
13861384 NestedPyTerm :: Bool ( b) => Ok ( ( * b) . into ( ) ) ,
1387- NestedPyTerm :: Date ( PyDate ( d) ) => Python :: with_gil ( |py| {
1388- let ts = d. extract :: < DateTime < Utc > > ( py) ?. timestamp ( ) ;
1389- if ts < 0 {
1390- return Err ( PyValueError :: new_err (
1391- "Only positive timestamps are available" . to_string ( ) ,
1392- ) ) ;
1393- }
1394- Ok ( builder:: Term :: Date ( ts as u64 ) )
1395- } ) ,
1385+ NestedPyTerm :: Date ( PyDate ( py_date) ) => {
1386+ Python :: attach ( |py| {
1387+ let dt: chrono:: DateTime < chrono:: Utc > = py_date. extract ( py) ?;
1388+ let ts = dt. timestamp ( ) ;
1389+ if ts < 0 {
1390+ return Err ( PyValueError :: new_err (
1391+ "Only positive timestamps supported" ,
1392+ ) ) ;
1393+ }
1394+ Ok ( builder:: Term :: Date ( ts as u64 ) )
1395+ } )
1396+ }
13961397 }
13971398 }
13981399}
13991400
1401+
14001402impl PyTerm {
14011403 pub fn to_term ( & self ) -> PyResult < builder:: Term > {
14021404 match self {
@@ -1460,7 +1462,7 @@ impl PyFact {
14601462
14611463 /// The fact terms
14621464 #[ getter]
1463- pub fn terms ( & self ) -> PyResult < Vec < PyObject > > {
1465+ pub fn terms ( & self ) -> PyResult < Vec < Py < PyAny > > > {
14641466 self . 0 . predicate . terms . iter ( ) . map ( term_to_py) . collect ( )
14651467 }
14661468
@@ -1681,7 +1683,7 @@ impl PyUnverifiedBiscuit {
16811683 . collect ( )
16821684 }
16831685
1684- pub fn verify ( & self , root : PyObject ) -> PyResult < PyBiscuit > {
1686+ pub fn verify ( & self , root : Py < PyAny > ) -> PyResult < PyBiscuit > {
16851687 Ok ( PyBiscuit (
16861688 self . 0
16871689 . clone ( )
0 commit comments