py: only well-formed masks are NotImplementedError; others stay TypeError

A boolean array of the axis's length, or of the dataset's whole shape, is
a mask h5py would apply (NotImplementedError here); one of any other shape
(np.array(True), a wrong length) is a key h5py itself refuses with
TypeError, which test_errors_match_h5py requires us to match.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
osobh
2026-09-27 07:57:49 -05:00
co-authored by Claude Opus 5.5
parent d09e55e229
commit 18e9be0af7
+24 -4
View File
@@ -255,6 +255,17 @@ pub(crate) fn parse(key: &Bound<'_, PyAny>, dims: &[u64]) -> PyResult<Plan> {
}
}
// A mask of the dataset's whole shape (`ds[ds[()] > 0]`).
if let [a] = args.as_slice() {
let np = key.py().import("numpy")?;
if a.is_instance(&np.getattr("ndarray")?)?
&& a.getattr("dtype")?.getattr("kind")?.extract::<String>()? == "b"
&& a.getattr("ndim")?.extract::<usize>()? > 1
&& a.getattr("shape")?.extract::<Vec<u64>>()? == dims
{
return Err(mask_unsupported());
}
}
if args.iter().any(|a| a.is_none()) {
return Err(PyTypeError::new_err(
"Indexing with None (or np.newaxis) is not supported",
@@ -333,6 +344,10 @@ pub(crate) fn parse(key: &Bound<'_, PyAny>, dims: &[u64]) -> PyResult<Plan> {
})
}
fn mask_unsupported() -> PyErr {
PyNotImplementedError::new_err("boolean mask indexing is not supported by clawhdf5")
}
fn parse_axis(py: Python<'_>, a: &Bound<'_, PyAny>, n: u64) -> PyResult<Axis> {
if a.is_none() {
return Err(PyTypeError::new_err(
@@ -380,10 +395,15 @@ fn parse_axis(py: Python<'_>, a: &Bound<'_, PyAny>, n: u64) -> PyResult<Axis> {
let arr = np.call_method1("asarray", (a,))?;
let kind: String = arr.getattr("dtype")?.getattr("kind")?.extract()?;
if kind == "b" {
// h5py supports masks; clawhdf5 does not (yet), for reads or
// writes: an unsupported operation, not a wrong key.
return Err(PyNotImplementedError::new_err(
"boolean mask indexing is not supported by clawhdf5",
// A mask along this axis (h5py supports them; clawhdf5 does
// not, for reads or writes: an unsupported operation). A mask
// of any other shape is a wrong key, as in h5py.
let shape: Vec<u64> = arr.getattr("shape")?.extract()?;
if shape == [n] {
return Err(mask_unsupported());
}
return Err(PyTypeError::new_err(
"Boolean indexing array has incompatible shape",
));
}
let ndim: usize = arr.getattr("ndim")?.extract()?;