Skip to content

Commit 2a662f5

Browse files
authored
Merge pull request #75 from kngwyu/as_return_noresult
Not return result in as_array & as_slice
2 parents 31ca599 + e057ed0 commit 2a662f5

File tree

7 files changed

+67
-74
lines changed

7 files changed

+67
-74
lines changed

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ fn main_<'py>(py: Python<'py>) -> PyResult<()> {
6565
let pyarray: &PyArray1<i32> = py
6666
.eval("np.array([1, 2, 3], dtype='int32')", Some(&dict), None)?
6767
.extract()?;
68-
let slice = pyarray.as_slice()?;
68+
let slice = pyarray.as_slice();
6969
assert_eq!(slice, &[1, 2, 3]);
7070
Ok(())
7171
}
@@ -95,7 +95,7 @@ extern crate numpy;
9595
extern crate pyo3;
9696

9797
use ndarray::{ArrayD, ArrayViewD, ArrayViewMutD};
98-
use numpy::{IntoPyArray, IntoPyResult, PyArrayDyn};
98+
use numpy::{IntoPyArray, PyArrayDyn};
9999
use pyo3::prelude::{pymodinit, PyModule, PyResult, Python};
100100

101101
#[pymodinit]
@@ -119,16 +119,16 @@ fn rust_ext(_py: Python, m: &PyModule) -> PyResult<()> {
119119
y: &PyArrayDyn<f64>,
120120
) -> PyResult<PyArrayDyn<f64>> {
121121
// you can convert numpy error into PyErr via ?
122-
let x = x.as_array()?;
122+
let x = x.as_array();
123123
// you can also specify your error context, via closure
124-
let y = y.as_array().into_pyresult_with(|| "y must be f64 array")?;
124+
let y = y.as_array();
125125
Ok(axpy(a, x, y).into_pyarray(py).to_owned(py))
126126
}
127127

128128
// wrapper of `mult`
129129
#[pyfn(m, "mult")]
130130
fn mult_py(_py: Python, a: f64, x: &PyArrayDyn<f64>) -> PyResult<()> {
131-
let x = x.as_array_mut()?;
131+
let x = x.as_array_mut();
132132
mult(a, x);
133133
Ok(())
134134
}

example/extensions/src/lib.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ extern crate numpy;
33
extern crate pyo3;
44

55
use ndarray::{ArrayD, ArrayViewD, ArrayViewMutD};
6-
use numpy::{IntoPyArray, IntoPyResult, PyArrayDyn};
6+
use numpy::{IntoPyArray, PyArrayDyn};
77
use pyo3::prelude::{pymodinit, PyModule, PyResult, Python};
88

99
#[pymodinit]
@@ -27,16 +27,16 @@ fn rust_ext(_py: Python, m: &PyModule) -> PyResult<()> {
2727
y: &PyArrayDyn<f64>,
2828
) -> PyResult<PyArrayDyn<f64>> {
2929
// you can convert numpy error into PyErr via ?
30-
let x = x.as_array()?;
30+
let x = x.as_array();
3131
// you can also specify your error context, via closure
32-
let y = y.as_array().into_pyresult_with(|| "y must be f64 array")?;
32+
let y = y.as_array();
3333
Ok(axpy(a, x, y).into_pyarray(py).to_owned(py))
3434
}
3535

3636
// wrapper of `mult`
3737
#[pyfn(m, "mult")]
3838
fn mult_py(_py: Python, a: f64, x: &PyArrayDyn<f64>) -> PyResult<()> {
39-
let x = x.as_array_mut()?;
39+
let x = x.as_array_mut();
4040
mult(a, x);
4141
Ok(())
4242
}

src/array.rs

