diff --git a/README.md b/README.md index 459f748c2..aca402af3 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ fn main_<'py>(py: Python<'py>) -> PyResult<()> { let pyarray: &PyArray1 = py .eval("np.array([1, 2, 3], dtype='int32')", Some(&dict), None)? .extract()?; - let slice = pyarray.as_slice()?; + let slice = pyarray.as_slice(); assert_eq!(slice, &[1, 2, 3]); Ok(()) } @@ -95,7 +95,7 @@ extern crate numpy; extern crate pyo3; use ndarray::{ArrayD, ArrayViewD, ArrayViewMutD}; -use numpy::{IntoPyArray, IntoPyResult, PyArrayDyn}; +use numpy::{IntoPyArray, PyArrayDyn}; use pyo3::prelude::{pymodinit, PyModule, PyResult, Python}; #[pymodinit] @@ -119,16 +119,16 @@ fn rust_ext(_py: Python, m: &PyModule) -> PyResult<()> { y: &PyArrayDyn, ) -> PyResult> { // you can convert numpy error into PyErr via ? - let x = x.as_array()?; + let x = x.as_array(); // you can also specify your error context, via closure - let y = y.as_array().into_pyresult_with(|| "y must be f64 array")?; + let y = y.as_array(); Ok(axpy(a, x, y).into_pyarray(py).to_owned(py)) } // wrapper of `mult` #[pyfn(m, "mult")] fn mult_py(_py: Python, a: f64, x: &PyArrayDyn) -> PyResult<()> { - let x = x.as_array_mut()?; + let x = x.as_array_mut(); mult(a, x); Ok(()) } diff --git a/example/extensions/src/lib.rs b/example/extensions/src/lib.rs index 16930320d..126b78e7f 100644 --- a/example/extensions/src/lib.rs +++ b/example/extensions/src/lib.rs @@ -3,7 +3,7 @@ extern crate numpy; extern crate pyo3; use ndarray::{ArrayD, ArrayViewD, ArrayViewMutD}; -use numpy::{IntoPyArray, IntoPyResult, PyArrayDyn}; +use numpy::{IntoPyArray, PyArrayDyn}; use pyo3::prelude::{pymodinit, PyModule, PyResult, Python}; #[pymodinit] @@ -27,16 +27,16 @@ fn rust_ext(_py: Python, m: &PyModule) -> PyResult<()> { y: &PyArrayDyn, ) -> PyResult> { // you can convert numpy error into PyErr via ? - let x = x.as_array()?; + let x = x.as_array(); // you can also specify your error context, via closure - let y = y.as_array().into_pyresult_with(|| "y must be f64 array")?; + let y = y.as_array(); Ok(axpy(a, x, y).into_pyarray(py).to_owned(py)) } // wrapper of `mult` #[pyfn(m, "mult")] fn mult_py(_py: Python, a: f64, x: &PyArrayDyn) -> PyResult<()> { - let x = x.as_array_mut()?; + let x = x.as_array_mut(); mult(a, x); Ok(()) } diff --git a/src/array.rs b/src/array.rs index 5025f7856..bfa18e539 100644 --- a/src/array.rs +++ b/src/array.rs @@ -19,20 +19,21 @@ use types::{NpyDataType, TypeNum}; /// /// # Memory location /// -/// 1.`PyArray` constructed via `IntoPyArray::into_pyarray` or `PyArray::from_vec` -/// or `PyArray::from_owned_array` +/// - Case1: Constructed via [`IntoPyArray`](../convert/trait.IntoPyArray.html) or +/// [`from_vec`](#method.from_vec) or [`from_owned_array`](#method.from_owned_vec). /// -/// These methods don't allocate and use `Box<[T]>` as container. +/// These methods don't allocate and use `Box<[T]>` as a internal buffer. /// /// Please take care that **you cannot use some destructive methods like `resize`, /// for this kind of array**. /// -/// 2.`PyArray` constructed via other methods, like `ToPyArray::to_pyarray` or `PyArray::from_slice` -/// or `PyArray::from_array`. +/// - Case2: Constructed via other methods, like [`ToPyArray`](../convert/trait.ToPyArray.html) or +/// [`from_slice`](#method.from_slice) or [`from_array`](#from_array). /// /// These methods allocate a memory area in Python's private heap. /// -/// In this case, you have no restriction. +/// In both cases, **an internal buffer of `PyArray` is managed by Python GC.** +/// So you can neither retrieve it nor deallocate it manually. /// /// # Reference /// @@ -68,7 +69,7 @@ use types::{NpyDataType, TypeNum}; /// let pyarray = PyArray::arange(gil.python(), 0., 4., 1.).reshape([2, 2]).unwrap(); /// let array = array![[3., 4.], [5., 6.]]; /// assert_eq!( -/// array.dot(&pyarray.as_array().unwrap()), +/// array.dot(&pyarray.as_array()), /// array![[8., 15.], [12., 23.]] /// ); /// # } @@ -156,9 +157,6 @@ impl PyArray { /// You can use this method when you have to avoid lifetime annotation to your function args /// or return types, like used with pyo3's `pymethod`. /// - /// Since this method increases refcount, you can use `PyArray` even after `pyo3::GILGuard` - /// dropped, in most cases. - /// /// # Example /// ``` /// # extern crate pyo3; extern crate numpy; fn main() { @@ -170,7 +168,7 @@ impl PyArray { /// array.to_owned(gil.python()) /// } /// let array = return_py_array(); - /// assert_eq!(array.as_slice().unwrap(), &[0, 0, 0, 0, 0]); + /// assert_eq!(array.as_slice(), &[0, 0, 0, 0, 0]); /// # } /// ``` pub fn to_owned(&self, py: Python) -> Self { @@ -376,7 +374,7 @@ impl PyArray { /// use numpy::PyArray2; /// let gil = pyo3::Python::acquire_gil(); /// let pyarray = PyArray2::zeros(gil.python(), [2, 2], false); - /// assert_eq!(pyarray.as_array().unwrap(), array![[0, 0], [0, 0]]); + /// assert_eq!(pyarray.as_array(), array![[0, 0], [0, 0]]); /// # } /// ``` pub fn zeros<'py, ID>(py: Python<'py>, dims: ID, is_fortran: bool) -> &'py Self @@ -407,7 +405,7 @@ impl PyArray { /// use numpy::PyArray; /// let gil = pyo3::Python::acquire_gil(); /// let pyarray = PyArray::from_array(gil.python(), &array![[1, 2], [3, 4]]); - /// assert_eq!(pyarray.as_array().unwrap(), array![[1, 2], [3, 4]]); + /// assert_eq!(pyarray.as_array(), array![[1, 2], [3, 4]]); /// # } /// ``` pub fn from_array<'py, S>(py: Python<'py>, arr: &ArrayBase) -> &'py Self @@ -427,7 +425,7 @@ impl PyArray { /// use numpy::PyArray; /// let gil = pyo3::Python::acquire_gil(); /// let pyarray = PyArray::from_owned_array(gil.python(), array![[1, 2], [3, 4]]); - /// assert_eq!(pyarray.as_array().unwrap(), array![[1, 2], [3, 4]]); + /// assert_eq!(pyarray.as_array(), array![[1, 2], [3, 4]]); /// # } /// ``` pub fn from_owned_array<'py>(py: Python<'py>, arr: Array) -> &'py Self { @@ -443,25 +441,20 @@ impl PyArray { /// let gil = pyo3::Python::acquire_gil(); /// let py_array = PyArray::arange(gil.python(), 0, 4, 1).reshape([2, 2]).unwrap(); /// assert_eq!( - /// py_array.as_array().unwrap(), + /// py_array.as_array(), /// array![[0, 1], [2, 3]] /// ) /// # } /// ``` - pub fn as_array(&self) -> Result, ErrorKind> { - self.type_check()?; - unsafe { Ok(ArrayView::from_shape_ptr(self.ndarray_shape(), self.data())) } + pub fn as_array(&self) -> ArrayView { + self.type_check_assert(); + unsafe { ArrayView::from_shape_ptr(self.ndarray_shape(), self.data()) } } /// Almost same as [`as_array`](#method.as_array), but returns `ArrayViewMut`. - pub fn as_array_mut(&self) -> Result, ErrorKind> { - self.type_check()?; - unsafe { - Ok(ArrayViewMut::from_shape_ptr( - self.ndarray_shape(), - self.data(), - )) - } + pub fn as_array_mut(&self) -> ArrayViewMut { + self.type_check_assert(); + unsafe { ArrayViewMut::from_shape_ptr(self.ndarray_shape(), self.data()) } } /// Get an immutable reference of a specified element, without checking the @@ -574,7 +567,7 @@ impl PyArray { /// let gil = pyo3::Python::acquire_gil(); /// let array = [1, 2, 3, 4, 5]; /// let pyarray = PyArray::from_slice(gil.python(), &array); - /// assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3, 4, 5]); + /// assert_eq!(pyarray.as_slice(), &[1, 2, 3, 4, 5]); /// # } /// ``` pub fn from_slice<'py>(py: Python<'py>, slice: &[T]) -> &'py Self { @@ -594,7 +587,7 @@ impl PyArray { /// let gil = pyo3::Python::acquire_gil(); /// let vec = vec![1, 2, 3, 4, 5]; /// let pyarray = PyArray::from_vec(gil.python(), vec); - /// assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3, 4, 5]); + /// assert_eq!(pyarray.as_slice(), &[1, 2, 3, 4, 5]); /// # } /// ``` pub fn from_vec<'py>(py: Python<'py>, vec: Vec) -> &'py Self { @@ -611,7 +604,7 @@ impl PyArray { /// let gil = pyo3::Python::acquire_gil(); /// let vec = vec![1, 2, 3, 4, 5]; /// let pyarray = PyArray::from_iter(gil.python(), vec.iter().map(|&x| x)); - /// assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3, 4, 5]); + /// assert_eq!(pyarray.as_slice(), &[1, 2, 3, 4, 5]); /// # } /// ``` pub fn from_exact_iter(py: Python, iter: impl ExactSizeIterator) -> &Self { @@ -636,7 +629,7 @@ impl PyArray { /// let gil = pyo3::Python::acquire_gil(); /// let set: BTreeSet = [4, 3, 2, 5, 1].into_iter().cloned().collect(); /// let pyarray = PyArray::from_iter(gil.python(), set); - /// assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3, 4, 5]); + /// assert_eq!(pyarray.as_slice(), &[1, 2, 3, 4, 5]); /// # } /// ``` pub fn from_iter(py: Python, iter: impl IntoIterator) -> &Self { @@ -715,7 +708,7 @@ impl PyArray { /// let gil = pyo3::Python::acquire_gil(); /// let vec2 = vec![vec![1, 2, 3]; 2]; /// let pyarray = PyArray::from_vec2(gil.python(), &vec2).unwrap(); - /// assert_eq!(pyarray.as_array().unwrap(), array![[1, 2, 3], [1, 2, 3]]); + /// assert_eq!(pyarray.as_array(), array![[1, 2, 3], [1, 2, 3]]); /// assert!(PyArray::from_vec2(gil.python(), &vec![vec![1], vec![2, 3]]).is_err()); /// # } /// ``` @@ -757,7 +750,7 @@ impl PyArray { /// let vec2 = vec![vec![vec![1, 2]; 2]; 2]; /// let pyarray = PyArray::from_vec3(gil.python(), &vec2).unwrap(); /// assert_eq!( - /// pyarray.as_array().unwrap(), + /// pyarray.as_array(), /// array![[[1, 2], [1, 2]], [[1, 2], [1, 2]]] /// ); /// assert!(PyArray::from_vec3(gil.python(), &vec![vec![vec![1], vec![]]]).is_err()); @@ -802,6 +795,11 @@ impl PyArray { NpyDataType::from_i32(self.typenum()) } + fn type_check_assert(&self) { + let type_check = self.type_check(); + assert!(type_check.is_ok(), "{:?}", type_check); + } + fn type_check(&self) -> Result<(), ErrorKind> { let truth = self.typenum(); if T::is_same_type(truth) { @@ -818,18 +816,18 @@ impl PyArray { /// use numpy::PyArray; /// let gil = pyo3::Python::acquire_gil(); /// let py_array = PyArray::arange(gil.python(), 0, 4, 1).reshape([2, 2]).unwrap(); - /// assert_eq!(py_array.as_slice().unwrap(), &[0, 1, 2, 3]); + /// assert_eq!(py_array.as_slice(), &[0, 1, 2, 3]); /// # } /// ``` - pub fn as_slice(&self) -> Result<&[T], ErrorKind> { - self.type_check()?; - unsafe { Ok(::std::slice::from_raw_parts(self.data(), self.len())) } + pub fn as_slice(&self) -> &[T] { + self.type_check_assert(); + unsafe { ::std::slice::from_raw_parts(self.data(), self.len()) } } /// Get the mmutable view of the internal data of `PyArray`, as slice. - pub fn as_slice_mut(&self) -> Result<&mut [T], ErrorKind> { - self.type_check()?; - unsafe { Ok(::std::slice::from_raw_parts_mut(self.data(), self.len())) } + pub fn as_slice_mut(&self) -> &mut [T] { + self.type_check_assert(); + unsafe { ::std::slice::from_raw_parts_mut(self.data(), self.len()) } } /// Copies self into `other`, performing a data-type conversion if necessary. @@ -841,7 +839,7 @@ impl PyArray { /// let pyarray_f = PyArray::arange(gil.python(), 2.0, 5.0, 1.0); /// let pyarray_i = PyArray::::new(gil.python(), [3], false); /// assert!(pyarray_f.copy_to(pyarray_i).is_ok()); - /// assert_eq!(pyarray_i.as_slice().unwrap(), &[2, 3, 4]); + /// assert_eq!(pyarray_i.as_slice(), &[2, 3, 4]); /// # } pub fn copy_to(&self, other: &PyArray) -> Result<(), ErrorKind> { let self_ptr = self.as_array_ptr(); @@ -862,7 +860,7 @@ impl PyArray { /// let gil = pyo3::Python::acquire_gil(); /// let pyarray_f = PyArray::arange(gil.python(), 2.0, 5.0, 1.0); /// let pyarray_i = pyarray_f.cast::(false).unwrap(); - /// assert_eq!(pyarray_i.as_slice().unwrap(), &[2, 3, 4]); + /// assert_eq!(pyarray_i.as_slice(), &[2, 3, 4]); /// # } pub fn cast<'py, U: TypeNum>( &'py self, @@ -897,7 +895,7 @@ impl PyArray { /// let gil = pyo3::Python::acquire_gil(); /// let array = PyArray::from_exact_iter(gil.python(), 0..9); /// let array = array.reshape([3, 3]).unwrap(); - /// assert_eq!(array.as_array().unwrap(), array![[0, 1, 2], [3, 4, 5], [6, 7, 8]]); + /// assert_eq!(array.as_array(), array![[0, 1, 2], [3, 4, 5], [6, 7, 8]]); /// assert!(array.reshape([5]).is_err()); /// # } /// ``` @@ -949,9 +947,9 @@ impl> PyArray { /// use numpy::PyArray; /// let gil = pyo3::Python::acquire_gil(); /// let pyarray = PyArray::arange(gil.python(), 2.0, 4.0, 0.5); - /// assert_eq!(pyarray.as_slice().unwrap(), &[2.0, 2.5, 3.0, 3.5]); + /// assert_eq!(pyarray.as_slice(), &[2.0, 2.5, 3.0, 3.5]); /// let pyarray = PyArray::arange(gil.python(), -2, 4, 3); - /// assert_eq!(pyarray.as_slice().unwrap(), &[-2, 1]); + /// assert_eq!(pyarray.as_slice(), &[-2, 1]); /// # } pub fn arange<'py>(py: Python<'py>, start: T, stop: T, step: T) -> &'py Self { unsafe { diff --git a/src/convert.rs b/src/convert.rs index 3c2a00125..643e24659 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -23,7 +23,7 @@ use npyffi::npy_intp; /// use numpy::{PyArray, IntoPyArray}; /// let gil = pyo3::Python::acquire_gil(); /// let py_array = vec![1, 2, 3].into_pyarray(gil.python()); -/// assert_eq!(py_array.as_slice().unwrap(), &[1, 2, 3]); +/// assert_eq!(py_array.as_slice(), &[1, 2, 3]); /// assert!(py_array.resize(100).is_err()); // You can't resize owned-by-rust array. /// # } /// ``` @@ -75,7 +75,7 @@ where /// use numpy::{PyArray, ToPyArray}; /// let gil = pyo3::Python::acquire_gil(); /// let py_array = vec![1, 2, 3].to_pyarray(gil.python()); -/// assert_eq!(py_array.as_slice().unwrap(), &[1, 2, 3]); +/// assert_eq!(py_array.as_slice(), &[1, 2, 3]); /// # } /// ``` pub trait ToPyArray { diff --git a/src/lib.rs b/src/lib.rs index 2d7fd22d8..17d9c6654 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,7 @@ //! let py = gil.python(); //! let py_array = array![[1i64, 2], [3, 4]].to_pyarray(py); //! assert_eq!( -//! py_array.as_array().unwrap(), +//! py_array.as_array(), //! array![[1i64, 2], [3, 4]] //! ); //! } diff --git a/src/npyffi/array.rs b/src/npyffi/array.rs index 7ac4f0748..9bfa1b150 100644 --- a/src/npyffi/array.rs +++ b/src/npyffi/array.rs @@ -24,13 +24,11 @@ const CAPSULE_NAME: &str = "_ARRAY_API"; /// use numpy::{PyArray, npyffi::types::NPY_SORTKIND, PY_ARRAY_API}; /// use pyo3::Python; /// let gil = Python::acquire_gil(); -/// let array = PyArray::arange(gil.python(), 2, 5, 1); -/// array.as_slice_mut().unwrap().swap(0, 1); -/// assert_eq!(array.as_slice().unwrap(), &[3, 2, 4]); +/// let array = PyArray::from_slice(gil.python(), &[3, 2, 4]); /// unsafe { /// PY_ARRAY_API.PyArray_Sort(array.as_array_ptr(), 0, NPY_SORTKIND::NPY_QUICKSORT); /// } -/// assert_eq!(array.as_slice().unwrap(), &[2, 3, 4]) +/// assert_eq!(array.as_slice(), &[2, 3, 4]) /// # } /// ``` pub static PY_ARRAY_API: PyArrayAPI = PyArrayAPI { diff --git a/tests/array.rs b/tests/array.rs index c23cf3d6e..54716952c 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -59,14 +59,14 @@ fn arange() { let arr = PyArray::::arange(gil.python(), 0.0, 1.0, 0.1); println!("ndim = {:?}", arr.ndim()); println!("dims = {:?}", arr.dims()); - println!("array = {:?}", arr.as_slice().unwrap()); + println!("array = {:?}", arr.as_slice()); } #[test] fn as_array() { let gil = pyo3::Python::acquire_gil(); let arr = PyArray::::zeros(gil.python(), [3, 2, 4], false); - let a = arr.as_array().unwrap(); + let a = arr.as_array(); assert_eq!(arr.shape(), a.shape()); assert_eq!( arr.strides().iter().map(|x| x / 8).collect::>(), @@ -81,7 +81,7 @@ fn to_pyarray_vec() { let a = vec![1, 2, 3]; let arr = a.to_pyarray(gil.python()); println!("arr.shape = {:?}", arr.shape()); - println!("arr = {:?}", arr.as_slice().unwrap()); + println!("arr = {:?}", arr.as_slice()); assert_eq!(arr.shape(), [3]); } @@ -105,17 +105,14 @@ fn to_pyarray_array() { fn iter_to_pyarray() { let gil = pyo3::Python::acquire_gil(); let arr = PyArray::from_iter(gil.python(), (0..10).map(|x| x * x)); - assert_eq!( - arr.as_slice().unwrap(), - &[0, 1, 4, 9, 16, 25, 36, 49, 64, 81] - ); + assert_eq!(arr.as_slice(), &[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]); } #[test] fn long_iter_to_pyarray() { let gil = pyo3::Python::acquire_gil(); let arr = PyArray::from_iter(gil.python(), (0u32..512).map(|x| x)); - let slice = arr.as_slice().unwrap(); + let slice = arr.as_slice(); for (i, &elem) in slice.iter().enumerate() { assert_eq!(i as u32, elem); } @@ -135,7 +132,7 @@ fn from_vec2() { let vec2 = vec![vec![1, 2, 3]; 2]; let gil = pyo3::Python::acquire_gil(); let pyarray = PyArray::from_vec2(gil.python(), &vec2).unwrap(); - assert_eq!(pyarray.as_array().unwrap(), array![[1, 2, 3], [1, 2, 3]]); + assert_eq!(pyarray.as_array(), array![[1, 2, 3], [1, 2, 3]]); assert!(PyArray::from_vec2(gil.python(), &vec![vec![1], vec![2, 3]]).is_err()); } @@ -145,7 +142,7 @@ fn from_vec3() { let vec3 = vec![vec![vec![1, 2]; 2]; 2]; let pyarray = PyArray::from_vec3(gil.python(), &vec3).unwrap(); assert_eq!( - pyarray.as_array().unwrap(), + pyarray.as_array(), array![[[1, 2], [1, 2]], [[1, 2], [1, 2]]] ); } @@ -162,7 +159,7 @@ fn from_eval() { .unwrap() .extract() .unwrap(); - assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3]); + assert_eq!(pyarray.as_slice(), &[1, 2, 3]); } #[test] @@ -188,7 +185,7 @@ macro_rules! small_array_test { let array: [$t; 2] = [$t::min_value(), $t::max_value()]; let pyarray = array.to_pyarray(gil.python()); assert_eq!( - pyarray.as_slice().unwrap(), + pyarray.as_slice(), &[$t::min_value(), $t::max_value()] ); })+ @@ -204,7 +201,7 @@ fn array_cast() { let vec2 = vec![vec![1.0, 2.0, 3.0]; 2]; let arr_f64 = PyArray::from_vec2(gil.python(), &vec2).unwrap(); let arr_i32: &PyArray2 = arr_f64.cast(false).unwrap(); - assert_eq!(arr_i32.as_array().unwrap(), array![[1, 2, 3], [1, 2, 3]]); + assert_eq!(arr_i32.as_array(), array![[1, 2, 3], [1, 2, 3]]); } #[test] @@ -212,7 +209,7 @@ fn into_pyarray_vec() { let gil = pyo3::Python::acquire_gil(); let a = vec![1, 2, 3]; let arr = a.into_pyarray(gil.python()); - assert_eq!(arr.as_slice().unwrap(), &[1, 2, 3]) + assert_eq!(arr.as_slice(), &[1, 2, 3]) } #[test]