Repository navigation
Conversation
The cast_value spec requires the fill value to survive a forward and inverse cast with the codec's configuration, and requires an error when it does not. resolve_metadata cast the fill value forward only, so out_of_range "clamp" or "wrap", or rounding, accepted a fill value that decodes to something else. A partly written chunk then read that value where it should read the fill value: float32 fill 1000.0 with an int8 clamp target read back as 127.0. resolve_metadata, which ArrayV3Metadata runs at construction, now casts the encoded fill back with the decode scalar_map and compares it with the original. NaN matches NaN; the sign of zero must match. A fill value whose forward or inverse cast fails gets an error that names it as the fill value. Assisted-by: ClaudeCode:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Assisted-by: ClaudeCode:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Assisted-by: ClaudeCode:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4510 +/- ##
=======================================
Coverage 94.71% 94.72%
=======================================
Files 94 94
Lines 13663 13681 +18
=======================================
+ Hits 12941 12959 +18
Misses 722 722
🚀 New features to boost your workflow:
|
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 AI text below 🤖
The
cast_valuecodec now rejects a fill value that does not survive a round trip through the codec, as thecast_valuespec requires. Previouslyout_of_range="clamp"or"wrap", or rounding, could encode the fill value to something that decodes to a different value, so the unwritten part of a partly written chunk read back as that value instead of the fill value. For example, afloat32array with fill value1000.0and anint8target with clamping read127.0there. Array creation now raises aValueErrorthat names the fill value, both data types, and the value it decodes to.Spec
From the
data_typesection of thecast_valuespec:CastValue.resolve_metadatacast the fill value forward only, with the encodescalar_map, and never checked the inverse.Reproduction (before this change, cast-value-rs 0.4.2)
Element 1 sits in a partly written chunk, so it is stored as the encoded fill (127) and decodes to 127.0. Element 2 and 3 are in a chunk that was never written, so they read the fill directly. After this change,
create_arrayraises:Fix
The check lives in
CastValue.resolve_metadata.validatedoes not receive the fill value, andArrayV3Metadata.__init__already callsevolve_from_array_spec,validate, thenresolve_metadatafor each codec, soresolve_metadataruns at metadata construction.scalar_mapand the sameroundingandout_of_range._same_scalarcompares the result with the original fill. NaN matches NaN, whatever the payload. Otherwise the bytes must match, so the sign of zero must be preserved, as the spec requires. This rejects-0.0with an integer target, since it comes back as+0.0.ValueErrorthat says it is the fill value and names both dtypes.resolve_metadatais also called when chunks are read and written, so each call now does two one-element casts instead of one.Tests
In
tests/test_codecs/test_cast_value.py:test_fill_value_roundtrip_accepted[nan-through-scalar-map]…[clamp-in-range]…[wrap-in-range]…[int-to-float]…[integral-float-to-int]…[exact-float-narrowing]…[signed-zero-float-to-float]test_fill_value_partial_chunk_without_check_reads_wrong_valuetest_fill_value_clamp_out_of_range_rejectedtest_fill_value_wrap_out_of_range_rejectedtest_fill_value_lost_to_rounding_rejectedtest_fill_value_signed_zero_lost_rejectedtest_fill_value_nan_to_int_without_scalar_map_rejectedtest_fill_value_cannot_decode_rejectedThe accepted cases write one element of a two-element chunk, then check that the stored chunk holds the encoded fill and that the unwritten element reads back with the same bytes as the fill. All seven error tests and the regression test fail without the change to
cast_value.py.Results with
hatch run test.py3.13-optional:pytest(cast-value-rs 0.4.2):tests/(full suite,-n auto): 12663 passed, 1275 skipped, 4 xfailedtests/test_codecs/plus every other test file that mentions cast_value: 2447 passed, 6 skipped, 2 xfailedtest.py3.13-minimal(no cast-value-rs),test_cast_value.pyandtest_codec_pipeline.py: 42 passed, 33 skippedprek(ruff check, ruff format, mypy, codespell, numpydoc, towncrier-check, and the rest) passes on the changed filesBookkeeping
mainat bd0dc84.cast_value fillin issues and PRs).🤖 Generated with Claude Code