diff --git a/Cargo.toml b/Cargo.toml index 4c71108a9..d2b39821e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,12 +22,15 @@ 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 = ["macros"] } +pyo3 = { version = "0.22.0", default-features = false, features = ["macros", "py-clone"] } rustc-hash = "1.1" [dev-dependencies] -pyo3 = { version = "0.21.0", default-features = false, features = ["auto-initialize"] } +pyo3 = { version = "0.22.0", default-features = false, features = ["auto-initialize"] } nalgebra = { version = "0.32", default-features = false, features = ["std"] } [package.metadata.docs.rs] all-features = true + +[features] +gil-refs = ["pyo3/gil-refs"] diff --git a/src/array.rs b/src/array.rs index dfc630727..d0de2949c 100644 --- a/src/array.rs +++ b/src/array.rs @@ -19,9 +19,11 @@ use num_traits::AsPrimitive; use pyo3::{ ffi, pyobject_native_type_base, types::{DerefToPyAny, PyAnyMethods, PyModule}, - AsPyPointer, Bound, DowncastError, FromPyObject, IntoPy, Py, PyAny, PyErr, PyNativeType, - PyObject, PyResult, PyTypeInfo, Python, + AsPyPointer, Bound, DowncastError, IntoPy, Py, PyAny, PyErr, PyObject, PyResult, PyTypeInfo, + Python, }; +#[cfg(feature = "gil-refs")] +use pyo3::{FromPyObject, PyNativeType}; use crate::borrow::{PyReadonlyArray, PyReadwriteArray}; use crate::cold; @@ -170,6 +172,7 @@ impl IntoPy>> for &'_ PyArray { } } +#[cfg(feature = "gil-refs")] impl From<&'_ PyArray> for Py> { #[inline] fn from(other: &PyArray) -> Self { @@ -189,6 +192,7 @@ impl IntoPy for PyArray { } } +#[cfg(feature = "gil-refs")] impl<'py, T: Element, D: Dimension> FromPyObject<'py> for &'py PyArray { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { #[allow(clippy::map_clone)] // due to MSRV @@ -204,7 +208,10 @@ impl PyArray { pub fn as_untyped(&self) -> &PyUntypedArray { unsafe { &*(self as *const Self as *const PyUntypedArray) } } +} +#[cfg(feature = "gil-refs")] +impl PyArray { /// Turn `&PyArray` into `Py>`, /// i.e. a pointer into Python's heap which is independent of the GIL lifetime. /// @@ -225,7 +232,6 @@ impl PyArray { /// assert_eq!(array.bind(py).readonly().as_slice().unwrap(), [0.0; 5]); /// }); /// ``` - #[deprecated(since = "0.21.0", note = "use Bound::unbind() instead")] pub fn to_owned(&self) -> Py { unsafe { Py::from_borrowed_ptr(self.py(), self.as_ptr()) } } @@ -235,7 +241,6 @@ 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) @@ -246,7 +251,6 @@ 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) @@ -290,27 +294,6 @@ impl PyArray { Ok(array) } - /// Same as [`shape`][PyUntypedArray::shape], but returns `D` instead of `&[usize]`. - #[inline(always)] - pub fn dims(&self) -> D { - D::from_dimension(&Dim(self.shape())).expect(DIMENSIONALITY_MISMATCH_ERR) - } - - /// Deprecated form of [`PyArray::new_bound`] - /// - /// # Safety - /// Same as [`PyArray::new_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by `PyArray::new_bound` in the future" - )] - pub unsafe fn new<'py, ID>(py: Python<'py>, dims: ID, is_fortran: bool) -> &Self - where - ID: IntoDimension, - { - Self::new_bound(py, dims, is_fortran).into_gil_ref() - } - /// Creates a new uninitialized NumPy array. /// /// If `is_fortran` is true, then it has Fortran/column-major order, @@ -435,24 +418,6 @@ impl PyArray { Self::new_with_data(py, dims, strides, data_ptr, container.cast()) } - /// Deprecated form of [`PyArray::borrow_from_array_bound`] - /// - /// # Safety - /// Same as [`PyArray::borrow_from_array_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by `PyArray::borrow_from_array_bound` in the future" - )] - pub unsafe fn borrow_from_array<'py, S>( - array: &ArrayBase, - container: &'py PyAny, - ) -> &'py Self - where - S: Data, - { - Self::borrow_from_array_bound(array, (*container.as_borrowed()).clone()).into_gil_ref() - } - /// Creates a NumPy array backed by `array` and ties its ownership to the Python object `container`. /// /// # Safety @@ -504,18 +469,6 @@ impl PyArray { ) } - /// Deprecated form of [`PyArray::zeros_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by `PyArray::zeros_bound` in the future" - )] - pub fn zeros<'py, ID>(py: Python<'py>, dims: ID, is_fortran: bool) -> &Self - where - ID: IntoDimension, - { - Self::zeros_bound(py, dims, is_fortran).into_gil_ref() - } - /// Construct a new NumPy array filled with zeros. /// /// If `is_fortran` is true, then it has Fortran/column-major order, @@ -558,6 +511,104 @@ impl PyArray { } } + /// Constructs a NumPy from an [`ndarray::Array`] + /// + /// This method uses the internal [`Vec`] of the [`ndarray::Array`] as the base object of the NumPy array. + /// + /// # Example + /// + /// ``` + /// use numpy::{PyArray, PyArrayMethods}; + /// use ndarray::array; + /// use pyo3::Python; + /// + /// Python::with_gil(|py| { + /// let pyarray = PyArray::from_owned_array_bound(py, array![[1, 2], [3, 4]]); + /// + /// assert_eq!(pyarray.readonly().as_array(), array![[1, 2], [3, 4]]); + /// }); + /// ``` + pub fn from_owned_array_bound(py: Python<'_>, mut arr: Array) -> Bound<'_, Self> { + let (strides, dims) = (arr.npy_strides(), arr.raw_dim()); + let data_ptr = arr.as_mut_ptr(); + unsafe { + Self::from_raw_parts( + py, + dims, + strides.as_ptr(), + data_ptr, + PySliceContainer::from(arr), + ) + } + } + + /// Construct a NumPy array from a [`ndarray::ArrayBase`]. + /// + /// This method allocates memory in Python's heap via the NumPy API, + /// and then copies all elements of the array there. + /// + /// # Example + /// + /// ``` + /// use numpy::{PyArray, PyArrayMethods}; + /// use ndarray::array; + /// use pyo3::Python; + /// + /// Python::with_gil(|py| { + /// let pyarray = PyArray::from_array_bound(py, &array![[1, 2], [3, 4]]); + /// + /// assert_eq!(pyarray.readonly().as_array(), array![[1, 2], [3, 4]]); + /// }); + /// ``` + pub fn from_array_bound<'py, S>(py: Python<'py>, arr: &ArrayBase) -> Bound<'py, Self> + where + S: Data, + { + ToPyArray::to_pyarray_bound(arr, py) + } +} + +#[cfg(feature = "gil-refs")] +impl PyArray { + /// Same as [`shape`][PyUntypedArray::shape], but returns `D` instead of `&[usize]`. + #[inline(always)] + pub fn dims(&self) -> D { + D::from_dimension(&Dim(self.shape())).expect(DIMENSIONALITY_MISMATCH_ERR) + } + + /// Deprecated form of [`PyArray::new_bound`] + /// + /// # Safety + /// Same as [`PyArray::new_bound`] + pub unsafe fn new<'py, ID>(py: Python<'py>, dims: ID, is_fortran: bool) -> &Self + where + ID: IntoDimension, + { + Self::new_bound(py, dims, is_fortran).into_gil_ref() + } + + /// Deprecated form of [`PyArray::borrow_from_array_bound`] + /// + /// # Safety + /// Same as [`PyArray::borrow_from_array_bound`] + pub unsafe fn borrow_from_array<'py, S>( + array: &ArrayBase, + container: &'py PyAny, + ) -> &'py Self + where + S: Data, + { + Self::borrow_from_array_bound(array, (*container.as_borrowed()).clone()).into_gil_ref() + } + + /// Deprecated form of [`PyArray::zeros_bound`] + pub fn zeros<'py, ID>(py: Python<'py>, dims: ID, is_fortran: bool) -> &Self + where + ID: IntoDimension, + { + Self::zeros_bound(py, dims, is_fortran).into_gil_ref() + } + /// Returns an immutable view of the internal data as a slice. /// /// # Safety @@ -593,45 +644,10 @@ impl PyArray { } /// Deprecated form of [`PyArray::from_owned_array_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by PyArray::from_owned_array_bound in the future" - )] pub fn from_owned_array<'py>(py: Python<'py>, arr: Array) -> &'py Self { Self::from_owned_array_bound(py, arr).into_gil_ref() } - /// Constructs a NumPy from an [`ndarray::Array`] - /// - /// This method uses the internal [`Vec`] of the [`ndarray::Array`] as the base object of the NumPy array. - /// - /// # Example - /// - /// ``` - /// use numpy::{PyArray, PyArrayMethods}; - /// use ndarray::array; - /// use pyo3::Python; - /// - /// Python::with_gil(|py| { - /// let pyarray = PyArray::from_owned_array_bound(py, array![[1, 2], [3, 4]]); - /// - /// assert_eq!(pyarray.readonly().as_array(), array![[1, 2], [3, 4]]); - /// }); - /// ``` - pub fn from_owned_array_bound(py: Python<'_>, mut arr: Array) -> Bound<'_, Self> { - let (strides, dims) = (arr.npy_strides(), arr.raw_dim()); - let data_ptr = arr.as_mut_ptr(); - unsafe { - Self::from_raw_parts( - py, - dims, - strides.as_ptr(), - data_ptr, - PySliceContainer::from(arr), - ) - } - } - /// Get a reference of the specified element if the given index is valid. /// /// # Safety @@ -808,10 +824,6 @@ impl PyArray { } /// Deprecated form of [`PyArray::from_array_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by PyArray::from_array_bound in the future" - )] pub fn from_array<'py, S>(py: Python<'py>, arr: &ArrayBase) -> &'py Self where S: Data, @@ -819,31 +831,6 @@ impl PyArray { Self::from_array_bound(py, arr).into_gil_ref() } - /// Construct a NumPy array from a [`ndarray::ArrayBase`]. - /// - /// This method allocates memory in Python's heap via the NumPy API, - /// and then copies all elements of the array there. - /// - /// # Example - /// - /// ``` - /// use numpy::{PyArray, PyArrayMethods}; - /// use ndarray::array; - /// use pyo3::Python; - /// - /// Python::with_gil(|py| { - /// let pyarray = PyArray::from_array_bound(py, &array![[1, 2], [3, 4]]); - /// - /// assert_eq!(pyarray.readonly().as_array(), array![[1, 2], [3, 4]]); - /// }); - /// ``` - pub fn from_array_bound<'py, S>(py: Python<'py>, arr: &ArrayBase) -> Bound<'py, Self> - where - S: Data, - { - ToPyArray::to_pyarray_bound(arr, py) - } - /// Get an immutable borrow of the NumPy array pub fn try_readonly(&self) -> Result, BorrowError> { PyReadonlyArray::try_new(self.as_borrowed().to_owned()) @@ -995,10 +982,7 @@ where impl PyArray { /// Deprecated form of [`PyArray::from_owned_object_array_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by PyArray::from_owned_object_array_bound in the future" - )] + #[cfg(feature = "gil-refs")] pub fn from_owned_object_array<'py, T>(py: Python<'py>, arr: Array, D>) -> &'py Self { Self::from_owned_object_array_bound(py, arr).into_gil_ref() } @@ -1056,6 +1040,7 @@ impl PyArray { } } +#[cfg(feature = "gil-refs")] impl PyArray { /// Get the single element of a zero-dimensional array. /// @@ -1066,15 +1051,6 @@ impl PyArray { } impl PyArray { - /// Deprecated form of [`PyArray::from_slice_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by `PyArray::from_slice_bound` in the future" - )] - pub fn from_slice<'py>(py: Python<'py>, slice: &[T]) -> &'py Self { - Self::from_slice_bound(py, slice).into_gil_ref() - } - /// Construct a one-dimensional array from a [mod@slice]. /// /// # Example @@ -1098,16 +1074,6 @@ impl PyArray { } } - /// Deprecated form of [`PyArray::from_vec_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by `PyArray::from_vec_bound` in the future" - )] - #[inline(always)] - pub fn from_vec<'py>(py: Python<'py>, vec: Vec) -> &'py Self { - Self::from_vec_bound(py, vec).into_gil_ref() - } - /// Construct a one-dimensional array from a [`Vec`][Vec]. /// /// # Example @@ -1127,18 +1093,6 @@ impl PyArray { vec.into_pyarray_bound(py) } - /// Deprecated form of [`PyArray::from_iter_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by PyArray::from_iter_bound in the future" - )] - pub fn from_iter<'py, I>(py: Python<'py>, iter: I) -> &'py Self - where - I: IntoIterator, - { - Self::from_iter_bound(py, iter).into_gil_ref() - } - /// Construct a one-dimensional array from an [`Iterator`]. /// /// If no reliable [`size_hint`][Iterator::size_hint] is available, @@ -1164,12 +1118,31 @@ impl PyArray { } } +#[cfg(feature = "gil-refs")] +impl PyArray { + /// Deprecated form of [`PyArray::from_slice_bound`] + pub fn from_slice<'py>(py: Python<'py>, slice: &[T]) -> &'py Self { + Self::from_slice_bound(py, slice).into_gil_ref() + } + + /// Deprecated form of [`PyArray::from_vec_bound`] + #[inline(always)] + pub fn from_vec<'py>(py: Python<'py>, vec: Vec) -> &'py Self { + Self::from_vec_bound(py, vec).into_gil_ref() + } + + /// Deprecated form of [`PyArray::from_iter_bound`] + pub fn from_iter<'py, I>(py: Python<'py>, iter: I) -> &'py Self + where + I: IntoIterator, + { + Self::from_iter_bound(py, iter).into_gil_ref() + } +} + impl PyArray { /// Deprecated form of [`PyArray::from_vec2_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by `PyArray::from_vec2_bound` in the future" - )] + #[cfg(feature = "gil-refs")] pub fn from_vec2<'py>(py: Python<'py>, v: &[Vec]) -> Result<&'py Self, FromVecError> { Self::from_vec2_bound(py, v).map(Bound::into_gil_ref) } @@ -1219,10 +1192,7 @@ impl PyArray { impl PyArray { /// Deprecated form of [`PyArray::from_vec3_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by `PyArray::from_vec3_bound` in the future" - )] + #[cfg(feature = "gil-refs")] pub fn from_vec3<'py>(py: Python<'py>, v: &[Vec>]) -> Result<&'py Self, FromVecError> { Self::from_vec3_bound(py, v).map(Bound::into_gil_ref) } @@ -1286,6 +1256,7 @@ impl PyArray { } } +#[cfg(feature = "gil-refs")] impl PyArray { /// Copies `self` into `other`, performing a data type conversion if necessary. /// @@ -1458,10 +1429,7 @@ impl PyArray { impl> PyArray { /// Deprecated form of [`PyArray::arange_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by PyArray::arange_bound in the future" - )] + #[cfg(feature = "gil-refs")] pub fn arange<'py>(py: Python<'py>, start: T, stop: T, step: T) -> &Self { Self::arange_bound(py, start, stop, step).into_gil_ref() } diff --git a/src/convert.rs b/src/convert.rs index 4e50c5126..342758d96 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -41,10 +41,7 @@ pub trait IntoPyArray: Sized { type Dim: Dimension; /// Deprecated form of [`IntoPyArray::into_pyarray_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by `IntoPyArray::into_pyarray_bound` in the future" - )] + #[cfg(feature = "gil-refs")] fn into_pyarray<'py>(self, py: Python<'py>) -> &'py PyArray { Self::into_pyarray_bound(self, py).into_gil_ref() } @@ -152,10 +149,7 @@ pub trait ToPyArray { type Dim: Dimension; /// Deprecated form of [`ToPyArray::to_pyarray_bound`] - #[deprecated( - since = "0.21.0", - note = "will be replaced by `ToPyArray::to_pyarray_bound` in the future" - )] + #[cfg(feature = "gil-refs")] fn to_pyarray<'py>(&self, py: Python<'py>) -> &'py PyArray { Self::to_pyarray_bound(self, py).into_gil_ref() } diff --git a/src/datetime.rs b/src/datetime.rs index 9a96799e5..c5f96a305 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -241,7 +241,7 @@ impl TypeDescriptors { } }; - dtype.clone().into_bound(py) + dtype.bind(py).to_owned() } } diff --git a/src/dtype.rs b/src/dtype.rs index 9aa37eab9..e007c7b99 100644 --- a/src/dtype.rs +++ b/src/dtype.rs @@ -12,11 +12,12 @@ use pyo3::{ ffi::{self, PyTuple_Size}, pyobject_native_type_extract, pyobject_native_type_named, types::{PyAnyMethods, PyDict, PyDictMethods, PyTuple, PyType}, - AsPyPointer, Borrowed, Bound, PyAny, PyNativeType, PyObject, PyResult, PyTypeInfo, Python, - ToPyObject, + Borrowed, Bound, PyAny, PyObject, PyResult, PyTypeInfo, Python, ToPyObject, }; #[cfg(feature = "half")] use pyo3::{sync::GILOnceCell, Py}; +#[cfg(feature = "gil-refs")] +use pyo3::{AsPyPointer, PyNativeType}; use crate::npyffi::{ NpyTypes, PyArray_Descr, NPY_ALIGNED_STRUCT, NPY_BYTEORDER_CHAR, NPY_ITEM_HASOBJECT, NPY_TYPES, @@ -61,6 +62,7 @@ unsafe impl PyTypeInfo for PyArrayDescr { unsafe { PY_ARRAY_API.get_type_object(py, NpyTypes::PyArrayDescr_Type) } } + #[cfg(feature = "gil-refs")] fn is_type_of(ob: &PyAny) -> bool { unsafe { ffi::PyObject_TypeCheck(ob.as_ptr(), Self::type_object_raw(ob.py())) > 0 } } @@ -69,10 +71,7 @@ unsafe impl PyTypeInfo for PyArrayDescr { pyobject_native_type_extract!(PyArrayDescr); /// Returns the type descriptor ("dtype") for a registered type. -#[deprecated( - since = "0.21.0", - note = "This will be replaced by `dtype_bound` in the future." -)] +#[cfg(feature = "gil-refs")] pub fn dtype<'py, T: Element>(py: Python<'py>) -> &'py PyArrayDescr { T::get_dtype_bound(py).into_gil_ref() } @@ -83,18 +82,6 @@ pub fn dtype_bound<'py, T: Element>(py: Python<'py>) -> Bound<'py, PyArrayDescr> } impl PyArrayDescr { - /// Creates a new type descriptor ("dtype") object from an arbitrary object. - /// - /// Equivalent to invoking the constructor of [`numpy.dtype`][dtype]. - /// - /// [dtype]: https://numpy.org/doc/stable/reference/generated/numpy.dtype.html - #[deprecated( - since = "0.21.0", - note = "This will be replace by `new_bound` in the future." - )] - pub fn new<'py, T: ToPyObject + ?Sized>(py: Python<'py>, ob: &T) -> PyResult<&'py Self> { - Self::new_bound(py, ob).map(Bound::into_gil_ref) - } /// Creates a new type descriptor ("dtype") object from an arbitrary object. /// /// Equivalent to invoking the constructor of [`numpy.dtype`][dtype]. @@ -118,6 +105,42 @@ impl PyArrayDescr { inner(py, ob.to_object(py)) } + /// Shortcut for creating a type descriptor of `object` type. + pub fn object_bound(py: Python<'_>) -> Bound<'_, Self> { + Self::from_npy_type(py, NPY_TYPES::NPY_OBJECT) + } + + /// Returns the type descriptor for a registered type. + pub fn of_bound<'py, T: Element>(py: Python<'py>) -> Bound<'py, Self> { + T::get_dtype_bound(py) + } + + fn from_npy_type<'py>(py: Python<'py>, npy_type: NPY_TYPES) -> Bound<'py, Self> { + unsafe { + let descr = PY_ARRAY_API.PyArray_DescrFromType(py, npy_type as _); + Bound::from_owned_ptr(py, descr.cast()).downcast_into_unchecked() + } + } + + pub(crate) fn new_from_npy_type<'py>(py: Python<'py>, npy_type: NPY_TYPES) -> Bound<'py, Self> { + unsafe { + let descr = PY_ARRAY_API.PyArray_DescrNewFromType(py, npy_type as _); + Bound::from_owned_ptr(py, descr.cast()).downcast_into_unchecked() + } + } +} + +#[cfg(feature = "gil-refs")] +impl PyArrayDescr { + /// Creates a new type descriptor ("dtype") object from an arbitrary object. + /// + /// Equivalent to invoking the constructor of [`numpy.dtype`][dtype]. + /// + /// [dtype]: https://numpy.org/doc/stable/reference/generated/numpy.dtype.html + pub fn new<'py, T: ToPyObject + ?Sized>(py: Python<'py>, ob: &T) -> PyResult<&'py Self> { + Self::new_bound(py, ob).map(Bound::into_gil_ref) + } + /// Returns `self` as `*mut PyArray_Descr`. pub fn as_dtype_ptr(&self) -> *mut PyArray_Descr { self.as_borrowed().as_dtype_ptr() @@ -131,52 +154,20 @@ impl PyArrayDescr { } /// Shortcut for creating a type descriptor of `object` type. - #[deprecated( - since = "0.21.0", - note = "This will be replaced by `object_bound` in the future." - )] pub fn object<'py>(py: Python<'py>) -> &'py Self { Self::object_bound(py).into_gil_ref() } - /// Shortcut for creating a type descriptor of `object` type. - pub fn object_bound(py: Python<'_>) -> Bound<'_, Self> { - Self::from_npy_type(py, NPY_TYPES::NPY_OBJECT) - } - /// Returns the type descriptor for a registered type. - #[deprecated( - since = "0.21.0", - note = "This will be replaced by `of_bound` in the future." - )] pub fn of<'py, T: Element>(py: Python<'py>) -> &'py Self { Self::of_bound::(py).into_gil_ref() } - /// Returns the type descriptor for a registered type. - pub fn of_bound<'py, T: Element>(py: Python<'py>) -> Bound<'py, Self> { - T::get_dtype_bound(py) - } - /// Returns true if two type descriptors are equivalent. pub fn is_equiv_to(&self, other: &Self) -> bool { self.as_borrowed().is_equiv_to(&other.as_borrowed()) } - fn from_npy_type<'py>(py: Python<'py>, npy_type: NPY_TYPES) -> Bound<'py, Self> { - unsafe { - let descr = PY_ARRAY_API.PyArray_DescrFromType(py, npy_type as _); - Bound::from_owned_ptr(py, descr.cast()).downcast_into_unchecked() - } - } - - pub(crate) fn new_from_npy_type<'py>(py: Python<'py>, npy_type: NPY_TYPES) -> Bound<'py, Self> { - unsafe { - let descr = PY_ARRAY_API.PyArray_DescrNewFromType(py, npy_type as _); - Bound::from_owned_ptr(py, descr.cast()).downcast_into_unchecked() - } - } - /// Returns the [array scalar][arrays-scalars] corresponding to this type descriptor. /// /// Equivalent to [`numpy.dtype.type`][dtype-type]. @@ -681,10 +672,7 @@ pub unsafe trait Element: Clone + Send { const IS_COPY: bool; /// Returns the associated type descriptor ("dtype") for the given element type. - #[deprecated( - since = "0.21.0", - note = "This will be replaced by `get_dtype_bound` in the future." - )] + #[cfg(feature = "gil-refs")] fn get_dtype<'py>(py: Python<'py>) -> &'py PyArrayDescr { Self::get_dtype_bound(py).into_gil_ref() } @@ -804,6 +792,7 @@ unsafe impl Element for PyObject { mod tests { use super::*; + use pyo3::types::PyString; use pyo3::{py_run, types::PyTypeMethods}; use crate::npyffi::NPY_NEEDS_PYAPI; @@ -831,7 +820,7 @@ mod tests { #[test] fn test_dtype_names() { - fn type_name<'py, T: Element>(py: Python<'py>) -> String { + fn type_name(py: Python) -> Bound { dtype_bound::(py).typeobj().qualname().unwrap() } Python::with_gil(|py| { diff --git a/src/lib.rs b/src/lib.rs index cc218dd18..44996ee5c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -106,7 +106,7 @@ pub use crate::borrow::{ PyReadwriteArray5, PyReadwriteArray6, PyReadwriteArrayDyn, }; pub use crate::convert::{IntoPyArray, NpyIndex, ToNpyDims, ToPyArray}; -#[allow(deprecated)] +#[cfg(feature = "gil-refs")] pub use crate::dtype::dtype; pub use crate::dtype::{ dtype_bound, Complex32, Complex64, Element, PyArrayDescr, PyArrayDescrMethods, @@ -114,7 +114,7 @@ pub use crate::dtype::{ pub use crate::error::{BorrowError, FromVecError, NotContiguousError}; pub use crate::npyffi::{PY_ARRAY_API, PY_UFUNC_API}; pub use crate::strings::{PyFixedString, PyFixedUnicode}; -#[allow(deprecated)] +#[cfg(feature = "gil-refs")] pub use crate::sum_products::{dot, einsum, inner}; pub use crate::sum_products::{dot_bound, einsum_bound, inner_bound}; pub use crate::untyped_array::{PyUntypedArray, PyUntypedArrayMethods}; diff --git a/src/strings.rs b/src/strings.rs index 74606289e..c38e4c1cb 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -190,7 +190,7 @@ impl TypeDescriptors { } }; - dtype.clone().into_bound(py) + dtype.bind(py).to_owned() } } diff --git a/src/sum_products.rs b/src/sum_products.rs index 32cff6203..3dd4a206e 100644 --- a/src/sum_products.rs +++ b/src/sum_products.rs @@ -4,7 +4,9 @@ use std::ptr::null_mut; use ndarray::{Dimension, IxDyn}; use pyo3::types::PyAnyMethods; -use pyo3::{Borrowed, Bound, FromPyObject, PyNativeType, PyResult}; +#[cfg(feature = "gil-refs")] +use pyo3::PyNativeType; +use pyo3::{Borrowed, Bound, FromPyObject, PyResult}; use crate::array::PyArray; use crate::dtype::Element; @@ -13,6 +15,7 @@ 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> {} +#[cfg(feature = "gil-refs")] impl<'py, T, D> ArrayOrScalar<'py, T> for &'py PyArray where T: Element, @@ -30,10 +33,7 @@ where impl<'py, T> ArrayOrScalar<'py, T> for T where T: Element + FromPyObject<'py> {} /// Deprecated form of [`inner_bound`] -#[deprecated( - since = "0.21.0", - note = "will be replaced by `inner_bound` in the future" -)] +#[cfg(feature = "gil-refs")] pub fn inner<'py, T, DIN1, DIN2, OUT>( array1: &'py PyArray, array2: &'py PyArray, @@ -100,10 +100,7 @@ where } /// Deprecated form of [`dot_bound`] -#[deprecated( - since = "0.21.0", - note = "will be replaced by `dot_bound` in the future" -)] +#[cfg(feature = "gil-refs")] pub fn dot<'py, T, DIN1, DIN2, OUT>( array1: &'py PyArray, array2: &'py PyArray, @@ -176,10 +173,7 @@ where } /// Deprecated form of [`einsum_bound`] -#[deprecated( - since = "0.21.0", - note = "will be replaced by `einsum_bound` in the future" -)] +#[cfg(feature = "gil-refs")] pub fn einsum<'py, T, OUT>(subscripts: &str, arrays: &[&'py PyArray]) -> PyResult where T: Element, @@ -226,10 +220,7 @@ where } /// Deprecated form of [`einsum_bound!`][crate::einsum_bound!] -#[deprecated( - since = "0.21.0", - note = "will be replaced by `einsum_bound!` in the future" -)] +#[cfg(feature = "gil-refs")] #[macro_export] macro_rules! einsum { ($subscripts:literal $(,$array:ident)+ $(,)*) => {{ diff --git a/src/untyped_array.rs b/src/untyped_array.rs index c51a89458..d70dfb5c4 100644 --- a/src/untyped_array.rs +++ b/src/untyped_array.rs @@ -3,9 +3,11 @@ //! [ndarray]: https://numpy.org/doc/stable/reference/arrays.ndarray.html use std::slice; +#[cfg(feature = "gil-refs")] +use pyo3::PyNativeType; use pyo3::{ ffi, pyobject_native_type_extract, pyobject_native_type_named, types::PyAnyMethods, - AsPyPointer, Bound, IntoPy, PyAny, PyNativeType, PyObject, PyTypeInfo, Python, + AsPyPointer, Bound, IntoPy, PyAny, PyObject, PyTypeInfo, Python, }; use crate::array::{PyArray, PyArrayMethods}; @@ -85,6 +87,7 @@ impl IntoPy for PyUntypedArray { pyobject_native_type_extract!(PyUntypedArray); +#[cfg(feature = "gil-refs")] impl PyUntypedArray { /// Returns a raw pointer to the underlying [`PyArrayObject`][npyffi::PyArrayObject]. #[inline] diff --git a/tests/array.rs b/tests/array.rs index 273173c79..f85bf8bce 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -259,6 +259,7 @@ fn from_vec3_ragged() { } #[test] +#[cfg(feature = "gil-refs")] fn extract_as_fixed() { Python::with_gil(|py| { let locals = get_np_locals(py); @@ -273,6 +274,7 @@ fn extract_as_fixed() { } #[test] +#[cfg(feature = "gil-refs")] fn extract_as_dyn() { Python::with_gil(|py| { let locals = get_np_locals(py); @@ -294,6 +296,7 @@ fn extract_as_dyn() { } #[test] +#[cfg(feature = "gil-refs")] fn extract_fail_by_check() { Python::with_gil(|py| { let locals = get_np_locals(py); @@ -311,6 +314,7 @@ fn extract_fail_by_check() { } #[test] +#[cfg(feature = "gil-refs")] fn extract_fail_by_dim() { Python::with_gil(|py| { let locals = get_np_locals(py); @@ -328,6 +332,7 @@ fn extract_fail_by_dim() { } #[test] +#[cfg(feature = "gil-refs")] fn extract_fail_by_dtype() { Python::with_gil(|py| { let locals = get_np_locals(py); @@ -474,6 +479,7 @@ fn unbind_works() { } #[test] +#[cfg(feature = "gil-refs")] fn to_owned_works() { let arr: Py> = Python::with_gil(|py| { let arr = PyArray::from_slice_bound(py, &[1_i32, 2, 3]);