Skip to content

Commit adbbafd

Browse files
authored
Merge pull request #52 from ensignavenger/main
use pyo3 0.28.2 and support python 3.14 issue#51
2 parents e5d713e + e26d8ec commit adbbafd

2 files changed

Lines changed: 44 additions & 42 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ crate-type = ["cdylib"]
99

1010
[dependencies]
1111
biscuit-auth = { version = "6.0.0", features = ["pem"] }
12-
pyo3 = { version = "0.24.1", features = ["extension-module", "chrono"] }
12+
pyo3 = { version = "0.28.2", features = ["extension-module", "chrono"] }
1313
hex = "0.4"
1414
base64 = "0.13.0"
1515
chrono = "0.4"

src/lib.rs

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use ::biscuit_auth::{
3131
use pyo3::exceptions::PyValueError;
3232
use pyo3::prelude::*;
3333
use pyo3::types::*;
34+
use pyo3::IntoPyObjectExt;
3435

3536
use 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)]
6666
pub enum PyAlgorithm {
6767
Ed25519,
@@ -86,12 +86,12 @@ impl From<PyAlgorithm> for builder::Algorithm {
8686
}
8787

8888
struct PyKeyProvider {
89-
py_value: PyObject,
89+
py_value: Py<PyAny>,
9090
}
9191

9292
impl 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")]
471471
pub struct PyAuthorizerBuilder(Option<AuthorizerBuilder>);
472472

473-
#[pyclass(name = "AuthorizerLimits")]
473+
#[pyclass(name = "AuthorizerLimits", from_py_object)]
474474
#[derive(Clone)]
475475
pub 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)]
925925
pub 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)]
11501150
pub 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)]
12301230
pub 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
13181317
fn 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

13351333
fn 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

13501348
impl 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+
14001402
impl 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

Comments
 (0)