From 9ad1063b27e45c17e3664fe759f8cc89d4ee89c4 Mon Sep 17 00:00:00 2001 From: Icxolu <10486322+Icxolu@users.noreply.github.com> Date: Sat, 27 Sep 2025 12:06:26 +0200 Subject: [PATCH] update PyO3 0.27 --- CHANGELOG.md | 3 +++ Cargo.toml | 6 ++--- README.md | 32 ++++++++++------------ benches/array.rs | 4 +-- examples/linalg/Cargo.lock | 23 ++++++++-------- examples/linalg/Cargo.toml | 2 +- examples/linalg/src/lib.rs | 13 +++++---- examples/parallel/Cargo.toml | 2 +- examples/parallel/src/lib.rs | 13 +++++---- examples/simple/Cargo.toml | 2 +- examples/simple/src/lib.rs | 51 ++++++++++++++++-------------------- src/array_like.rs | 10 ++++--- src/borrow/mod.rs | 18 +++++++++---- src/sum_products.rs | 22 ++++++++-------- 14 files changed, 100 insertions(+), 101 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a316c7ab..a9d5a34f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ # Changelog +- v0.27.0 + - Bump PyO3 dependency to v0.27.0. ([#xxx](https://github.com/PyO3/rust-numpy/pull/xxx)) + - v0.26.0 - bump MSRV to 1.74, matching PyO3 ([#504](https://github.com/PyO3/rust-numpy/pull/504)) - extend supported `nalgebra` version to `0.34` ([#503](https://github.com/PyO3/rust-numpy/pull/503)) diff --git a/Cargo.toml b/Cargo.toml index e30f53051..1c15ff4a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "numpy" -version = "0.26.0" +version = "0.27.0" authors = [ "The rust-numpy Project Developers", "PyO3 Project and Contributors ", @@ -22,13 +22,13 @@ num-complex = ">= 0.2, < 0.5" num-integer = "0.1" num-traits = "0.2" ndarray = ">= 0.15, < 0.17" -pyo3 = { version = "0.26.0", default-features = false, features = ["macros"]} +pyo3 = { version = "0.26.0", default-features = false, features = ["macros"], path = "../pyo3"} rustc-hash = "2.0" [dev-dependencies] pyo3 = { version = "0.26.0", default-features = false, features = [ "auto-initialize", -] } +], path = "../pyo3" } nalgebra = { version = ">=0.30, <0.35", default-features = false, features = [ "std", ] } diff --git a/README.md b/README.md index f7401e8c1..bacdfd7a9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ rust-numpy =========== [![Actions Status](https://github.com/PyO3/rust-numpy/workflows/CI/badge.svg)](https://github.com/PyO3/rust-numpy/actions) [![Crate](https://img.shields.io/crates/v/numpy.svg)](https://crates.io/crates/numpy) -[![Minimum rustc 1.63](https://img.shields.io/badge/rustc-1.63+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) +[![Minimum rustc 1.74](https://img.shields.io/badge/rustc-1.74+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) [![Documentation](https://docs.rs/numpy/badge.svg)](https://docs.rs/numpy) [![codecov](https://codecov.io/gh/PyO3/rust-numpy/branch/main/graph/badge.svg)](https://codecov.io/gh/PyO3/rust-numpy) @@ -13,7 +13,7 @@ Rust bindings for the NumPy C-API. - [Current main](https://pyo3.github.io/rust-numpy) ## Requirements -- Rust >= 1.63.0 +- Rust >= 1.74.0 - Basically, our MSRV follows the one of [PyO3](https://github.com/PyO3/pyo3) - Python >= 3.7 - Python 3.6 support was dropped from 0.16 @@ -38,17 +38,17 @@ name = "rust_ext" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.22", features = ["extension-module"] } -numpy = "0.22" +pyo3 = { version = "0.27", features = ["extension-module"] } +numpy = "0.27" ``` ```rust -use numpy::ndarray::{ArrayD, ArrayViewD, ArrayViewMutD}; -use numpy::{IntoPyArray, PyArrayDyn, PyReadonlyArrayDyn, PyArrayMethods}; -use pyo3::{pymodule, types::PyModule, PyResult, Python, Bound}; +#[pyo3::pymodule] +mod rust_ext { + use numpy::ndarray::{ArrayD, ArrayViewD, ArrayViewMutD}; + use numpy::{IntoPyArray, PyArrayDyn, PyReadonlyArrayDyn, PyArrayMethods}; + use pyo3::{pyfunction, PyResult, Python, Bound}; -#[pymodule] -fn rust_ext<'py>(_py: Python<'py>, m: &Bound<'py, PyModule>) -> PyResult<()> { // example using immutable borrows producing a new array fn axpy(a: f64, x: ArrayViewD<'_, f64>, y: ArrayViewD<'_, f64>) -> ArrayD { a * &x + &y @@ -60,8 +60,7 @@ fn rust_ext<'py>(_py: Python<'py>, m: &Bound<'py, PyModule>) -> PyResult<()> { } // wrapper of `axpy` - #[pyfn(m)] - #[pyo3(name = "axpy")] + #[pyfunction(name = "axpy")] fn axpy_py<'py>( py: Python<'py>, a: f64, @@ -75,14 +74,11 @@ fn rust_ext<'py>(_py: Python<'py>, m: &Bound<'py, PyModule>) -> PyResult<()> { } // wrapper of `mult` - #[pyfn(m)] - #[pyo3(name = "mult")] + #[pyfunction(name = "mult")] fn mult_py<'py>(a: f64, x: &Bound<'py, PyArrayDyn>) { let x = unsafe { x.as_array_mut() }; mult(a, x); } - - Ok(()) } ``` @@ -93,8 +89,8 @@ fn rust_ext<'py>(_py: Python<'py>, m: &Bound<'py, PyModule>) -> PyResult<()> { name = "numpy-test" [dependencies] -pyo3 = { version = "0.22", features = ["auto-initialize"] } -numpy = "0.22" +pyo3 = { version = "0.27", features = ["auto-initialize"] } +numpy = "0.27" ``` ```rust @@ -132,7 +128,7 @@ on anything but that exact range. It can therefore be necessary to manually unif For example, if you specify the following dependencies ```toml -numpy = "0.22" +numpy = "0.27" ndarray = "0.15" ``` diff --git a/benches/array.rs b/benches/array.rs index 332e6295e..156a89c56 100644 --- a/benches/array.rs +++ b/benches/array.rs @@ -24,7 +24,7 @@ fn extract_success(bencher: &mut Bencher) { #[bench] fn extract_failure(bencher: &mut Bencher) { Python::attach(|py| { - let any = PyArray2::::zeros(py, (10, 10), false).into_any(); + let any = PyArray2::::zeros(py, (10, 10), false).into_any(); bencher.iter(|| { black_box(&any) @@ -46,7 +46,7 @@ fn cast_success(bencher: &mut Bencher) { #[bench] fn cast_failure(bencher: &mut Bencher) { Python::attach(|py| { - let any = PyArray2::::zeros(py, (10, 10), false).into_any(); + let any = PyArray2::::zeros(py, (10, 10), false).into_any(); bencher.iter(|| black_box(&any).cast::>().unwrap_err()); }); diff --git a/examples/linalg/Cargo.lock b/examples/linalg/Cargo.lock index 9c23c1e7f..7b6b62247 100644 --- a/examples/linalg/Cargo.lock +++ b/examples/linalg/Cargo.lock @@ -406,7 +406,7 @@ dependencies = [ "num-integer", "num-traits", "pyo3", - "pyo3-build-config", + "pyo3-build-config 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash", ] @@ -525,20 +525,25 @@ dependencies = [ [[package]] name = "pyo3" version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba0117f4212101ee6544044dae45abe1083d30ce7b29c4b5cbdfa2354e07383" dependencies = [ "indoc", "libc", "memoffset", "once_cell", "portable-atomic", - "pyo3-build-config", + "pyo3-build-config 0.26.0", "pyo3-ffi", "pyo3-macros", "unindent", ] +[[package]] +name = "pyo3-build-config" +version = "0.26.0" +dependencies = [ + "target-lexicon", +] + [[package]] name = "pyo3-build-config" version = "0.26.0" @@ -551,18 +556,14 @@ dependencies = [ [[package]] name = "pyo3-ffi" version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "025474d3928738efb38ac36d4744a74a400c901c7596199e20e45d98eb194105" dependencies = [ "libc", - "pyo3-build-config", + "pyo3-build-config 0.26.0", ] [[package]] name = "pyo3-macros" version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e64eb489f22fe1c95911b77c44cc41e7c19f3082fc81cce90f657cdc42ffded" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -573,12 +574,10 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "100246c0ecf400b475341b8455a9213344569af29a3c841d29270e53102e0fcf" dependencies = [ "heck", "proc-macro2", - "pyo3-build-config", + "pyo3-build-config 0.26.0", "quote", "syn", ] diff --git a/examples/linalg/Cargo.toml b/examples/linalg/Cargo.toml index 29888c7e0..7a47c9f65 100644 --- a/examples/linalg/Cargo.toml +++ b/examples/linalg/Cargo.toml @@ -9,7 +9,7 @@ name = "rust_linalg" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.26.0", features = ["extension-module"] } +pyo3 = { version = "0.26.0", features = ["extension-module"], path = "../../../pyo3" } numpy = { path = "../.." } ndarray-linalg = { version = "0.14.1", features = ["openblas-system"] } diff --git a/examples/linalg/src/lib.rs b/examples/linalg/src/lib.rs index 27b333edd..d5c91e04c 100755 --- a/examples/linalg/src/lib.rs +++ b/examples/linalg/src/lib.rs @@ -1,10 +1,10 @@ -use ndarray_linalg::solve::Inverse; -use numpy::{IntoPyArray, PyArray2, PyReadonlyArray2}; -use pyo3::{exceptions::PyRuntimeError, pymodule, types::PyModule, Bound, PyResult, Python}; +#[pyo3::pymodule] +mod rust_linalg { + use ndarray_linalg::solve::Inverse; + use numpy::{IntoPyArray, PyArray2, PyReadonlyArray2}; + use pyo3::{exceptions::PyRuntimeError, pyfunction, Bound, PyResult, Python}; -#[pymodule] -fn rust_linalg<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { - #[pyfn(m)] + #[pyfunction] fn inv<'py>( py: Python<'py>, x: PyReadonlyArray2<'py, f64>, @@ -15,5 +15,4 @@ fn rust_linalg<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { .map_err(|e| PyRuntimeError::new_err(e.to_string()))?; Ok(y.into_pyarray(py)) } - Ok(()) } diff --git a/examples/parallel/Cargo.toml b/examples/parallel/Cargo.toml index 969632e2d..0e38719f5 100644 --- a/examples/parallel/Cargo.toml +++ b/examples/parallel/Cargo.toml @@ -9,7 +9,7 @@ name = "rust_parallel" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.26.0", features = ["extension-module", "multiple-pymethods"] } +pyo3 = { version = "0.26.0", features = ["extension-module", "multiple-pymethods"], path = "../../../pyo3"} numpy = { path = "../.." } ndarray = { version = "0.16", features = ["rayon", "blas"] } blas-src = { version = "0.8", features = ["openblas"] } diff --git a/examples/parallel/src/lib.rs b/examples/parallel/src/lib.rs index b1adc1cae..955d58895 100755 --- a/examples/parallel/src/lib.rs +++ b/examples/parallel/src/lib.rs @@ -1,13 +1,13 @@ // We need to link `blas_src` directly, c.f. https://github.com/rust-ndarray/ndarray#how-to-enable-blas-integration extern crate blas_src; -use numpy::ndarray::Zip; -use numpy::{IntoPyArray, PyArray1, PyReadonlyArray1, PyReadonlyArray2}; -use pyo3::{pymodule, types::PyModule, Bound, PyResult, Python}; +#[pyo3::pymodule] +mod rust_parallel { + use numpy::ndarray::Zip; + use numpy::{IntoPyArray, PyArray1, PyReadonlyArray1, PyReadonlyArray2}; + use pyo3::{pyfunction, Bound, PyResult, Python}; -#[pymodule] -fn rust_parallel<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { - #[pyfn(m)] + #[pyfunction] fn rows_dot<'py>( py: Python<'py>, x: PyReadonlyArray2<'py, f64>, @@ -18,5 +18,4 @@ fn rust_parallel<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { let z = Zip::from(x.rows()).par_map_collect(|row| row.dot(&y)); z.into_pyarray(py) } - Ok(()) } diff --git a/examples/simple/Cargo.toml b/examples/simple/Cargo.toml index f67c69d9d..81c333329 100644 --- a/examples/simple/Cargo.toml +++ b/examples/simple/Cargo.toml @@ -9,7 +9,7 @@ name = "rust_ext" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.26.0", features = ["extension-module", "abi3-py37"] } +pyo3 = { version = "0.26.0", features = ["extension-module", "abi3-py37"], path = "../../../pyo3"} numpy = { path = "../.." } [workspace] diff --git a/examples/simple/src/lib.rs b/examples/simple/src/lib.rs index fd41372a1..a0f05ce06 100644 --- a/examples/simple/src/lib.rs +++ b/examples/simple/src/lib.rs @@ -1,20 +1,19 @@ -use std::ops::Add; +#[pyo3::pymodule] +mod rust_ext { + use numpy::ndarray::{Array1, ArrayD, ArrayView1, ArrayViewD, ArrayViewMutD, Zip}; + use numpy::{ + datetime::{units, Timedelta}, + Complex64, IntoPyArray, PyArray1, PyArrayDyn, PyArrayMethods, PyReadonlyArray1, + PyReadonlyArrayDyn, PyReadwriteArray1, PyReadwriteArrayDyn, + }; + use pyo3::{ + exceptions::PyIndexError, + pyfunction, + types::{PyDict, PyDictMethods}, + Bound, FromPyObject, Py, PyAny, PyResult, Python, + }; + use std::ops::Add; -use numpy::ndarray::{Array1, ArrayD, ArrayView1, ArrayViewD, ArrayViewMutD, Zip}; -use numpy::{ - datetime::{units, Timedelta}, - Complex64, IntoPyArray, PyArray1, PyArrayDyn, PyArrayMethods, PyReadonlyArray1, - PyReadonlyArrayDyn, PyReadwriteArray1, PyReadwriteArrayDyn, -}; -use pyo3::{ - exceptions::PyIndexError, - pymodule, - types::{PyDict, PyDictMethods, PyModule}, - Bound, FromPyObject, Py, PyAny, PyResult, Python, -}; - -#[pymodule] -fn rust_ext<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { // example using generic Py fn head(py: Python<'_>, x: ArrayViewD<'_, Py>) -> PyResult> { x.get(0) @@ -46,15 +45,13 @@ fn rust_ext<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { } // wrapper of `head` - #[pyfn(m)] - #[pyo3(name = "head")] + #[pyfunction(name = "head")] fn head_py<'py>(x: PyReadonlyArrayDyn<'py, Py>) -> PyResult> { head(x.py(), x.as_array()) } // wrapper of `axpy` - #[pyfn(m)] - #[pyo3(name = "axpy")] + #[pyfunction(name = "axpy")] fn axpy_py<'py>( py: Python<'py>, a: f64, @@ -68,16 +65,14 @@ fn rust_ext<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { } // wrapper of `mult` - #[pyfn(m)] - #[pyo3(name = "mult")] + #[pyfunction(name = "mult")] fn mult_py<'py>(a: f64, mut x: PyReadwriteArrayDyn<'py, f64>) { let x = x.as_array_mut(); mult(a, x); } // wrapper of `conj` - #[pyfn(m)] - #[pyo3(name = "conj")] + #[pyfunction(name = "conj")] fn conj_py<'py>( py: Python<'py>, x: PyReadonlyArrayDyn<'py, Complex64>, @@ -86,7 +81,7 @@ fn rust_ext<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { } // example of how to extract an array from a dictionary - #[pyfn(m)] + #[pyfunction] fn extract(d: &Bound<'_, PyDict>) -> f64 { let x = d .get_item("x") @@ -99,7 +94,7 @@ fn rust_ext<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { } // example using timedelta64 array - #[pyfn(m)] + #[pyfunction] fn add_minutes_to_seconds<'py>( mut x: PyReadwriteArray1<'py, Timedelta>, y: PyReadonlyArray1<'py, Timedelta>, @@ -121,7 +116,7 @@ fn rust_ext<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { I64(Bound<'py, PyArray1>), } - #[pyfn(m)] + #[pyfunction] fn polymorphic_add<'py>( x: SupportedArray<'py>, y: SupportedArray<'py>, @@ -151,6 +146,4 @@ fn rust_ext<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { } } } - - Ok(()) } diff --git a/src/array_like.rs b/src/array_like.rs index c00fb5de7..0419c1438 100644 --- a/src/array_like.rs +++ b/src/array_like.rs @@ -6,7 +6,7 @@ use pyo3::{ intern, sync::PyOnceLock, types::{PyAnyMethods, PyDict}, - Bound, FromPyObject, Py, PyAny, PyResult, + Borrowed, FromPyObject, Py, PyAny, PyErr, PyResult, }; use crate::array::PyArrayMethods; @@ -135,14 +135,16 @@ where } } -impl<'py, T, D, C> FromPyObject<'py> for PyArrayLike<'py, T, D, C> +impl<'a, 'py, T, D, C> FromPyObject<'a, 'py> for PyArrayLike<'py, T, D, C> where T: Element + 'py, D: Dimension + 'py, C: Coerce, - Vec: FromPyObject<'py>, + Vec: FromPyObject<'a, 'py>, { - fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { + type Error = PyErr; + + fn extract(ob: Borrowed<'a, 'py, PyAny>) -> PyResult { if let Ok(array) = ob.cast::>() { return Ok(Self(array.readonly(), PhantomData)); } diff --git a/src/borrow/mod.rs b/src/borrow/mod.rs index b3bf61950..0a75f1eb3 100644 --- a/src/borrow/mod.rs +++ b/src/borrow/mod.rs @@ -175,7 +175,7 @@ use std::ops::Deref; use ndarray::{ ArrayView, ArrayViewMut, Dimension, IntoDimension, Ix0, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn, }; -use pyo3::{Bound, FromPyObject, PyAny, PyResult}; +use pyo3::{Borrowed, Bound, DowncastError, FromPyObject, PyAny, PyResult}; use crate::array::{PyArray, PyArrayMethods}; use crate::convert::NpyIndex; @@ -237,8 +237,12 @@ where } } -impl<'py, T: Element, D: Dimension> FromPyObject<'py> for PyReadonlyArray<'py, T, D> { - fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { +impl<'a, 'py, T: Element + 'a, D: Dimension + 'a> FromPyObject<'a, 'py> + for PyReadonlyArray<'py, T, D> +{ + type Error = DowncastError<'a, 'py>; + + fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result { let array = obj.cast::>()?; Ok(array.readonly()) } @@ -476,8 +480,12 @@ where } } -impl<'py, T: Element, D: Dimension> FromPyObject<'py> for PyReadwriteArray<'py, T, D> { - fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { +impl<'a, 'py, T: Element + 'a, D: Dimension + 'a> FromPyObject<'a, 'py> + for PyReadwriteArray<'py, T, D> +{ + type Error = DowncastError<'a, 'py>; + + fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result { let array = obj.cast::>()?; Ok(array.readwrite()) } diff --git a/src/sum_products.rs b/src/sum_products.rs index ba18938a7..ced428abc 100644 --- a/src/sum_products.rs +++ b/src/sum_products.rs @@ -11,16 +11,16 @@ use crate::dtype::Element; use crate::npyffi::{array::PY_ARRAY_API, NPY_CASTING, NPY_ORDER}; /// Return value of a function that can yield either an array or a scalar. -pub trait ArrayOrScalar<'py, T>: FromPyObject<'py> {} +pub trait ArrayOrScalar<'a, 'py, T>: FromPyObject<'a, 'py> {} -impl<'py, T, D> ArrayOrScalar<'py, T> for Bound<'py, PyArray> +impl<'a, 'py, T, D> ArrayOrScalar<'a, 'py, T> for Bound<'py, PyArray> where - T: Element, - D: Dimension, + T: Element + 'a, + D: Dimension + 'a, { } -impl<'py, T> ArrayOrScalar<'py, T> for T where T: Element + FromPyObject<'py> {} +impl<'a, 'py, T> ArrayOrScalar<'a, 'py, T> for T where T: Element + FromPyObject<'a, 'py> {} /// Return the inner product of two arrays. /// @@ -64,14 +64,14 @@ where T: Element, DIN1: Dimension, DIN2: Dimension, - OUT: ArrayOrScalar<'py, T>, + OUT: for<'a> ArrayOrScalar<'a, 'py, T>, { let py = array1.py(); let obj = unsafe { let result = PY_ARRAY_API.PyArray_InnerProduct(py, array1.as_ptr(), array2.as_ptr()); Bound::from_owned_ptr_or_err(py, result)? }; - obj.extract() + obj.extract().map_err(Into::into) } /// Return the dot product of two arrays. @@ -122,14 +122,14 @@ where T: Element, DIN1: Dimension, DIN2: Dimension, - OUT: ArrayOrScalar<'py, T>, + OUT: for<'a> ArrayOrScalar<'a, 'py, T>, { let py = array1.py(); let obj = unsafe { let result = PY_ARRAY_API.PyArray_MatrixProduct(py, array1.as_ptr(), array2.as_ptr()); Bound::from_owned_ptr_or_err(py, result)? }; - obj.extract() + obj.extract().map_err(Into::into) } /// Return the Einstein summation convention of given tensors. @@ -141,7 +141,7 @@ pub fn einsum<'py, T, OUT>( ) -> PyResult where T: Element, - OUT: ArrayOrScalar<'py, T>, + OUT: for<'a> ArrayOrScalar<'a, 'py, T>, { let subscripts = match CStr::from_bytes_with_nul(subscripts.as_bytes()) { Ok(subscripts) => Cow::Borrowed(subscripts), @@ -162,7 +162,7 @@ where ); Bound::from_owned_ptr_or_err(py, result)? }; - obj.extract() + obj.extract().map_err(Into::into) } /// Return the Einstein summation convention of given tensors.