feat: attrs() reports every attribute; unsigned arrays stay unsigned
attrs() silently omitted any attribute whose datatype had no AttrValue variant
— including every Python bool, which h5py stores as an enum — plus complex,
compound and reference attributes, and cast unsigned 64-bit arrays to
I64Array so values above i64::MAX came back negative.
- numpy/h5py-style booleans (an enum of exactly FALSE=0 / TRUE=1 over an
integer base) decode as I64 / I64Array of 0/1.
- AttrValue::U64Array keeps unsigned arrays unsigned. Behaviour change: an
unsigned array attribute no longer arrives as I64Array; the netCDF-4 CF
helpers (_FillValue, valid_range) and the Python bindings handle it.
- AttrValue::Raw { datatype, shape, data } carries any other attribute
verbatim (also used when a value fails to decode as its declared type), so
the attribute list is always complete. Decodable with data_read against the
datatype; Python receives {"dtype", "shape", "data"}.
- Both new variants are writable, so attributes round-trip between files.
h5py interop tests cover reading 13 attribute kinds and h5py reading back a
compound and a u64 attribute written by clawhdf5.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
5dd95a6cf8
commit
97ab658c11
@@ -128,10 +128,28 @@ pub(crate) fn attr_value_to_py(py: Python<'_>, val: &clawhdf5_rs::AttrValue) ->
|
||||
let list = pyo3::types::PyList::new(py, a).unwrap();
|
||||
list.into_any().unbind()
|
||||
}
|
||||
clawhdf5_rs::AttrValue::U64Array(a) => {
|
||||
let list = pyo3::types::PyList::new(py, a).unwrap();
|
||||
list.into_any().unbind()
|
||||
}
|
||||
clawhdf5_rs::AttrValue::StringArray(a) => {
|
||||
let list = pyo3::types::PyList::new(py, a).unwrap();
|
||||
list.into_any().unbind()
|
||||
}
|
||||
// No Python-side decoding for this datatype: hand back everything
|
||||
// needed to interpret it rather than dropping the attribute.
|
||||
clawhdf5_rs::AttrValue::Raw {
|
||||
datatype,
|
||||
shape,
|
||||
data,
|
||||
} => {
|
||||
let dict = pyo3::types::PyDict::new(py);
|
||||
dict.set_item("dtype", format!("{datatype:?}")).unwrap();
|
||||
dict.set_item("shape", shape).unwrap();
|
||||
dict.set_item("data", pyo3::types::PyBytes::new(py, data))
|
||||
.unwrap();
|
||||
dict.into_any().unbind()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user