+42-44
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,21 @@ use types::{NpyDataType, TypeNum};
1919
///
2020
/// # Memory location
2121
///
22-
/// 1.`PyArray` constructed via `IntoPyArray::into_pyarray` or `PyArray::from_vec`
23-
/// or `PyArray::from_owned_array`
22+
/// - Case1: Constructed via [`IntoPyArray`](../convert/trait.IntoPyArray.html) or
23+
/// [`from_vec`](#method.from_vec) or [`from_owned_array`](#method.from_owned_vec).
2424
///
25-
/// These methods don't allocate and use `Box<[T]>` as container.
25+
/// These methods don't allocate and use `Box<[T]>` as a internal buffer.
2626
///
2727
/// Please take care that **you cannot use some destructive methods like `resize`,
2828
/// for this kind of array**.
2929
///
30-
/// 2.`PyArray` constructed via other methods, like `ToPyArray::to_pyarray` or `PyArray::from_slice`
31-
/// or `PyArray::from_array`.
30+
/// - Case2: Constructed via other methods, like [`ToPyArray`](../convert/trait.ToPyArray.html) or
31+
/// [`from_slice`](#method.from_slice) or [`from_array`](#from_array).
3232
///
3333
/// These methods allocate a memory area in Python's private heap.
3434
///
35-
/// In this case, you have no restriction.
35+
/// In both cases, **an internal buffer of `PyArray` is managed by Python GC.**
36+
/// So you can neither retrieve it nor deallocate it manually.
3637
///
3738
/// # Reference
3839
///
@@ -68,7 +69,7 @@ use types::{NpyDataType, TypeNum};
6869
/// let pyarray = PyArray::arange(gil.python(), 0., 4., 1.).reshape([2, 2]).unwrap();
6970
/// let array = array![[3., 4.], [5., 6.]];
7071
/// assert_eq!(
71-
/// array.dot(&pyarray.as_array().unwrap()),
72+
/// array.dot(&pyarray.as_array()),
7273
/// array![[8., 15.], [12., 23.]]
7374
/// );
7475
/// # }
@@ -156,9 +157,6 @@ impl<T, D> PyArray<T, D> {
156157
/// You can use this method when you have to avoid lifetime annotation to your function args
157158
/// or return types, like used with pyo3's `pymethod`.
158159
///
159-
/// Since this method increases refcount, you can use `PyArray` even after `pyo3::GILGuard`
160-
/// dropped, in most cases.
161-
///
162160
/// # Example
163161
/// ```
164162
/// # extern crate pyo3; extern crate numpy; fn main() {
@@ -170,7 +168,7 @@ impl<T, D> PyArray<T, D> {
170168
/// array.to_owned(gil.python())
171169
/// }
172170
/// let array = return_py_array();
173-
/// assert_eq!(array.as_slice().unwrap(), &[0, 0, 0, 0, 0]);
171+
/// assert_eq!(array.as_slice(), &[0, 0, 0, 0, 0]);
174172
/// # }
175173
/// ```
176174
pub fn to_owned(&self, py: Python) -> Self {
@@ -376,7 +374,7 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
376374
/// use numpy::PyArray2;
377375
/// let gil = pyo3::Python::acquire_gil();
378376
/// let pyarray = PyArray2::zeros(gil.python(), [2, 2], false);
379-
/// assert_eq!(pyarray.as_array().unwrap(), array![[0, 0], [0, 0]]);
377+
/// assert_eq!(pyarray.as_array(), array![[0, 0], [0, 0]]);
380378
/// # }
381379
/// ```
382380
pub fn zeros<'py, ID>(py: Python<'py>, dims: ID, is_fortran: bool) -> &'py Self
@@ -407,7 +405,7 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
407405
/// use numpy::PyArray;
408406
/// let gil = pyo3::Python::acquire_gil();
409407
/// let pyarray = PyArray::from_array(gil.python(), &array![[1, 2], [3, 4]]);
410-
/// assert_eq!(pyarray.as_array().unwrap(), array![[1, 2], [3, 4]]);
408+
/// assert_eq!(pyarray.as_array(), array![[1, 2], [3, 4]]);
411409
/// # }
412410
/// ```
413411
pub fn from_array<'py, S>(py: Python<'py>, arr: &ArrayBase<S, D>) -> &'py Self
@@ -427,7 +425,7 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
427425
/// use numpy::PyArray;
428426
/// let gil = pyo3::Python::acquire_gil();
429427
/// let pyarray = PyArray::from_owned_array(gil.python(), array![[1, 2], [3, 4]]);
430-
/// assert_eq!(pyarray.as_array().unwrap(), array![[1, 2], [3, 4]]);
428+
/// assert_eq!(pyarray.as_array(), array![[1, 2], [3, 4]]);
431429
/// # }
432430
/// ```
433431
pub fn from_owned_array<'py>(py: Python<'py>, arr: Array<T, D>) -> &'py Self {
@@ -443,25 +441,20 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
443441
/// let gil = pyo3::Python::acquire_gil();
444442
/// let py_array = PyArray::arange(gil.python(), 0, 4, 1).reshape([2, 2]).unwrap();
445443
/// assert_eq!(
446-
/// py_array.as_array().unwrap(),
444+
/// py_array.as_array(),
447445
/// array![[0, 1], [2, 3]]
448446
/// )
449447
/// # }
450448
/// ```
451-
pub fn as_array(&self) -> Result<ArrayView<T, D>, ErrorKind> {
452-
self.type_check()?;
453-
unsafe { Ok(ArrayView::from_shape_ptr(self.ndarray_shape(), self.data())) }
449+
pub fn as_array(&self) -> ArrayView<T, D> {
450+
self.type_check_assert();
451+
unsafe { ArrayView::from_shape_ptr(self.ndarray_shape(), self.data()) }
454452
}
455453

456454
/// Almost same as [`as_array`](#method.as_array), but returns `ArrayViewMut`.
457-
pub fn as_array_mut(&self) -> Result<ArrayViewMut<T, D>, ErrorKind> {
458-
self.type_check()?;
459-
unsafe {
460-
Ok(ArrayViewMut::from_shape_ptr(
461-
self.ndarray_shape(),
462-
self.data(),
463-
))
464-
}
455+
pub fn as_array_mut(&self) -> ArrayViewMut<T, D> {
456+
self.type_check_assert();
457+
unsafe { ArrayViewMut::from_shape_ptr(self.ndarray_shape(), self.data()) }
465458
}
466459

467460
/// Get an immutable reference of a specified element, without checking the
@@ -574,7 +567,7 @@ impl<T: TypeNum> PyArray<T, Ix1> {
574567
/// let gil = pyo3::Python::acquire_gil();
575568
/// let array = [1, 2, 3, 4, 5];
576569
/// let pyarray = PyArray::from_slice(gil.python(), &array);
577-
/// assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3, 4, 5]);
570+
/// assert_eq!(pyarray.as_slice(), &[1, 2, 3, 4, 5]);
578571
/// # }
579572
/// ```
580573
pub fn from_slice<'py>(py: Python<'py>, slice: &[T]) -> &'py Self {
@@ -594,7 +587,7 @@ impl<T: TypeNum> PyArray<T, Ix1> {
594587
/// let gil = pyo3::Python::acquire_gil();
595588
/// let vec = vec![1, 2, 3, 4, 5];
596589
/// let pyarray = PyArray::from_vec(gil.python(), vec);
597-
/// assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3, 4, 5]);
590+
/// assert_eq!(pyarray.as_slice(), &[1, 2, 3, 4, 5]);
598591
/// # }
599592
/// ```
600593
pub fn from_vec<'py>(py: Python<'py>, vec: Vec<T>) -> &'py Self {
@@ -611,7 +604,7 @@ impl<T: TypeNum> PyArray<T, Ix1> {
611604
/// let gil = pyo3::Python::acquire_gil();
612605
/// let vec = vec![1, 2, 3, 4, 5];
613606
/// let pyarray = PyArray::from_iter(gil.python(), vec.iter().map(|&x| x));
614-
/// assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3, 4, 5]);
607+
/// assert_eq!(pyarray.as_slice(), &[1, 2, 3, 4, 5]);
615608
/// # }
616609
/// ```
617610
pub fn from_exact_iter(py: Python, iter: impl ExactSizeIterator<Item = T>) -> &Self {
@@ -636,7 +629,7 @@ impl<T: TypeNum> PyArray<T, Ix1> {
636629
/// let gil = pyo3::Python::acquire_gil();
637630
/// let set: BTreeSet<u32> = [4, 3, 2, 5, 1].into_iter().cloned().collect();
638631
/// let pyarray = PyArray::from_iter(gil.python(), set);
639-
/// assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3, 4, 5]);
632+
/// assert_eq!(pyarray.as_slice(), &[1, 2, 3, 4, 5]);
640633
/// # }
641634
/// ```
642635
pub fn from_iter(py: Python, iter: impl IntoIterator<Item = T>) -> &Self {
@@ -715,7 +708,7 @@ impl<T: TypeNum> PyArray<T, Ix2> {
715708
/// let gil = pyo3::Python::acquire_gil();
716709
/// let vec2 = vec![vec![1, 2, 3]; 2];
717710
/// let pyarray = PyArray::from_vec2(gil.python(), &vec2).unwrap();
718-
/// assert_eq!(pyarray.as_array().unwrap(), array![[1, 2, 3], [1, 2, 3]]);
711+
/// assert_eq!(pyarray.as_array(), array![[1, 2, 3], [1, 2, 3]]);
719712
/// assert!(PyArray::from_vec2(gil.python(), &vec![vec![1], vec![2, 3]]).is_err());
720713
/// # }
721714
/// ```
@@ -757,7 +750,7 @@ impl<T: TypeNum> PyArray<T, Ix3> {
757750
/// let vec2 = vec![vec![vec![1, 2]; 2]; 2];
758751
/// let pyarray = PyArray::from_vec3(gil.python(), &vec2).unwrap();
759752
/// assert_eq!(
760-
/// pyarray.as_array().unwrap(),
753+
/// pyarray.as_array(),
761754
/// array![[[1, 2], [1, 2]], [[1, 2], [1, 2]]]
762755
/// );
763756
/// assert!(PyArray::from_vec3(gil.python(), &vec![vec![vec![1], vec![]]]).is_err());
@@ -802,6 +795,11 @@ impl<T: TypeNum, D> PyArray<T, D> {
802795
NpyDataType::from_i32(self.typenum())
803796
}
804797

798+
fn type_check_assert(&self) {
799+
let type_check = self.type_check();
800+
assert!(type_check.is_ok(), "{:?}", type_check);
801+
}
802+
805803
fn type_check(&self) -> Result<(), ErrorKind> {
806804
let truth = self.typenum();
807805
if T::is_same_type(truth) {
@@ -818,18 +816,18 @@ impl<T: TypeNum, D> PyArray<T, D> {
818816
/// use numpy::PyArray;
819817
/// let gil = pyo3::Python::acquire_gil();
820818
/// let py_array = PyArray::arange(gil.python(), 0, 4, 1).reshape([2, 2]).unwrap();
821-
/// assert_eq!(py_array.as_slice().unwrap(), &[0, 1, 2, 3]);
819+
/// assert_eq!(py_array.as_slice(), &[0, 1, 2, 3]);
822820
/// # }
823821
/// ```
824-
pub fn as_slice(&self) -> Result<&[T], ErrorKind> {
825-
self.type_check()?;
826-
unsafe { Ok(::std::slice::from_raw_parts(self.data(), self.len())) }
822+
pub fn as_slice(&self) -> &[T] {
823+
self.type_check_assert();
824+
unsafe { ::std::slice::from_raw_parts(self.data(), self.len()) }
827825
}
828826

829827
/// Get the mmutable view of the internal data of `PyArray`, as slice.
830-
pub fn as_slice_mut(&self) -> Result<&mut [T], ErrorKind> {
831-
self.type_check()?;
832-
unsafe { Ok(::std::slice::from_raw_parts_mut(self.data(), self.len())) }
828+
pub fn as_slice_mut(&self) -> &mut [T] {
829+
self.type_check_assert();
830+
unsafe { ::std::slice::from_raw_parts_mut(self.data(), self.len()) }
833831
}
834832

835833
/// Copies self into `other`, performing a data-type conversion if necessary.
@@ -841,7 +839,7 @@ impl<T: TypeNum, D> PyArray<T, D> {
841839
/// let pyarray_f = PyArray::arange(gil.python(), 2.0, 5.0, 1.0);
842840
/// let pyarray_i = PyArray::<i64, _>::new(gil.python(), [3], false);
843841
/// assert!(pyarray_f.copy_to(pyarray_i).is_ok());
844-
/// assert_eq!(pyarray_i.as_slice().unwrap(), &[2, 3, 4]);
842+
/// assert_eq!(pyarray_i.as_slice(), &[2, 3, 4]);
845843
/// # }
846844
pub fn copy_to<U: TypeNum>(&self, other: &PyArray<U, D>) -> Result<(), ErrorKind> {
847845
let self_ptr = self.as_array_ptr();
@@ -862,7 +860,7 @@ impl<T: TypeNum, D> PyArray<T, D> {
862860
/// let gil = pyo3::Python::acquire_gil();
863861
/// let pyarray_f = PyArray::arange(gil.python(), 2.0, 5.0, 1.0);
864862
/// let pyarray_i = pyarray_f.cast::<i32>(false).unwrap();
865-
/// assert_eq!(pyarray_i.as_slice().unwrap(), &[2, 3, 4]);
863+
/// assert_eq!(pyarray_i.as_slice(), &[2, 3, 4]);
866864
/// # }
867865
pub fn cast<'py, U: TypeNum>(
868866
&'py self,
@@ -897,7 +895,7 @@ impl<T: TypeNum, D> PyArray<T, D> {
897895
/// let gil = pyo3::Python::acquire_gil();
898896
/// let array = PyArray::from_exact_iter(gil.python(), 0..9);
899897
/// let array = array.reshape([3, 3]).unwrap();
900-
/// assert_eq!(array.as_array().unwrap(), array![[0, 1, 2], [3, 4, 5], [6, 7, 8]]);
898+
/// assert_eq!(array.as_array(), array![[0, 1, 2], [3, 4, 5], [6, 7, 8]]);
901899
/// assert!(array.reshape([5]).is_err());
902900
/// # }
903901
/// ```
@@ -949,9 +947,9 @@ impl<T: TypeNum + AsPrimitive<f64>> PyArray<T, Ix1> {
949947
/// use numpy::PyArray;
950948
/// let gil = pyo3::Python::acquire_gil();
951949
/// let pyarray = PyArray::arange(gil.python(), 2.0, 4.0, 0.5);
952-
/// assert_eq!(pyarray.as_slice().unwrap(), &[2.0, 2.5, 3.0, 3.5]);
950+
/// assert_eq!(pyarray.as_slice(), &[2.0, 2.5, 3.0, 3.5]);
953951
/// let pyarray = PyArray::arange(gil.python(), -2, 4, 3);
954-
/// assert_eq!(pyarray.as_slice().unwrap(), &[-2, 1]);
952+
/// assert_eq!(pyarray.as_slice(), &[-2, 1]);
955953
/// # }
956954
pub fn arange<'py>(py: Python<'py>, start: T, stop: T, step: T) -> &'py Self {
957955
unsafe {

src/convert.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use npyffi::npy_intp;
2323
/// use numpy::{PyArray, IntoPyArray};
2424
/// let gil = pyo3::Python::acquire_gil();
2525
/// let py_array = vec![1, 2, 3].into_pyarray(gil.python());
26-
/// assert_eq!(py_array.as_slice().unwrap(), &[1, 2, 3]);
26+
/// assert_eq!(py_array.as_slice(), &[1, 2, 3]);
2727
/// assert!(py_array.resize(100).is_err()); // You can't resize owned-by-rust array.
2828
/// # }
2929
/// ```
@@ -75,7 +75,7 @@ where
7575
/// use numpy::{PyArray, ToPyArray};
7676
/// let gil = pyo3::Python::acquire_gil();
7777
/// let py_array = vec![1, 2, 3].to_pyarray(gil.python());
78-
/// assert_eq!(py_array.as_slice().unwrap(), &[1, 2, 3]);
78+
/// assert_eq!(py_array.as_slice(), &[1, 2, 3]);
7979
/// # }
8080
/// ```
8181
pub trait ToPyArray {

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
//! let py = gil.python();
2626
//! let py_array = array![[1i64, 2], [3, 4]].to_pyarray(py);
2727
//! assert_eq!(
28-
//! py_array.as_array().unwrap(),
28+
//! py_array.as_array(),
2929
//! array![[1i64, 2], [3, 4]]
3030
//! );
3131
//! }

src/npyffi/array.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,11 @@ const CAPSULE_NAME: &str = "_ARRAY_API";
2424
/// use numpy::{PyArray, npyffi::types::NPY_SORTKIND, PY_ARRAY_API};
2525
/// use pyo3::Python;
2626
/// let gil = Python::acquire_gil();
27-
/// let array = PyArray::arange(gil.python(), 2, 5, 1);
28-
/// array.as_slice_mut().unwrap().swap(0, 1);
29-
/// assert_eq!(array.as_slice().unwrap(), &[3, 2, 4]);
27+
/// let array = PyArray::from_slice(gil.python(), &[3, 2, 4]);
3028
/// unsafe {
3129
/// PY_ARRAY_API.PyArray_Sort(array.as_array_ptr(), 0, NPY_SORTKIND::NPY_QUICKSORT);
3230
/// }
33-
/// assert_eq!(array.as_slice().unwrap(), &[2, 3, 4])
31+
/// assert_eq!(array.as_slice(), &[2, 3, 4])
3432
/// # }
3533
/// ```
3634
pub static PY_ARRAY_API: PyArrayAPI = PyArrayAPI {

0 commit comments

Comments
 (0)