Skip to content

test: sample the full rectilinear chunk grid declaration space - #4377

Draft
d-v-b wants to merge 2 commits into
zarr-developers:mainfrom
d-v-b:test/rectilinear-declaration-space
Draft

d-v-b wants to merge 2 commits into
zarr-developers:mainfrom
d-v-b:test/rectilinear-declaration-space

Conversation

@d-v-b

@d-v-b d-v-b commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

🤖 AI text below 🤖

Follow-up to #4374. The bug shipped in 3.2.x because the rectilinear hypothesis strategy returned one list of edges per dimension, so no property test ever saw a bare-int dimension, a grid mixing bare ints and edge lists, a run-length encoded declaration, or edges overhanging the extent. A first-element-only classifier was invisible to it.

Changes

Two strategies in zarr.testing.strategies, for the two spaces the spec has:

  • rectilinear_chunks samples the chunks= syntax: per dimension a bare int (a step; may exceed the extent) or a flat edge list summing to the extent, in any arrangement, with at least one list so the grid is rectilinear. Run-length encoding is deliberately not part of this space; it is a metadata form, not an input form.
  • rectilinear_chunk_shape_declarations samples the stored chunk_shapes: bare-int steps, edge lists written in full or run-length encoded (canonical, or arbitrary grouping with split runs and [size, 1] pairs), and edges overhanging the extent (trailing edge, or last edge past the end). Each draw returns the chunk_shapes it must parse to.
  • chunk_grids (and so array_metadata) draws from the stored space via from_dict, so the metadata roundtrip properties now see all of it. arrays passes grids the list syntax cannot express (overhang, all bare ints) as the metadata object, and asserts the stored grid equals the declared one.
  • test_unified_chunk_grid.py had a private copy of the old strategy; it now draws from the shared one.

Two new properties pin what would have caught #4374: every stored declaration parses to its expanded edges and re-serializes to an equivalent grid (checked inside a full ArrayV3Metadata document), and every chunks= specification lands in zarr.json as a "rectilinear" grid whose chunk_shapes equal the specification.

Reach

Measured with --hypothesis-show-statistics (share of examples per test). In test_basic_indexing: 19% of draws mix bare ints and edge lists, 16% have a bare-int dimension, 4.6% a step larger than the extent. In the metadata roundtrips: canonical RLE 3.9%, arbitrary-grouping RLE 2%, overhang 2%. Every one of these was 0% before. No assume() in the strategies.

Independent of #4375 and #4376; passes on main as well.

🤖 Generated with Claude Code

The rectilinear hypothesis strategy returned one list of edges per
dimension, so no property test ever saw a bare-int dimension, a grid
mixing bare ints and edge lists, a run-length encoded declaration, or
edges overhanging the extent. The first-element-only classifier that
zarr 3.2.x shipped (zarr-developers#4374) was invisible to it.

The strategies now cover two spaces. `rectilinear_chunks` samples the
`chunks=` syntax: bare ints and flat edge lists in any arrangement, at
least one list so the grid is rectilinear. `rectilinear_chunk_shape_
declarations` samples the stored metadata: bare-int steps (including
larger than the extent), edge lists written in full or run-length
encoded in canonical or arbitrary grouping, and overhanging edges. Each
draw comes with the chunk_shapes it must parse to. `chunk_grids` and so
`array_metadata` draw from the stored space; `arrays` passes grids the
list syntax cannot express as the metadata object, and asserts the
stored grid equals the declared one.

Two property tests pin the properties that would have caught zarr-developers#4374:
every stored declaration parses to its expanded edges and re-serializes
to an equivalent grid, and every `chunks=` specification is stored in
zarr.json as a "rectilinear" grid equal to the specification.

test_unified_chunk_grid.py used a private copy of the old strategy; it
now draws from the shared one.

Assisted-by: ClaudeCode:claude-fable-5-1
d-v-b added a commit to d-v-b/zarr-python that referenced this pull request Sep 18, 2026
Assisted-by: ClaudeCode:claude-fable-5-1
@github-actions github-actions Bot added the needs release notes Automatically applied to PRs which haven't added release notes label Sep 18, 2026
Assisted-by: ClaudeCode:claude-fable-5-1
@github-actions github-actions Bot removed the needs release notes Automatically applied to PRs which haven't added release notes label Sep 18, 2026
@read-the-docs-community

read-the-docs-community Bot commented Sep 18, 2026

Copy link
Copy Markdown

@read-the-docs-community

read-the-docs-community Bot commented Sep 18, 2026

Copy link
Copy Markdown

@codecov

codecov Bot commented Sep 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.90110% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 94.24%. Comparing base (ba883a5) to head (0410129).
⚠️ Report is 19 commits behind head on main.

Files with missing lines Patch % Lines
src/zarr/testing/strategies.py 98.90% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4377      +/-   ##
==========================================
- Coverage   94.34%   94.24%   -0.10%     
==========================================
  Files          92       92              
  Lines       12935    13002      +67     
==========================================
+ Hits        12203    12254      +51     
- Misses        732      748      +16     
Files with missing lines Coverage Δ
src/zarr/testing/strategies.py 96.45% <98.90%> (+0.31%) ⬆️

... and 16 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant