Skip to content

Commit cf25192

Browse files
committed
ShapeError -> DimensionalityError/TypeError
1 parent fdc389e commit cf25192

File tree

3 files changed

+68
-63
lines changed

3 files changed

+68
-63
lines changed

src/array.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::{iter::ExactSizeIterator, marker::PhantomData};
1616

1717
use crate::convert::{ArrayExt, IntoPyArray, NpyIndex, ToNpyDims, ToPyArray};
1818
use crate::dtype::{DataType, Element};
19-
use crate::error::{FromVecError, NotContiguousError, ShapeError};
19+
use crate::error::{DimensionalityError, FromVecError, NotContiguousError, TypeError};
2020
use crate::slice_container::PySliceContainer;
2121

2222
/// A safe, static-typed interface for
@@ -136,14 +136,21 @@ impl<'a, T: Element, D: Dimension> FromPyObject<'a> for &'a PyArray<T, D> {
136136
}
137137
&*(ob as *const PyAny as *const PyArray<T, D>)
138138
};
139+
139140
let src_dtype = array.dtype();
140141
let dst_dtype = T::get_dtype(ob.py());
141-
let dim = array.shape().len();
142-
if src_dtype.is_equiv_to(dst_dtype) && D::NDIM.map(|n| n == dim).unwrap_or(true) {
143-
Ok(array)
144-
} else {
145-
Err(ShapeError::new(src_dtype, dim, T::DATA_TYPE, D::NDIM).into())
142+
if !src_dtype.is_equiv_to(dst_dtype) {
143+
return Err(TypeError::new(src_dtype, dst_dtype).into());
146144
}
145+
146+
let src_ndim = array.shape().len();
147+
if let Some(dst_ndim) = D::NDIM {
148+
if src_ndim != dst_ndim {
149+
return Err(DimensionalityError::new(src_ndim, dst_ndim).into());
150+
}
151+
}
152+
153+
Ok(array)
147154
}
148155
}
149156

src/error.rs

Lines changed: 54 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,10 @@
11
//! Defines error types.
2-
use crate::DataType;
3-
use pyo3::{exceptions as exc, PyErr, PyErrArguments, PyObject, Python, ToPyObject};
4-
use std::fmt;
5-
6-
/// Represents a dimension and dtype of numpy array.
7-
///
8-
/// Only for error formatting.
9-
#[derive(Debug)]
10-
pub(crate) struct ArrayDim {
11-
dim: Option<usize>,
12-
dtype: Option<DataType>,
13-
}
142
15-
impl fmt::Display for ArrayDim {
16-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17-
let ArrayDim { dim, dtype } = self;
18-
match (dim, dtype) {
19-
(Some(dim), Some(dtype)) => write!(f, "dim={:?}, dtype={:?}", dim, dtype),
20-
(None, Some(dtype)) => write!(f, "dim=_, dtype={:?}", dtype),
21-
(Some(dim), None) => write!(f, "dim={:?}, dtype=Unknown", dim),
22-
(None, None) => write!(f, "dim=_, dtype=Unknown"),
23-
}
24-
}
25-
}
26-
27-
/// Represents that shapes of the given arrays don't match.
28-
#[derive(Debug)]
29-
pub struct ShapeError {
30-
from: ArrayDim,
31-
to: ArrayDim,
32-
}
3+
use std::fmt;
334

34-
impl ShapeError {
35-
pub(crate) fn new(
36-
from_dtype: &crate::PyArrayDescr,
37-
from_dim: usize,
38-
to_type: DataType,
39-
to_dim: Option<usize>,
40-
) -> Self {
41-
ShapeError {
42-
from: ArrayDim {
43-
dim: Some(from_dim),
44-
dtype: from_dtype.get_datatype(),
45-
},
46-
to: ArrayDim {
47-
dim: to_dim,
48-
dtype: Some(to_type),
49-
},
50-
}
51-
}
52-
}
5+
use pyo3::{exceptions as exc, PyErr, PyErrArguments, PyObject, Python, ToPyObject};
536

54-
impl fmt::Display for ShapeError {
55-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56-
let ShapeError { from, to } = self;
57-
write!(f, "Shape Mismatch:\n from=({}), to=({})", from, to)
58-
}
59-
}
7+
use crate::dtype::PyArrayDescr;
608

619
macro_rules! impl_pyerr {
6210
($err_type: ty) => {
@@ -76,7 +24,57 @@ macro_rules! impl_pyerr {
7624
};
7725
}
7826

79-
impl_pyerr!(ShapeError);
27+
/// Represents that dimensionalities of the given arrays don't match.
28+
#[derive(Debug)]
29+
pub struct DimensionalityError {
30+
from: usize,
31+
to: usize,
32+
}
33+
34+
impl DimensionalityError {
35+
pub(crate) fn new(from: usize, to: usize) -> Self {
36+
Self { from, to }
37+
}
38+
}
39+
40+
impl fmt::Display for DimensionalityError {
41+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42+
let Self { from, to } = self;
43+
write!(f, "dimensionality mismatch:\n from={}, to={}", from, to)
44+
}
45+
}
46+
47+
impl_pyerr!(DimensionalityError);
48+
49+
/// Represents that types of the given arrays don't match.
50+
#[derive(Debug)]
51+
pub struct TypeError {
52+
from: String,
53+
to: String,
54+
}
55+
56+
impl TypeError {
57+
pub(crate) fn new(from: &PyArrayDescr, to: &PyArrayDescr) -> Self {
58+
let dtype_to_str = |dtype: &PyArrayDescr| {
59+
dtype
60+
.str()
61+
.map_or_else(|_| "(unknown)".into(), |s| s.to_string_lossy().into_owned())
62+
};
63+
Self {
64+
from: dtype_to_str(from),
65+
to: dtype_to_str(to),
66+
}
67+
}
68+
}
69+
70+
impl fmt::Display for TypeError {
71+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72+
let Self { from, to } = self;
73+
write!(f, "type mismatch:\n from={}, to={}", from, to)
74+
}
75+
}
76+
77+
impl_pyerr!(TypeError);
8078

8179
/// Represents that given vec cannot be treated as array.
8280
#[derive(Debug)]

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub use crate::array::{
4747
};
4848
pub use crate::convert::{IntoPyArray, NpyIndex, ToNpyDims, ToPyArray};
4949
pub use crate::dtype::{c32, c64, DataType, Element, PyArrayDescr};
50-
pub use crate::error::{FromVecError, NotContiguousError, ShapeError};
50+
pub use crate::error::{DimensionalityError, FromVecError, NotContiguousError, TypeError};
5151
pub use crate::npyffi::{PY_ARRAY_API, PY_UFUNC_API};
5252
pub use crate::npyiter::{
5353
IterMode, NpyIterFlag, NpyMultiIter, NpyMultiIterBuilder, NpySingleIter, NpySingleIterBuilder,

0 commit comments

Comments
 (0)