Skip to content

Commit 323a3e7

Browse files
authored
Merge pull request #139 from kngwyu/refactor-errors
Refactor error types
2 parents 60bdaad + 20602b3 commit 323a3e7

File tree

5 files changed

+100
-128
lines changed

5 files changed

+100
-128
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# Changelog
2+
- v0.10.0
3+
- Remove `ErrorKind` and introduce some concrete error types
4+
25
- v0.9.0
36
- Update PyO3 to 0.10.0
47

examples/simple-extension/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![deny(rust_2018_idioms)]
21
use ndarray::{ArrayD, ArrayViewD, ArrayViewMutD};
32
use numpy::{IntoPyArray, PyArrayDyn};
43
use pyo3::prelude::{pymodule, Py, PyModule, PyResult, Python};

src/array.rs

Lines changed: 32 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ use crate::npyffi::{self, npy_intp, NPY_ORDER, PY_ARRAY_API};
33
use ndarray::*;
44
use num_traits::AsPrimitive;
55
use pyo3::{ffi, prelude::*, type_object, types::PyAny};
6-
use pyo3::{AsPyPointer, PyDowncastError, PyNativeType};
6+
use pyo3::{AsPyPointer, PyDowncastError, PyNativeType, PyResult};
77
use std::{iter::ExactSizeIterator, marker::PhantomData};
88
use std::{mem, os::raw::c_int, ptr, slice};
99

1010
use crate::convert::{IntoPyArray, NpyIndex, ToNpyDims, ToPyArray};
11-
use crate::error::{ErrorKind, IntoPyResult};
11+
use crate::error::{FromVecError, NotContiguousError, ShapeError};
1212
use crate::slice_box::SliceBox;
1313
use crate::types::{NpyDataType, TypeNum};
1414

@@ -127,10 +127,8 @@ impl<'a, T: TypeNum, D: Dimension> FromPyObject<'a> for &'a PyArray<T, D> {
127127
}
128128
&*(ob as *const PyAny as *const PyArray<T, D>)
129129
};
130-
array
131-
.type_check()
132-
.map(|_| array)
133-
.into_pyresult_with(|| "[FromPyObject::extract] typecheck failed")
130+
array.type_check()?;
131+
Ok(array)
134132
}
135133
}
136134

