diff --git a/.github/workflows/test_python.yml b/.github/workflows/test_python.yml index ca6ced5..be955f8 100644 --- a/.github/workflows/test_python.yml +++ b/.github/workflows/test_python.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - uses: actions/checkout@v4 diff --git a/Cargo.toml b/Cargo.toml index 8aa2dd7..2733625 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,8 +32,8 @@ ndarray = { version = "0.16", optional = true } ## Use dynamic or static arrays from the [nalgebra] crate as value of a quantity. nalgebra = { version = "0.34", optional = true } approx = { version = "0.5", optional = true } -pyo3 = { version = "0.26", optional = true } -numpy = { version = "0.26", optional = true } +pyo3 = { version = "0.27", optional = true } +numpy = { version = "0.27", optional = true } num-dual = { version = "0.12", optional = true } [features] @@ -46,3 +46,4 @@ python = ["pyo3"] python_numpy = ["python", "numpy/nalgebra", "ndarray", "nalgebra"] ## Enable approximate comparisons through the [approx] crate. approx = ["dep:approx", "ndarray?/approx"] + diff --git a/example/extend_quantity/Cargo.toml b/example/extend_quantity/Cargo.toml index 31fd5de..fac6699 100644 --- a/example/extend_quantity/Cargo.toml +++ b/example/extend_quantity/Cargo.toml @@ -8,7 +8,7 @@ name = "extend_quantity" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.26", features = ["extension-module", "abi3-py39"] } +pyo3 = { version = "0.27", features = ["extension-module", "abi3-py310"] } quantity = { version = "*", path = "../../", features = ["python_numpy"] } ndarray = "0.16" nalgebra = "0.34" \ No newline at end of file diff --git a/si-units/Cargo.toml b/si-units/Cargo.toml index ca2dae0..1af780b 100644 --- a/si-units/Cargo.toml +++ b/si-units/Cargo.toml @@ -22,7 +22,7 @@ crate-type = ["cdylib"] [dependencies] ndarray = "0.16" -numpy = "0.26" -pyo3 = { version = "0.26", features = ["extension-module", "abi3-py39"] } -regex = "1.11" +numpy = "0.27" +pyo3 = { version = "0.27", features = ["extension-module", "abi3-py310"] } +regex = "1.12" thiserror = "2.0" diff --git a/si-units/src/lib.rs b/si-units/src/lib.rs index 39ed6c6..2243325 100644 --- a/si-units/src/lib.rs +++ b/si-units/src/lib.rs @@ -1,6 +1,6 @@ #![warn(clippy::all)] #![allow(non_snake_case)] -use ndarray::{arr1, Array1}; +use ndarray::{Array1, arr1}; use numpy::IntoPyArray; use pyo3::basic::CompareOp; use pyo3::exceptions::PyRuntimeError; @@ -150,7 +150,7 @@ impl PySIObject { } fn __mul__<'py>(&self, rhs: &Bound<'py, PyAny>) -> PyResult> { - let (rhs_value, unit) = if let Ok(r) = rhs.downcast::().map(Bound::get) { + let (rhs_value, unit) = if let Ok(r) = rhs.cast::().map(Bound::get) { (r.value.bind(rhs.py()).clone(), self.unit * r.unit) } else { (rhs.clone(), self.unit) @@ -166,7 +166,7 @@ impl PySIObject { } fn __rmul__<'py>(&self, lhs: &Bound<'py, PyAny>) -> PyResult> { - let (lhs_value, unit) = if let Ok(l) = lhs.downcast::().map(Bound::get) { + let (lhs_value, unit) = if let Ok(l) = lhs.cast::().map(Bound::get) { (l.value.bind(lhs.py()).clone(), l.unit * self.unit) } else { (lhs.clone(), self.unit) @@ -182,9 +182,9 @@ impl PySIObject { } fn __truediv__<'py>(&self, rhs: &Bound<'py, PyAny>) -> PyResult> { - let (rhs_value, unit) = if let Ok(r) = rhs.downcast::().map(Bound::get) { + let (rhs_value, unit) = if let Ok(r) = rhs.cast::().map(Bound::get) { (r.value.bind(rhs.py()).clone(), self.unit / r.unit) - } else if rhs.downcast::().is_ok() { + } else if rhs.cast::().is_ok() { return if self.unit == _KELVIN { let delta = PyFloat::new(rhs.py(), 273.15); self.value.bind(rhs.py()).call_method1("__sub__", (&delta,)) @@ -208,7 +208,7 @@ impl PySIObject { } fn __rtruediv__<'py>(&self, lhs: &Bound<'py, PyAny>) -> PyResult> { - let (lhs_value, unit) = if let Ok(l) = lhs.downcast::().map(Bound::get) { + let (lhs_value, unit) = if let Ok(l) = lhs.cast::().map(Bound::get) { (l.value.bind(lhs.py()).clone(), l.unit / self.unit) } else { (lhs.clone(), self.unit.recip()) @@ -283,10 +283,11 @@ impl SIObject { } } -impl<'py> FromPyObject<'py> for SINumber { - fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { +impl<'py> FromPyObject<'_, 'py> for SINumber { + type Error = PyErr; + fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult { let py = ob.py(); - let ob = ob.downcast::()?.borrow(); + let ob = ob.cast::()?.borrow(); let value = ob.value.extract::(py)?; let unit = ob.unit; Ok(SINumber { value, unit }) @@ -317,7 +318,7 @@ fn array(value: Bound<'_, PyAny>) -> PyResult> { let value = value.into_pyarray(py).into_any().unbind(); Bound::new(py, PySIObject::new(value, unit)) } else { - Ok(value.downcast_into::()?) + Ok(value.cast_into::()?) } } diff --git a/src/python.rs b/src/python.rs index c1d145c..45551b9 100644 --- a/src/python.rs +++ b/src/python.rs @@ -92,11 +92,12 @@ impl<'py, T: Integer, L: Integer, M: Integer, I: Integer, THETA: Integer, N: Int } impl<'py, T: Integer, L: Integer, M: Integer, I: Integer, THETA: Integer, N: Integer, J: Integer> - FromPyObject<'py> for Quantity> + FromPyObject<'_, 'py> for Quantity> where Self: PrintUnit, { - fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { + type Error = PyErr; + fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult { let Ok((value, unit_from)) = ob .call_method0("__getnewargs__") .and_then(|raw| raw.extract::<(f64, [i8; 7])>()) @@ -131,11 +132,12 @@ impl< N: Integer, J: Integer, D: Dimension, -> FromPyObject<'py> for Quantity, SIUnit> +> FromPyObject<'_, 'py> for Quantity, SIUnit> where Self: PrintUnit, { - fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { + type Error = PyErr; + fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult { let Ok((value, unit_from)) = ob .call_method0("__getnewargs__") .and_then(|raw| raw.extract::<(PyReadonlyArray, [i8; 7])>()) @@ -162,11 +164,12 @@ where #[cfg(feature = "nalgebra")] impl<'py, T: Integer, L: Integer, M: Integer, I: Integer, THETA: Integer, N: Integer, J: Integer> - FromPyObject<'py> for Quantity, SIUnit> + FromPyObject<'_, 'py> for Quantity, SIUnit> where Self: PrintUnit, { - fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { + type Error = PyErr; + fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult { let Ok((value, unit_from)) = ob.call_method0("__getnewargs__").and_then(|raw| { raw.extract::<(PyReadonlyArray1, [i8; 7])>() .map(|(m, u)| { @@ -195,11 +198,12 @@ where #[cfg(feature = "nalgebra")] impl<'py, T: Integer, L: Integer, M: Integer, I: Integer, THETA: Integer, N: Integer, J: Integer> - FromPyObject<'py> for Quantity, SIUnit> + FromPyObject<'_, 'py> for Quantity, SIUnit> where Self: PrintUnit, { - fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { + type Error = PyErr; + fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult { let Ok((value, unit_from)) = ob.call_method0("__getnewargs__").and_then(|raw| { raw.extract::<(PyReadonlyArray2, [i8; 7])>() .map(|(m, u)| { @@ -245,8 +249,10 @@ impl<'py> IntoPyObject<'py> for Angle { } } -impl<'py> FromPyObject<'py> for Angle { - fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { +impl<'py> FromPyObject<'_, 'py> for Angle { + type Error = PyErr; + + fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult { let Ok(value) = ob .call_method0("__getnewargs__") .and_then(|raw| raw.extract::())