Fix silent byte-swapping of non-native-endian attribute values in the netcdf4 backend - #11543
Fix silent byte-swapping of non-native-endian attribute values in the netcdf4 backend#11543glaziermag wants to merge 3 commits into
Conversation
netCDF4-python does not byte-swap non-native-endian attribute arrays on write, so attributes read from netCDF-3 files with the scipy engine (which returns big-endian arrays) were silently corrupted when written back with the netcdf4 engine (e.g. valid_range [0., 1.] became [0., 3.03865e-319], the byte-swapped bit pattern of 1.0). Convert attribute values to native endianness before writing, matching what _force_native_endianness already does for variable data. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
for more information, see https://pre-commit.ci
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Independent verification of this PR at exact head Bug reproduced on pristine base — exactly as reported. Reading All green at PR head, same harness, same interpreter:
The new regression test is load-bearing: run standalone (it is added by this PR) it fails on unpatched base with exactly the reported corruption and passes at head. No behavioral drift on existing suites: One non-blocking factual note on the description: Diff is minimal and lands the guard at both write sites ( |
Description
Writing a dataset whose attributes hold non-native-endian numpy arrays silently stores byte-swapped values with the
netcdf4engine. The easiest way to get such attributes is reading a netCDF-3 file with thescipyengine, which returns attribute arrays big-endian — so this fully-default round-trip corrupts metadata on disk:The same happens for
xarray/tests/data/bears.nc(acf[-2., 1., 0.]→[2.69e-43, 4.60e-41, 0.0]) and for integer attributes (>i4[1, 2]→[16777216, 33554432]), for both variable and global attributes, and in NETCDF4 as well as NETCDF3 formats via this engine. No warning or error is raised; inspecting the written file with h5py shows the byte-swapped values are committed to disk at write time.Cause: netCDF4-python's
setncattr/setncattsdo not byte-swap. The backend already converts variable data to native endianness for exactly this reason (_force_native_endianness, whose comment notes this "is not supported by the netCDF4 python library"), but attribute values reachsetncatts/setncattrunconverted. This PR applies the same native-endianness conversion to attribute values at both write sites (prepare_variableandset_attribute), with a regression test. Theh5netcdfwriter already handles identical input correctly and is unchanged.Checklist
whats-new.rstAI Disclosure
Tools: Claude (Claude Code). The defect was found by round-tripping the committed files in
xarray/tests/data/through defaultopen_dataset/to_netcdf. The repro above was confirmed twice in a clean environment at 551ced5 (netCDF4 1.7.4, scipy 1.18.1, numpy 2.5.2), the fix verified to clear it, and theTestNetCDF4Data/TestScipy/TestGenericNetCDFDatasuites run against the patch (427 passed). Prompt: a standing instruction to find, verify, and fix one upstream defect.[This is Claude Code on behalf of glaziermag]