@@ -443,27 +441,25 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
443441
/// let py_array = PyArray::arange(py, 0, 4, 1).reshape([2, 2]).unwrap();
444442
/// assert_eq!(py_array.as_slice().unwrap(), &[0, 1, 2, 3]);
445443
/// let locals = [("np", numpy::get_array_module(py).unwrap())].into_py_dict(py);
446-
/// let not_contiguous: &PyArray1<f32> = py
447-
/// .eval("np.zeros((3, 5))[[0, 2], [3, 4]]", Some(locals), None)
444+
/// let not_contiguous: &PyArray1<i32> = py
445+
/// .eval("np.arange(10)[::2]", Some(locals), None)
448446
/// .unwrap()
449447
/// .downcast()
450448
/// .unwrap();
451449
/// assert!(not_contiguous.as_slice().is_err());
452450
/// ```
453-
pub fn as_slice(&self) -> Result<&[T], ErrorKind> {
454-
self.type_check()?;
451+
pub fn as_slice(&self) -> Result<&[T], NotContiguousError> {
455452
if !self.is_contiguous() {
456-
Err(ErrorKind::NotContiguous)
453+
Err(NotContiguousError)
457454
} else {
458455
Ok(unsafe { slice::from_raw_parts(self.data(), self.len()) })
459456
}
460457
}
461458

462459
/// Get the mmutable view of the internal data of `PyArray`, as slice.
463-
pub fn as_slice_mut(&self) -> Result<&mut [T], ErrorKind> {
464-
self.type_check()?;
460+
pub fn as_slice_mut(&self) -> Result<&mut [T], NotContiguousError> {
465461
if !self.is_contiguous() {
466-
Err(ErrorKind::NotContiguous)
462+
Err(NotContiguousError)
467463
} else {
468464
Ok(unsafe { slice::from_raw_parts_mut(self.data(), self.len()) })
469465
}
@@ -629,19 +625,14 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
629625
assert!(type_check.is_ok(), "{:?}", type_check);
630626
}
631627

632-
fn type_check(&self) -> Result<(), ErrorKind> {
628+
fn type_check(&self) -> Result<(), ShapeError> {
633629
let truth = self.typenum();
634630
let dim = self.shape().len();
635631
let dim_ok = D::NDIM.map(|n| n == dim).unwrap_or(true);
636632
if T::is_same_type(truth) && dim_ok {
637633
Ok(())
638634
} else {
639-
Err(ErrorKind::py_to_rust(
640-
truth,
641-
dim,
642-
T::npy_data_type(),
643-
D::NDIM,
644-
))
635+
Err(ShapeError::new(truth, dim, T::npy_data_type(), D::NDIM))
645636
}
646637
}
647638
}
@@ -772,7 +763,7 @@ impl<T: TypeNum> PyArray<T, Ix1> {
772763
/// pyarray.resize(100).unwrap();
773764
/// assert_eq!(pyarray.len(), 100);
774765
/// ```
775-
pub fn resize(&self, new_elems: usize) -> Result<(), ErrorKind> {
766+
pub fn resize(&self, new_elems: usize) -> PyResult<()> {
776767
self.resize_([new_elems], 1, NPY_ORDER::NPY_ANYORDER)
777768
}
778769

@@ -781,7 +772,7 @@ impl<T: TypeNum> PyArray<T, Ix1> {
781772
dims: D,
782773
check_ref: c_int,
783774
order: NPY_ORDER,
784-
) -> Result<(), ErrorKind> {
775+
) -> PyResult<()> {
785776
let dims = dims.into_dimension();
786777
let mut np_dims = dims.to_npy_dims();
787778
let res = unsafe {
@@ -793,7 +784,7 @@ impl<T: TypeNum> PyArray<T, Ix1> {
793784
)
794785
};
795786
if res.is_null() {
796-
Err(ErrorKind::py(self.py()))
787+
Err(PyErr::fetch(self.py()))
797788
} else {
798789
Ok(())
799790
}
@@ -816,16 +807,13 @@ impl<T: TypeNum> PyArray<T, Ix2> {
816807
/// assert_eq!(pyarray.as_array(), array![[1, 2, 3], [1, 2, 3]]);
817808
/// assert!(PyArray::from_vec2(gil.python(), &[vec![1], vec![2, 3]]).is_err());
818809
/// ```
819-
pub fn from_vec2<'py>(py: Python<'py>, v: &[Vec<T>]) -> Result<&'py Self, ErrorKind>
810+
pub fn from_vec2<'py>(py: Python<'py>, v: &[Vec<T>]) -> Result<&'py Self, FromVecError>
820811
where
821812
T: Clone,
822813
{
823814
let last_len = v.last().map_or(0, |v| v.len());
824815
if v.iter().any(|v| v.len() != last_len) {
825-
return Err(ErrorKind::FromVec {
826-
dim1: v.len(),
827-
dim2: last_len,
828-
});
816+
return Err(FromVecError::new(v.len(), last_len));
829817
}
830818
let dims = [v.len(), last_len];
831819
let array = Self::new(py, dims, false);
@@ -859,25 +847,19 @@ impl<T: TypeNum> PyArray<T, Ix3> {
859847
/// );
860848
/// assert!(PyArray::from_vec3(gil.python(), &[vec![vec![1], vec![]]]).is_err());
861849
/// ```
862-
pub fn from_vec3<'py>(py: Python<'py>, v: &[Vec<Vec<T>>]) -> Result<&'py Self, ErrorKind>
850+
pub fn from_vec3<'py>(py: Python<'py>, v: &[Vec<Vec<T>>]) -> Result<&'py Self, FromVecError>
863851
where
864852
T: Clone,
865853
{
866-
let dim2 = v.last().map_or(0, |v| v.len());
867-
if v.iter().any(|v| v.len() != dim2) {
868-
return Err(ErrorKind::FromVec {
869-
dim1: v.len(),
870-
dim2,
871-
});
854+
let len2 = v.last().map_or(0, |v| v.len());
855+
if v.iter().any(|v| v.len() != len2) {
856+
return Err(FromVecError::new(v.len(), len2));
872857
}
873-
let dim3 = v.last().map_or(0, |v| v.last().map_or(0, |v| v.len()));
874-
if v.iter().any(|v| v.iter().any(|v| v.len() != dim3)) {
875-
return Err(ErrorKind::FromVec {
876-
dim1: v.len(),
877-
dim2: dim3,
878-
});
858+
let len3 = v.last().map_or(0, |v| v.last().map_or(0, |v| v.len()));
859+
if v.iter().any(|v| v.iter().any(|v| v.len() != len3)) {
860+
return Err(FromVecError::new(v.len(), len3));
879861
}
880-
let dims = [v.len(), dim2, dim3];
862+
let dims = [v.len(), len2, len3];
881863
let array = Self::new(py, dims, false);
882864
unsafe {
883865
for (z, vz) in v.iter().enumerate() {
@@ -908,12 +890,12 @@ impl<T: TypeNum, D> PyArray<T, D> {
908890
/// assert!(pyarray_f.copy_to(pyarray_i).is_ok());
909891
/// assert_eq!(pyarray_i.as_slice().unwrap(), &[2, 3, 4]);
910892
/// ```
911-
pub fn copy_to<U: TypeNum>(&self, other: &PyArray<U, D>) -> Result<(), ErrorKind> {
893+
pub fn copy_to<U: TypeNum>(&self, other: &PyArray<U, D>) -> PyResult<()> {
912894
let self_ptr = self.as_array_ptr();
913895
let other_ptr = other.as_array_ptr();
914896
let result = unsafe { PY_ARRAY_API.PyArray_CopyInto(other_ptr, self_ptr) };
915897
if result == -1 {
916-
Err(ErrorKind::py(self.py()))
898+
Err(PyErr::fetch(self.py()))
917899
} else {
918900
Ok(())
919901
}
@@ -927,10 +909,7 @@ impl<T: TypeNum, D> PyArray<T, D> {
927909
/// let pyarray_f = PyArray::arange(gil.python(), 2.0, 5.0, 1.0);
928910
/// let pyarray_i = pyarray_f.cast::<i32>(false).unwrap();
929911
/// assert_eq!(pyarray_i.as_slice().unwrap(), &[2, 3, 4]);
930-
pub fn cast<'py, U: TypeNum>(
931-
&'py self,
932-
is_fortran: bool,
933-
) -> Result<&'py PyArray<U, D>, ErrorKind> {
912+
pub fn cast<'py, U: TypeNum>(&'py self, is_fortran: bool) -> PyResult<&'py PyArray<U, D>> {
934913
let ptr = unsafe {
935914
let descr = PY_ARRAY_API.PyArray_DescrFromType(U::typenum_default());
936915
PY_ARRAY_API.PyArray_CastToType(
@@ -940,7 +919,7 @@ impl<T: TypeNum, D> PyArray<T, D> {
940919
)
941920
};
942921
if ptr.is_null() {
943-
Err(ErrorKind::py(self.py()))
922+
Err(PyErr::fetch(self.py()))
944923
} else {
945924
Ok(unsafe { PyArray::<U, D>::from_owned_ptr(self.py(), ptr) })
946925
}
@@ -964,7 +943,7 @@ impl<T: TypeNum, D> PyArray<T, D> {
964943
/// assert!(array.reshape([5]).is_err());
965944
/// ```
966945
#[inline(always)]
967-
pub fn reshape<'py, ID, D2>(&'py self, dims: ID) -> Result<&'py PyArray<T, D2>, ErrorKind>
946+
pub fn reshape<'py, ID, D2>(&'py self, dims: ID) -> PyResult<&'py PyArray<T, D2>>
968947
where
969948
ID: IntoDimension<Dim = D2>,
970949
D2: Dimension,
@@ -977,7 +956,7 @@ impl<T: TypeNum, D> PyArray<T, D> {
977956
&'py self,
978957
dims: ID,
979958
order: NPY_ORDER,
980-
) -> Result<&'py PyArray<T, D2>, ErrorKind>
959+
) -> PyResult<&'py PyArray<T, D2>>
981960
where
982961
ID: IntoDimension<Dim = D2>,
983962
D2: Dimension,
@@ -992,7 +971,7 @@ impl<T: TypeNum, D> PyArray<T, D> {
992971
)
993972
};
994973
if ptr.is_null() {
995-
Err(ErrorKind::py(self.py()))
974+
Err(PyErr::fetch(self.py()))
996975
} else {
997976
Ok(unsafe { PyArray::<T, D2>::from_owned_ptr(self.py(), ptr) })
998977
}

0 commit comments

Comments
 (0)