clawhdf5: set_attr adds the Attribute Info message a version-2 header needs

libhdf5 counts a version-2 object header's attributes through its Attribute
Info message (0x15) and reports none when the header has none. set_attr gave
v110/latest groups, the root group and datasets without attributes an
attribute message only, so h5py listed the attribute but len(obj.attrs) and
H5Oget_info's num_attrs said 0, and stayed wrong after h5py r+ added more.

Like H5O__attr_create, the edit now adds the message when a version-2 header
lacks it, in the same planned edit: version 0, the header's creation-order
track/index flags, maximum creation index 0, undefined fractal heap and
B-tree addresses, message flag DONTSHARE — byte for byte what libhdf5
writes. It goes before the attribute (libhdf5's order) when free space
holds both, else after it, so a continuation chunk made for the attribute
also takes it.

Test: edit_interop attribute_count_in_version_2_headers — v110 and latest
files, attributes set on the root group, groups and datasets with and
without existing attributes: h5py's len/num_attrs/list/values, h5dump -A
and our reader agree, also after h5py r+ adds attributes up to and past the
compact limit. Fails on the previous editor (h5py len 0).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
osobh
2026-09-26 14:12:35 -05:00
co-authored by Claude Opus 5.5
parent f7e2ab12f2
commit 485bea0f4f
4 changed files with 136 additions and 1 deletions
+5 -1
View File
@@ -31,7 +31,11 @@
- `resize`: grow a chunked dataset up to its maximum dimensions (h5py's
`Dataset.resize`).
- `set_attr`: add or replace an attribute in an object header, in free
space or in a new continuation chunk at the end of the file.
space or in a new continuation chunk at the end of the file. A
version-2 header (h5py `libver='v110'` and later) without an Attribute
Info message gets one, as libhdf5's `H5O__attr_create` adds it: libhdf5
counts such a header's attributes through that message, and without it
h5py reported `len(obj.attrs) == 0` while listing them.
- Each edit is planned in memory and refused as a whole
(`Error::Unsupported`, file untouched) when any part is not supported:
new chunks in a version-2 B-tree index (two or more unlimited