fix(sharding): flatten any multi-dim value for coordinate selections in partial writes - #320
Open
d-v-b wants to merge 6 commits into
Open
fix(sharding): flatten any multi-dim value for coordinate selections in partial writes#320d-v-b wants to merge 6 commits into
d-v-b wants to merge 6 commits into
Conversation
d-v-b
added a commit
that referenced
this pull request
Sep 4, 2026
Assisted-by: ClaudeCode:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…in partial writes The guard added in zarr-developers#4284 only reshaped the value when its shape equalled the re-derived CoordinateIndexer's sel_shape. An orthogonal selection that mixes an integer index with two or more array indices defeats that: OrthogonalIndexer drops the integer axis from the value but np.ix_ keeps it as a length-1 axis in the chunk selection, so the shapes differ in rank while agreeing in element count, the reshape was skipped, and the write still raised the shape-mismatch ValueError. The invariant is that a coordinate indexer addresses the value flat, so ravel any multi-dimensional value instead. Both partial-encode paths now share one helper for deriving the shard indexer and shaping the value, and the check is an isinstance on CoordinateIndexer so mypy types sel_shape. The regression test is parametrized over selections with an integer axis in each position, three array axes, and an unsorted selection spanning two shards. Closes zarr-developers#4315 Assisted-by: ClaudeCode:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Assisted-by: ClaudeCode:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
d-v-b
force-pushed
the
fix/sharding-oindex-mixed-int-arrays
branch
from
September 4, 2026 09:08
8989750 to
ee25884
Compare
7 tasks
… unit axes Ravelling every multi-dimensional value for a coordinate selection was too lenient. A mask write with a (2, 2) value for four selected elements, or an orthogonal write with a spurious trailing axis, raises on an unsharded array but was silently accepted on a sharded one, because the element count matched and the shard-level selection cannot tell orthogonal from mask indexing. The value shape can. An np.ix_ selection has an N-D sel_shape and the caller's value is that shape minus the integer-indexed axes, which np.ix_ keeps as length-1 axes. Ravel exactly that shape and leave any other rank alone, so an invalid write fails the same way it does without sharding. Adds an error test for both leniencies and a positive case with a length-1 array axis next to an integer axis. Assisted-by: ClaudeCode:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…roperty tests The property tests could not have found the sharded orthogonal-write bugs: - test_oindex, test_mask_indexing and test_block_indexing skipped their set half on sharded arrays with assume(zarray.shards is None), added in zarr-developers#2825 when the bug was first seen and never lifted. test_vindex had its set half commented out. - orthogonal_indices wrapped every bare integer as a one-element array, so zarr never received an integer index and OrthogonalIndexer's dropped-axis path was unreachable. basic_indices(min_dims=1) never yields an integer either, so that branch was dead. - arrays() only drew a shard shape when every axis had a chunk strictly between 1 and the axis length, on top of the v3 and regular-grid draws: 2 of 500 test_oindex examples were sharded. Lift the skips, draw integers explicitly and give the numpy indexer the same dropped-axis result, enable the vindex write with a duplicate-point filter, and let any chunk that fits the array be sharded (33 of 500 now). With these changes test_oindex fails against the code before this PR with the mixed-integer shape mismatch, and passes with it. Assisted-by: ClaudeCode:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…arrays alike Replace the sharded-only wrong-rank test in test_sharding.py and the GH2469 one-off in test_indexing.py with one parametrized error test: a coordinate write with twice the elements, a mask write with a 2-D value, and an orthogonal write with an extra axis each raise ValueError on chunked and sharded arrays under both codec pipelines. The property under test is that storage layout does not change which writes are rejected, which a sharded-only test could not state. zarr_array_from_numpy_array grows a shards argument for it. Only the rejection is asserted; a write that fails inside the chunk merge may already have touched other chunks on a chunked array. Assisted-by: ClaudeCode:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
d-v-b
added a commit
that referenced
this pull request
Sep 5, 2026
…in partial writes (zarr-developers#4316) * fix(sharding): flatten any multi-dim value for coordinate selections in partial writes The guard added in zarr-developers#4284 only reshaped the value when its shape equalled the re-derived CoordinateIndexer's sel_shape. An orthogonal selection that mixes an integer index with two or more array indices defeats that: OrthogonalIndexer drops the integer axis from the value but np.ix_ keeps it as a length-1 axis in the chunk selection, so the shapes differ in rank while agreeing in element count, the reshape was skipped, and the write still raised the shape-mismatch ValueError. The invariant is that a coordinate indexer addresses the value flat, so ravel any multi-dimensional value instead. Both partial-encode paths now share one helper for deriving the shard indexer and shaping the value, and the check is an isinstance on CoordinateIndexer so mypy types sel_shape. The regression test is parametrized over selections with an integer axis in each position, three array axes, and an unsorted selection spanning two shards. Closes zarr-developers#4315 Assisted-by: ClaudeCode:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * docs: add changelog entry for #320 Assisted-by: ClaudeCode:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Rename 320.bugfix.md to 4316.bugfix.md * fix(sharding): ravel only a value shaped like the selection minus its unit axes Ravelling every multi-dimensional value for a coordinate selection was too lenient. A mask write with a (2, 2) value for four selected elements, or an orthogonal write with a spurious trailing axis, raises on an unsharded array but was silently accepted on a sharded one, because the element count matched and the shard-level selection cannot tell orthogonal from mask indexing. The value shape can. An np.ix_ selection has an N-D sel_shape and the caller's value is that shape minus the integer-indexed axes, which np.ix_ keeps as length-1 axes. Ravel exactly that shape and leave any other rank alone, so an invalid write fails the same way it does without sharding. Adds an error test for both leniencies and a positive case with a length-1 array axis next to an integer axis. Assisted-by: ClaudeCode:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * test: exercise sharded writes and bare integer axes in the indexing property tests The property tests could not have found the sharded orthogonal-write bugs: - test_oindex, test_mask_indexing and test_block_indexing skipped their set half on sharded arrays with assume(zarray.shards is None), added in zarr-developers#2825 when the bug was first seen and never lifted. test_vindex had its set half commented out. - orthogonal_indices wrapped every bare integer as a one-element array, so zarr never received an integer index and OrthogonalIndexer's dropped-axis path was unreachable. basic_indices(min_dims=1) never yields an integer either, so that branch was dead. - arrays() only drew a shard shape when every axis had a chunk strictly between 1 and the axis length, on top of the v3 and regular-grid draws: 2 of 500 test_oindex examples were sharded. Lift the skips, draw integers explicitly and give the numpy indexer the same dropped-axis result, enable the vindex write with a duplicate-point filter, and let any chunk that fits the array be sharded (33 of 500 now). With these changes test_oindex fails against the code before this PR with the mixed-integer shape mismatch, and passes with it. Assisted-by: ClaudeCode:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * test: assert invalid value ranks are rejected on chunked and sharded arrays alike Replace the sharded-only wrong-rank test in test_sharding.py and the GH2469 one-off in test_indexing.py with one parametrized error test: a coordinate write with twice the elements, a mask write with a 2-D value, and an orthogonal write with an extra axis each raise ValueError on chunked and sharded arrays under both codec pipelines. The property under test is that storage layout does not change which writes are rejected, which a sharded-only test could not state. zarr_array_from_numpy_array grows a shards argument for it. Only the rejection is asserted; a write that fails inside the chunk merge may already have touched other chunks on a chunked array. Assisted-by: ClaudeCode:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
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 🤖
Summary
Follow-up to zarr-developers#4284, fixing zarr-developers#4315.
An orthogonal write on a sharded array that mixes an integer index with two or more array indices still failed after zarr-developers#4284:
The guard from zarr-developers#4284 reshaped the value only when
value.shape == sel_shape.OrthogonalIndexerdrops the integer axis from the value it hands down, butnp.ix_keeps that axis as length 1 in the chunk selection, so the re-derivedCoordinateIndexer.sel_shapeis(2, 1, 2)while the value is(2, 2). Same element count, different rank, reshape skipped.Changes
CoordinateIndexerravels the broadcast coordinates._encode_partial_syncand_encode_partial_single) now share one helper,_get_shard_indexer_and_value, instead of two copies of the block. The check isisinstance(indexer, CoordinateIndexer)rather thangetattr(..., "sel_shape"), so mypy types the attribute.test_sharding_orthogonal_set_multiple_array_dimsis parametrized over selections: the original 2-D pair, an unsorted pair spanning two shards, an integer axis in each of the three positions, and three array axes. The twelve integer-axis cases fail against the fix: shape the value buffer for coordinate selections in sharded writes zarr-developers/zarr-python#4284 guard and pass here.Author attestation
TODO
changes/🤖 Generated with Claude Code