From 0b39d09ee305f18758f30a20602e684a6062acb5 Mon Sep 17 00:00:00 2001 From: Icxolu <10486322+Icxolu@users.noreply.github.com> Date: Tue, 5 Mar 2024 21:46:04 +0100 Subject: [PATCH] disable `gil-refs` feature --- Cargo.toml | 4 +- README.md | 14 ++--- examples/simple/src/lib.rs | 14 ++--- src/array.rs | 37 +++++++------- src/array_like.rs | 6 +-- src/borrow/shared.rs | 24 ++++----- src/datetime.rs | 36 ++++++------- src/dtype.rs | 42 +++++++-------- tests/array.rs | 102 +++++++++++++++++++------------------ tests/array_like.rs | 34 +++++++------ tests/borrow.rs | 20 +++++--- tests/to_py.rs | 18 +++---- 12 files changed, 181 insertions(+), 170 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 28b5b335f..243713bca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,11 +22,11 @@ num-complex = ">= 0.2, < 0.5" num-integer = "0.1" num-traits = "0.2" ndarray = ">= 0.13, < 0.16" -pyo3 = { version = "0.21.0", default-features = false, features = ["gil-refs", "macros"] } +pyo3 = { version = "0.21.0", default-features = false, features = ["macros"] } rustc-hash = "1.1" [dev-dependencies] -pyo3 = { version = "0.21.0", default-features = false, features = ["auto-initialize", "gil-refs"] } +pyo3 = { version = "0.21.0", default-features = false, features = ["auto-initialize"] } nalgebra = { version = "0.32", default-features = false, features = ["std"] } [package.metadata.docs.rs] diff --git a/README.md b/README.md index 9ef05624e..670df3377 100644 --- a/README.md +++ b/README.md @@ -98,17 +98,17 @@ numpy = "0.20" ``` ```rust -use numpy::PyArray1; -use pyo3::{types::IntoPyDict, PyResult, Python}; +use numpy::{PyArray1, PyArrayMethods}; +use pyo3::{types::{IntoPyDict, PyAnyMethods}, PyResult, Python}; fn main() -> PyResult<()> { Python::with_gil(|py| { - let np = py.import("numpy")?; - let locals = [("np", np)].into_py_dict(py); + let np = py.import_bound("numpy")?; + let locals = [("np", np)].into_py_dict_bound(py); - let pyarray: &PyArray1 = py - .eval("np.absolute(np.array([-1, -2, -3], dtype='int32'))", Some(locals), None)? - .extract()?; + let pyarray = py + .eval_bound("np.absolute(np.array([-1, -2, -3], dtype='int32'))", Some(&locals), None)? + .downcast_into::>()?; let readonly = pyarray.readonly(); let slice = readonly.as_slice()?; diff --git a/examples/simple/src/lib.rs b/examples/simple/src/lib.rs index a1d22bc1f..33c61557a 100644 --- a/examples/simple/src/lib.rs +++ b/examples/simple/src/lib.rs @@ -3,13 +3,13 @@ use std::ops::Add; use numpy::ndarray::{Array1, ArrayD, ArrayView1, ArrayViewD, ArrayViewMutD, Zip}; use numpy::{ datetime::{units, Timedelta}, - Complex64, IntoPyArray, PyArray1, PyArrayDyn, PyReadonlyArray1, PyReadonlyArrayDyn, - PyReadwriteArray1, PyReadwriteArrayDyn, + Complex64, IntoPyArray, PyArray1, PyArrayDyn, PyArrayMethods, PyReadonlyArray1, + PyReadonlyArrayDyn, PyReadwriteArray1, PyReadwriteArrayDyn, }; use pyo3::{ exceptions::PyIndexError, pymodule, - types::{PyDict, PyModule}, + types::{PyAnyMethods, PyDict, PyDictMethods, PyModule}, Bound, FromPyObject, PyAny, PyObject, PyResult, Python, }; @@ -87,12 +87,12 @@ fn rust_ext<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { // example of how to extract an array from a dictionary #[pyfn(m)] - fn extract(d: &PyDict) -> f64 { + fn extract(d: &Bound<'_, PyDict>) -> f64 { let x = d .get_item("x") .unwrap() .unwrap() - .downcast::>() + .downcast_into::>() .unwrap(); x.readonly().as_array().sum() @@ -117,8 +117,8 @@ fn rust_ext<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> { // covering the supported element types and dispatching into a generic implementation. #[derive(FromPyObject)] enum SupportedArray<'py> { - F64(&'py PyArray1), - I64(&'py PyArray1), + F64(Bound<'py, PyArray1>), + I64(Bound<'py, PyArray1>), } #[pyfn(m)] diff --git a/src/array.rs b/src/array.rs index 34863b13f..9392c1554 100644 --- a/src/array.rs +++ b/src/array.rs @@ -235,7 +235,9 @@ impl PyArray { /// # Safety /// /// This is a wrapper around [`pyo3::FromPyPointer::from_owned_ptr_or_opt`] and inherits its safety contract. + #[deprecated(since = "0.21.0", note = "use Bound::from_owned_ptr() instead")] pub unsafe fn from_owned_ptr<'py>(py: Python<'py>, ptr: *mut ffi::PyObject) -> &'py Self { + #[allow(deprecated)] py.from_owned_ptr(ptr) } @@ -244,7 +246,9 @@ impl PyArray { /// # Safety /// /// This is a wrapper around [`pyo3::FromPyPointer::from_borrowed_ptr_or_opt`] and inherits its safety contract. + #[deprecated(since = "0.21.0", note = "use Bound::from_borrowed_ptr() instead")] pub unsafe fn from_borrowed_ptr<'py>(py: Python<'py>, ptr: *mut ffi::PyObject) -> &'py Self { + #[allow(deprecated)] py.from_borrowed_ptr(ptr) } @@ -258,7 +262,7 @@ impl PyArray { impl PyArray { fn extract<'a, 'py, E>(ob: &'a Bound<'py, PyAny>) -> Result<&'a Bound<'py, Self>, E> where - E: From> + From + From>, + E: From> + From + From>, { // Check if the object is an array. let array = unsafe { @@ -786,14 +790,14 @@ impl PyArray { /// # Example /// /// ``` - /// use numpy::PyArray2; - /// use pyo3::Python; + /// use numpy::{PyArray2, PyArrayMethods}; + /// use pyo3::{Python, types::PyAnyMethods}; /// /// Python::with_gil(|py| { /// let pyarray= py - /// .eval("__import__('numpy').array([[0, 1], [2, 3]], dtype='int64')", None, None) + /// .eval_bound("__import__('numpy').array([[0, 1], [2, 3]], dtype='int64')", None, None) /// .unwrap() - /// .downcast::>() + /// .downcast_into::>() /// .unwrap(); /// /// assert_eq!(pyarray.to_vec().unwrap(), vec![0, 1, 2, 3]); @@ -842,10 +846,7 @@ impl PyArray { /// Get an immutable borrow of the NumPy array pub fn try_readonly(&self) -> Result, BorrowError> { - // TODO: replace with `Borrowed::to_owned` once - // pyo3#3963 makes it into a release - let bound = &*self.as_borrowed(); - PyReadonlyArray::try_new(bound.clone()) + PyReadonlyArray::try_new(self.as_borrowed().to_owned()) } /// Get an immutable borrow of the NumPy array @@ -861,10 +862,7 @@ impl PyArray { /// Get a mutable borrow of the NumPy array pub fn try_readwrite(&self) -> Result, BorrowError> { - // TODO: replace with `Borrowed::to_owned` once - // pyo3#3963 makes it into a release - let bound = &*self.as_borrowed(); - PyReadwriteArray::try_new(bound.clone()) + PyReadwriteArray::try_new(self.as_borrowed().to_owned()) } /// Get a mutable borrow of the NumPy array @@ -1013,10 +1011,11 @@ impl PyArray { /// /// ``` /// use ndarray::array; - /// use pyo3::{pyclass, Py, Python}; + /// use pyo3::{pyclass, Py, Python, types::PyAnyMethods}; /// use numpy::{PyArray, PyArrayMethods}; /// /// #[pyclass] + /// # #[allow(dead_code)] /// struct CustomElement { /// foo: i32, /// bar: f64, @@ -1036,7 +1035,7 @@ impl PyArray { /// /// let pyarray = PyArray::from_owned_object_array_bound(py, array); /// - /// assert!(pyarray.readonly().as_array().get(0).unwrap().as_ref(py).is_instance_of::()); + /// assert!(pyarray.readonly().as_array().get(0).unwrap().bind(py).is_instance_of::()); /// }); /// ``` pub fn from_owned_object_array_bound( @@ -1703,14 +1702,14 @@ pub trait PyArrayMethods<'py, T, D>: PyUntypedArrayMethods<'py> { /// # Example /// /// ``` - /// use numpy::PyArray2; - /// use pyo3::Python; + /// use numpy::{PyArray2, PyArrayMethods}; + /// use pyo3::{Python, types::PyAnyMethods}; /// /// Python::with_gil(|py| { /// let pyarray= py - /// .eval("__import__('numpy').array([[0, 1], [2, 3]], dtype='int64')", None, None) + /// .eval_bound("__import__('numpy').array([[0, 1], [2, 3]], dtype='int64')", None, None) /// .unwrap() - /// .downcast::>() + /// .downcast_into::>() /// .unwrap(); /// /// assert_eq!(pyarray.to_vec().unwrap(), vec![0, 1, 2, 3]); diff --git a/src/array_like.rs b/src/array_like.rs index 17ce47eb8..7f7749477 100644 --- a/src/array_like.rs +++ b/src/array_like.rs @@ -166,17 +166,17 @@ where .get_or_try_init(py, || { get_array_module(py)?.getattr("asarray").map(Into::into) })? - .as_ref(py); + .bind(py); let kwargs = if C::VAL { - let kwargs = PyDict::new(py); + let kwargs = PyDict::new_bound(py); kwargs.set_item(intern!(py, "dtype"), T::get_dtype_bound(py))?; Some(kwargs) } else { None }; - let array = as_array.call((ob,), kwargs)?.extract()?; + let array = as_array.call((ob,), kwargs.as_ref())?.extract()?; Ok(Self(array, PhantomData)) } } diff --git a/src/borrow/shared.rs b/src/borrow/shared.rs index e77c6b71b..1ff4344e7 100644 --- a/src/borrow/shared.rs +++ b/src/borrow/shared.rs @@ -574,11 +574,11 @@ mod tests { array.as_ptr().cast::() ); - let locals = [("view1", &view1)].into_py_dict(py); + let locals = [("view1", &view1)].into_py_dict_bound(py); let view2 = py - .eval("view1[:,0]", None, Some(locals)) + .eval_bound("view1[:,0]", None, Some(&locals)) .unwrap() - .downcast::>() + .downcast_into::>() .unwrap(); assert_ne!( view2.as_ptr().cast::(), @@ -819,12 +819,12 @@ mod tests { let array = PyArray::::zeros_bound(py, 10, false); let base = base_address(py, array.as_array_ptr()); - let locals = [("array", array)].into_py_dict(py); + let locals = [("array", array)].into_py_dict_bound(py); let view1 = py - .eval("array[:5]", None, Some(locals)) + .eval_bound("array[:5]", None, Some(&locals)) .unwrap() - .downcast::>() + .downcast_into::>() .unwrap(); let key1 = borrow_key(view1.as_array_ptr()); @@ -842,9 +842,9 @@ mod tests { } let view2 = py - .eval("array[5:]", None, Some(locals)) + .eval_bound("array[5:]", None, Some(&locals)) .unwrap() - .downcast::>() + .downcast_into::>() .unwrap(); let key2 = borrow_key(view2.as_array_ptr()); @@ -865,9 +865,9 @@ mod tests { } let view3 = py - .eval("array[5:]", None, Some(locals)) + .eval_bound("array[5:]", None, Some(&locals)) .unwrap() - .downcast::>() + .downcast_into::>() .unwrap(); let key3 = borrow_key(view3.as_array_ptr()); @@ -891,9 +891,9 @@ mod tests { } let view4 = py - .eval("array[7:]", None, Some(locals)) + .eval_bound("array[7:]", None, Some(&locals)) .unwrap() - .downcast::>() + .downcast_into::>() .unwrap(); let key4 = borrow_key(view4.as_array_ptr()); diff --git a/src/datetime.rs b/src/datetime.rs index 3f1684674..9a96799e5 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -10,25 +10,25 @@ //! # Example //! //! ``` -//! use numpy::{datetime::{units, Datetime, Timedelta}, PyArray1}; -//! use pyo3::Python; +//! use numpy::{datetime::{units, Datetime, Timedelta}, PyArray1, PyArrayMethods}; +//! use pyo3::{Python, types::PyAnyMethods}; //! # use pyo3::types::PyDict; //! //! Python::with_gil(|py| { //! # let locals = py -//! # .eval("{ 'np': __import__('numpy') }", None, None) +//! # .eval_bound("{ 'np': __import__('numpy') }", None, None) //! # .unwrap() -//! # .downcast::() +//! # .downcast_into::() //! # .unwrap(); //! # //! let array = py -//! .eval( +//! .eval_bound( //! "np.array([np.datetime64('2017-04-21')])", //! None, -//! Some(locals), +//! Some(&locals), //! ) //! .unwrap() -//! .downcast::>>() +//! .downcast_into::>>() //! .unwrap(); //! //! assert_eq!( @@ -37,13 +37,13 @@ //! ); //! //! let array = py -//! .eval( +//! .eval_bound( //! "np.array([np.datetime64('2022-03-29')]) - np.array([np.datetime64('2017-04-21')])", //! None, -//! Some(locals), +//! Some(&locals), //! ) //! .unwrap() -//! .downcast::>>() +//! .downcast_into::>>() //! .unwrap(); //! //! assert_eq!( @@ -251,7 +251,7 @@ mod tests { use pyo3::{ py_run, - types::{PyDict, PyModule}, + types::{PyAnyMethods, PyDict, PyModule}, }; use crate::array::{PyArray1, PyArrayMethods}; @@ -260,19 +260,19 @@ mod tests { fn from_python_to_rust() { Python::with_gil(|py| { let locals = py - .eval("{ 'np': __import__('numpy') }", None, None) + .eval_bound("{ 'np': __import__('numpy') }", None, None) .unwrap() - .downcast::() + .downcast_into::() .unwrap(); let array = py - .eval( + .eval_bound( "np.array([np.datetime64('1970-01-01')])", None, - Some(locals), + Some(&locals), ) .unwrap() - .downcast::>>() + .downcast_into::>>() .unwrap(); let value: i64 = array.get_owned(0).unwrap().into(); @@ -288,9 +288,9 @@ mod tests { *array.readwrite().get_mut(0).unwrap() = Timedelta::::from(5); let np = py - .eval("__import__('numpy')", None, None) + .eval_bound("__import__('numpy')", None, None) .unwrap() - .downcast::() + .downcast_into::() .unwrap(); py_run!(py, array np, "assert array.dtype == np.dtype('timedelta64[m]')"); diff --git a/src/dtype.rs b/src/dtype.rs index e1fd1b7ba..9aa37eab9 100644 --- a/src/dtype.rs +++ b/src/dtype.rs @@ -30,19 +30,19 @@ pub use num_complex::{Complex32, Complex64}; /// # Example /// /// ``` -/// use numpy::{dtype, get_array_module, PyArrayDescr}; -/// use numpy::pyo3::{types::IntoPyDict, Python}; +/// use numpy::{dtype_bound, get_array_module, PyArrayDescr, PyArrayDescrMethods}; +/// use numpy::pyo3::{types::{IntoPyDict, PyAnyMethods}, Python}; /// /// Python::with_gil(|py| { -/// let locals = [("np", get_array_module(py).unwrap())].into_py_dict(py); +/// let locals = [("np", get_array_module(py).unwrap())].into_py_dict_bound(py); /// -/// let dt: &PyArrayDescr = py -/// .eval("np.array([1, 2, 3.0]).dtype", Some(locals), None) +/// let dt = py +/// .eval_bound("np.array([1, 2, 3.0]).dtype", Some(&locals), None) /// .unwrap() -/// .downcast() +/// .downcast_into::() /// .unwrap(); /// -/// assert!(dt.is_equiv_to(dtype::(py))); +/// assert!(dt.is_equiv_to(&dtype_bound::(py))); /// }); /// ``` /// @@ -127,10 +127,7 @@ impl PyArrayDescr { /// /// Useful in cases where the descriptor is stolen by the API. pub fn into_dtype_ptr(&self) -> *mut PyArray_Descr { - // TODO: replace with `Borrowed::to_owned` once - // pyo3#3963 makes it into a release - let bound = &*self.as_borrowed(); - bound.clone().into_dtype_ptr() + self.as_borrowed().to_owned().into_dtype_ptr() } /// Shortcut for creating a type descriptor of `object` type. @@ -337,12 +334,8 @@ impl PyArrayDescr { /// Equivalent to [`numpy.dtype.names`][dtype-names]. /// /// [dtype-names]: https://numpy.org/doc/stable/reference/generated/numpy.dtype.names.html - pub fn names(&self) -> Option> { - if !self.has_fields() { - return None; - } - let names = unsafe { Borrowed::from_ptr(self.py(), (*self.as_dtype_ptr()).names) }; - names.extract().ok() + pub fn names(&self) -> Option> { + self.as_borrowed().names() } /// Returns the type descriptor and offset of the field with the given name. @@ -538,7 +531,7 @@ pub trait PyArrayDescrMethods<'py>: Sealed { /// Equivalent to [`numpy.dtype.names`][dtype-names]. /// /// [dtype-names]: https://numpy.org/doc/stable/reference/generated/numpy.dtype.names.html - fn names(&self) -> Option>; + fn names(&self) -> Option>; /// Returns the type descriptor and offset of the field with the given name. /// @@ -605,7 +598,7 @@ impl<'py> PyArrayDescrMethods<'py> for Bound<'py, PyArrayDescr> { } } - fn names(&self) -> Option> { + fn names(&self) -> Option> { if !self.has_fields() { return None; } @@ -823,7 +816,7 @@ mod tests { .is(&dtype_bound::(py))); let dt = PyArrayDescr::new_bound(py, [("a", "O"), ("b", "?")].as_ref()).unwrap(); - assert_eq!(dt.names(), Some(vec!["a", "b"])); + assert_eq!(dt.names(), Some(vec!["a".to_owned(), "b".to_owned()])); assert!(dt.has_object()); assert!(dt .get_field("a") @@ -887,7 +880,7 @@ mod tests { assert_eq!(dt.itemsize(), 8); assert_eq!(dt.alignment(), 8); assert!(!dt.has_object()); - assert_eq!(dt.names(), None); + assert!(dt.names().is_none()); assert!(!dt.has_fields()); assert!(!dt.is_aligned_struct()); assert!(!dt.has_subarray()); @@ -923,7 +916,7 @@ mod tests { assert_eq!(dt.itemsize(), 48); assert_eq!(dt.alignment(), 8); assert!(!dt.has_object()); - assert_eq!(dt.names(), None); + assert!(dt.names().is_none()); assert!(!dt.has_fields()); assert!(!dt.is_aligned_struct()); assert!(dt.has_subarray()); @@ -961,7 +954,10 @@ mod tests { assert_eq!(dt.itemsize(), 24); assert_eq!(dt.alignment(), 8); assert!(dt.has_object()); - assert_eq!(dt.names(), Some(vec!["x", "y", "z"])); + assert_eq!( + dt.names(), + Some(vec!["x".to_owned(), "y".to_owned(), "z".to_owned()]) + ); assert!(dt.has_fields()); assert!(dt.is_aligned_struct()); assert!(!dt.has_subarray()); diff --git a/tests/array.rs b/tests/array.rs index 610821b1c..0b568603f 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -16,18 +16,18 @@ use pyo3::{ Bound, Py, PyResult, Python, }; -fn get_np_locals<'py>(py: Python<'py>) -> &'py PyDict { - [("np", get_array_module(py).unwrap())].into_py_dict(py) +fn get_np_locals(py: Python<'_>) -> Bound<'_, PyDict> { + [("np", get_array_module(py).unwrap())].into_py_dict_bound(py) } -fn not_contiguous_array<'py>(py: Python<'py>) -> &'py PyArray1 { - py.eval( +fn not_contiguous_array(py: Python<'_>) -> Bound<'_, PyArray1> { + py.eval_bound( "np.array([1, 2, 3, 4], dtype='int32')[::2]", None, - Some(get_np_locals(py)), + Some(&get_np_locals(py)), ) .unwrap() - .downcast() + .downcast_into() .unwrap() } @@ -265,7 +265,7 @@ fn extract_as_fixed() { Python::with_gil(|py| { let locals = get_np_locals(py); let pyarray: &PyArray1 = py - .eval("np.array([1, 2, 3], dtype='int32')", Some(locals), None) + .eval_bound("np.array([1, 2, 3], dtype='int32')", Some(&locals), None) .unwrap() .extract() .unwrap(); @@ -279,9 +279,9 @@ fn extract_as_dyn() { Python::with_gil(|py| { let locals = get_np_locals(py); let pyarray: &PyArrayDyn = py - .eval( + .eval_bound( "np.array([[1, 2], [3, 4]], dtype='int32')", - Some(locals), + Some(&locals), None, ) .unwrap() @@ -299,8 +299,10 @@ fn extract_as_dyn() { fn extract_fail_by_check() { Python::with_gil(|py| { let locals = get_np_locals(py); - let pyarray: PyResult<&PyArray2> = - py.eval("[1, 2, 3]", Some(locals), None).unwrap().extract(); + let pyarray: PyResult<&PyArray2> = py + .eval_bound("[1, 2, 3]", Some(&locals), None) + .unwrap() + .extract(); let err = pyarray.unwrap_err(); assert_eq!( @@ -315,7 +317,7 @@ fn extract_fail_by_dim() { Python::with_gil(|py| { let locals = get_np_locals(py); let pyarray: PyResult<&PyArray2> = py - .eval("np.array([1, 2, 3], dtype='int32')", Some(locals), None) + .eval_bound("np.array([1, 2, 3], dtype='int32')", Some(&locals), None) .unwrap() .extract(); @@ -332,7 +334,7 @@ fn extract_fail_by_dtype() { Python::with_gil(|py| { let locals = get_np_locals(py); let pyarray: PyResult<&PyArray1> = py - .eval("np.array([1, 2, 3], dtype='float64')", Some(locals), None) + .eval_bound("np.array([1, 2, 3], dtype='float64')", Some(&locals), None) .unwrap() .extract(); @@ -467,7 +469,7 @@ fn unbind_works() { }); Python::with_gil(|py| { - let arr: &PyArray1<_> = arr.as_ref(py); + let arr = arr.bind(py); assert_eq!(arr.readonly().as_slice().unwrap(), &[1, 2, 3]); }); @@ -483,7 +485,7 @@ fn to_owned_works() { }); Python::with_gil(|py| { - let arr: &PyArray1<_> = arr.as_ref(py); + let arr = arr.bind(py); assert_eq!(arr.readonly().as_slice().unwrap(), &[1, 2, 3]); }); @@ -541,17 +543,17 @@ fn reshape() { #[test] fn half_f16_works() { Python::with_gil(|py| { - let np = py.eval("__import__('numpy')", None, None).unwrap(); - let locals = [("np", np)].into_py_dict(py); + let np = py.eval_bound("__import__('numpy')", None, None).unwrap(); + let locals = [("np", &np)].into_py_dict_bound(py); let array = py - .eval( + .eval_bound( "np.array([[1, 2], [3, 4]], dtype='float16')", None, - Some(locals), + Some(&locals), ) .unwrap() - .downcast::>() + .downcast_into::>() .unwrap(); assert_eq!( @@ -579,20 +581,22 @@ fn half_f16_works() { #[test] fn half_bf16_works() { Python::with_gil(|py| { - let np = py.eval("__import__('numpy')", None, None).unwrap(); + let np = py.eval_bound("__import__('numpy')", None, None).unwrap(); // NumPy itself does not provide a `bfloat16` dtype itself, // so we import ml_dtypes which does register such a dtype. - let mldt = py.eval("__import__('ml_dtypes')", None, None).unwrap(); - let locals = [("np", np), ("mldt", mldt)].into_py_dict(py); + let mldt = py + .eval_bound("__import__('ml_dtypes')", None, None) + .unwrap(); + let locals = [("np", &np), ("mldt", &mldt)].into_py_dict_bound(py); let array = py - .eval( + .eval_bound( "np.array([[1, 2], [3, 4]], dtype='bfloat16')", None, - Some(locals), + Some(&locals), ) .unwrap() - .downcast::>() + .downcast_into::>() .unwrap(); assert_eq!( @@ -619,17 +623,17 @@ fn half_bf16_works() { #[test] fn ascii_strings_with_explicit_dtype_works() { Python::with_gil(|py| { - let np = py.eval("__import__('numpy')", None, None).unwrap(); - let locals = [("np", np)].into_py_dict(py); + let np = py.eval_bound("__import__('numpy')", None, None).unwrap(); + let locals = [("np", &np)].into_py_dict_bound(py); let array = py - .eval( + .eval_bound( "np.array([b'foo', b'bar', b'foobar'], dtype='S6')", None, - Some(locals), + Some(&locals), ) .unwrap() - .downcast::>>() + .downcast_into::>>() .unwrap(); { @@ -655,17 +659,17 @@ fn ascii_strings_with_explicit_dtype_works() { #[test] fn unicode_strings_with_explicit_dtype_works() { Python::with_gil(|py| { - let np = py.eval("__import__('numpy')", None, None).unwrap(); - let locals = [("np", np)].into_py_dict(py); + let np = py.eval_bound("__import__('numpy')", None, None).unwrap(); + let locals = [("np", &np)].into_py_dict_bound(py); let array = py - .eval( + .eval_bound( "np.array(['foo', 'bar', 'foobar'], dtype='U6')", None, - Some(locals), + Some(&locals), ) .unwrap() - .downcast::>>() + .downcast_into::>>() .unwrap(); { @@ -694,34 +698,34 @@ fn unicode_strings_with_explicit_dtype_works() { #[test] fn ascii_strings_ignore_byteorder() { Python::with_gil(|py| { - let np = py.eval("__import__('numpy')", None, None).unwrap(); - let locals = [("np", np)].into_py_dict(py); + let np = py.eval_bound("__import__('numpy')", None, None).unwrap(); + let locals = [("np", &np)].into_py_dict_bound(py); let native_endian_works = py - .eval( + .eval_bound( "np.array([b'foo', b'bar'], dtype='=S3')", None, - Some(locals), + Some(&locals), ) .unwrap() .downcast::>>() .is_ok(); let little_endian_works = py - .eval( + .eval_bound( "np.array(['bfoo', b'bar'], dtype='>>() .is_ok(); let big_endian_works = py - .eval( + .eval_bound( "np.array([b'foo', b'bar'], dtype='>S3')", None, - Some(locals), + Some(&locals), ) .unwrap() .downcast::>>() @@ -737,23 +741,23 @@ fn ascii_strings_ignore_byteorder() { #[test] fn unicode_strings_respect_byteorder() { Python::with_gil(|py| { - let np = py.eval("__import__('numpy')", None, None).unwrap(); - let locals = [("np", np)].into_py_dict(py); + let np = py.eval_bound("__import__('numpy')", None, None).unwrap(); + let locals = [("np", &np)].into_py_dict_bound(py); let native_endian_works = py - .eval("np.array(['foo', 'bar'], dtype='=U3')", None, Some(locals)) + .eval_bound("np.array(['foo', 'bar'], dtype='=U3')", None, Some(&locals)) .unwrap() .downcast::>>() .is_ok(); let little_endian_works = py - .eval("np.array(['foo', 'bar'], dtype='>>() .is_ok(); let big_endian_works = py - .eval("np.array(['foo', 'bar'], dtype='>U3')", None, Some(locals)) + .eval_bound("np.array(['foo', 'bar'], dtype='>U3')", None, Some(&locals)) .unwrap() .downcast::>>() .is_ok(); diff --git a/tests/array_like.rs b/tests/array_like.rs index 2a340ca27..cd96f63f5 100644 --- a/tests/array_like.rs +++ b/tests/array_like.rs @@ -1,12 +1,12 @@ use ndarray::array; use numpy::{get_array_module, AllowTypeChange, PyArrayLike1, PyArrayLike2, PyArrayLikeDyn}; use pyo3::{ - types::{IntoPyDict, PyDict}, - Python, + types::{IntoPyDict, PyAnyMethods, PyDict}, + Bound, Python, }; -fn get_np_locals<'py>(py: Python<'py>) -> &'py PyDict { - [("np", get_array_module(py).unwrap())].into_py_dict(py) +fn get_np_locals(py: Python<'_>) -> Bound<'_, PyDict> { + [("np", get_array_module(py).unwrap())].into_py_dict_bound(py) } #[test] @@ -14,9 +14,9 @@ fn extract_reference() { Python::with_gil(|py| { let locals = get_np_locals(py); let py_array = py - .eval( + .eval_bound( "np.array([[1,2],[3,4]], dtype='float64')", - Some(locals), + Some(&locals), None, ) .unwrap(); @@ -34,7 +34,11 @@ fn convert_array_on_extract() { Python::with_gil(|py| { let locals = get_np_locals(py); let py_array = py - .eval("np.array([[1,2],[3,4]], dtype='int32')", Some(locals), None) + .eval_bound( + "np.array([[1,2],[3,4]], dtype='int32')", + Some(&locals), + None, + ) .unwrap(); let extracted_array = py_array .extract::>() @@ -50,7 +54,7 @@ fn convert_array_on_extract() { #[test] fn convert_list_on_extract() { Python::with_gil(|py| { - let py_list = py.eval("[[1.0,2.0],[3.0,4.0]]", None, None).unwrap(); + let py_list = py.eval_bound("[[1.0,2.0],[3.0,4.0]]", None, None).unwrap(); let extracted_array = py_list.extract::>().unwrap(); assert_eq!(array![[1.0, 2.0], [3.0, 4.0]], extracted_array.as_array()); @@ -62,7 +66,7 @@ fn convert_array_in_list_on_extract() { Python::with_gil(|py| { let locals = get_np_locals(py); let py_array = py - .eval("[np.array([1.0, 2.0]), [3.0, 4.0]]", Some(locals), None) + .eval_bound("[np.array([1.0, 2.0]), [3.0, 4.0]]", Some(&locals), None) .unwrap(); let extracted_array = py_array.extract::>().unwrap(); @@ -74,7 +78,7 @@ fn convert_array_in_list_on_extract() { fn convert_list_on_extract_dyn() { Python::with_gil(|py| { let py_list = py - .eval("[[[1,2],[3,4]],[[5,6],[7,8]]]", None, None) + .eval_bound("[[[1,2],[3,4]],[[5,6],[7,8]]]", None, None) .unwrap(); let extracted_array = py_list .extract::>() @@ -90,7 +94,7 @@ fn convert_list_on_extract_dyn() { #[test] fn convert_1d_list_on_extract() { Python::with_gil(|py| { - let py_list = py.eval("[1,2,3,4]", None, None).unwrap(); + let py_list = py.eval_bound("[1,2,3,4]", None, None).unwrap(); let extracted_array_1d = py_list.extract::>().unwrap(); let extracted_array_dyn = py_list.extract::>().unwrap(); @@ -107,9 +111,9 @@ fn unsafe_cast_shall_fail() { Python::with_gil(|py| { let locals = get_np_locals(py); let py_list = py - .eval( + .eval_bound( "np.array([1.1,2.2,3.3,4.4], dtype='float64')", - Some(locals), + Some(&locals), None, ) .unwrap(); @@ -124,9 +128,9 @@ fn unsafe_cast_with_coerce_works() { Python::with_gil(|py| { let locals = get_np_locals(py); let py_list = py - .eval( + .eval_bound( "np.array([1.1,2.2,3.3,4.4], dtype='float64')", - Some(locals), + Some(&locals), None, ) .unwrap(); diff --git a/tests/borrow.rs b/tests/borrow.rs index 9ab6cbd42..b2786534a 100644 --- a/tests/borrow.rs +++ b/tests/borrow.rs @@ -426,10 +426,14 @@ fn matrix_from_numpy() { Python::with_gil(|py| { let array = numpy::pyarray![py, [0, 1, 2], [3, 4, 5], [6, 7, 8]]; - let array: &PyArray2 = py - .eval("a[::-1]", Some([("a", array)].into_py_dict(py)), None) + let array = py + .eval_bound( + "a[::-1]", + Some(&[("a", array)].into_py_dict_bound(py)), + None, + ) .unwrap() - .downcast() + .downcast_into::>() .unwrap(); let array = array.readonly(); @@ -440,10 +444,14 @@ fn matrix_from_numpy() { Python::with_gil(|py| { let array = numpy::pyarray![py, [[0, 1], [2, 3]], [[4, 5], [6, 7]]]; - let array: &PyArray2 = py - .eval("a[:,:,0]", Some([("a", array)].into_py_dict(py)), None) + let array = py + .eval_bound( + "a[:,:,0]", + Some(&[("a", &array)].into_py_dict_bound(py)), + None, + ) .unwrap() - .downcast() + .downcast_into::>() .unwrap(); let array = array.readonly(); diff --git a/tests/to_py.rs b/tests/to_py.rs index d09c3e464..f5ebe0c55 100644 --- a/tests/to_py.rs +++ b/tests/to_py.rs @@ -5,7 +5,7 @@ use ndarray::{array, s, Array2, Array3}; use numpy::{prelude::*, PyArray}; use pyo3::{ py_run, - types::{PyDict, PyString}, + types::{PyAnyMethods, PyDict, PyString}, Python, ToPyObject, }; @@ -232,8 +232,8 @@ fn forder_into_pyarray() { #[test] fn to_pyarray_object_vec() { Python::with_gil(|py| { - let dict = PyDict::new(py); - let string = PyString::new(py, "Hello:)"); + let dict = PyDict::new_bound(py); + let string = PyString::new_bound(py, "Hello:)"); #[allow(clippy::useless_vec)] // otherwise we do not test the right trait impl let vec = vec![dict.to_object(py), string.to_object(py)]; @@ -241,7 +241,7 @@ fn to_pyarray_object_vec() { for (a, b) in vec.iter().zip(arr.readonly().as_slice().unwrap().iter()) { assert_eq!( - a.as_ref(py).compare(b).map_err(|e| e.print(py)).unwrap(), + a.bind(py).compare(b).map_err(|e| e.print(py)).unwrap(), Ordering::Equal ); } @@ -252,8 +252,8 @@ fn to_pyarray_object_vec() { fn to_pyarray_object_array() { Python::with_gil(|py| { let mut nd_arr = Array2::from_shape_fn((2, 3), |(_, _)| py.None()); - nd_arr[(0, 2)] = PyDict::new(py).to_object(py); - nd_arr[(1, 0)] = PyString::new(py, "Hello:)").to_object(py); + nd_arr[(0, 2)] = PyDict::new_bound(py).to_object(py); + nd_arr[(1, 0)] = PyString::new_bound(py, "Hello:)").to_object(py); let py_arr = nd_arr.to_pyarray_bound(py); @@ -264,7 +264,7 @@ fn to_pyarray_object_array() { .zip(py_arr.readonly().as_slice().unwrap().iter()) { assert_eq!( - a.as_ref(py).compare(b).map_err(|e| e.print(py)).unwrap(), + a.bind(py).compare(b).map_err(|e| e.print(py)).unwrap(), Ordering::Equal ); } @@ -275,8 +275,8 @@ fn to_pyarray_object_array() { fn slice_container_type_confusion() { Python::with_gil(|py| { let mut nd_arr = Array2::from_shape_fn((2, 3), |(_, _)| py.None()); - nd_arr[(0, 2)] = PyDict::new(py).to_object(py); - nd_arr[(1, 0)] = PyString::new(py, "Hello:)").to_object(py); + nd_arr[(0, 2)] = PyDict::new_bound(py).to_object(py); + nd_arr[(1, 0)] = PyString::new_bound(py, "Hello:)").to_object(py); let _py_arr = nd_arr.into_pyarray_bound(py);