From 18e9be0af7a6a781fe4c394f45bed37a6472bfa3 Mon Sep 17 00:00:00 2001 From: osobh Date: Sun, 27 Sep 2026 07:57:49 -0500 Subject: [PATCH] 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) --- crates/clawhdf5-py/src/select.rs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/crates/clawhdf5-py/src/select.rs b/crates/clawhdf5-py/src/select.rs index 93a1ad1..88ac358 100644 --- a/crates/clawhdf5-py/src/select.rs +++ b/crates/clawhdf5-py/src/select.rs @@ -255,6 +255,17 @@ pub(crate) fn parse(key: &Bound<'_, PyAny>, dims: &[u64]) -> PyResult { } } + // 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::()? == "b" + && a.getattr("ndim")?.extract::()? > 1 + && a.getattr("shape")?.extract::>()? == 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 { }) } +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 { if a.is_none() { return Err(PyTypeError::new_err( @@ -380,10 +395,15 @@ fn parse_axis(py: Python<'_>, a: &Bound<'_, PyAny>, n: u64) -> PyResult { 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 = 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()?;