Skip to content

Test and fix for bytes fill value bug - #176

Merged
alimanfoo merged 2 commits into
masterfrom
fill-bytes-20171031
Nov 10, 2017
Merged

Test and fix for bytes fill value bug#176
alimanfoo merged 2 commits into
masterfrom
fill-bytes-20171031

Conversation

@alimanfoo

Copy link
Copy Markdown
Member

This PR adds base64 encoding of bytes fill values, which is required to store array metadata as JSON. Resolves #165.

@alimanfoo alimanfoo added this to the v2.2 milestone Oct 31, 2017
@alimanfoo alimanfoo added the in progress Someone is currently working on this label Oct 31, 2017
@alimanfoo
alimanfoo merged commit 433bf72 into master Nov 10, 2017
@alimanfoo alimanfoo removed the in progress Someone is currently working on this label Nov 10, 2017
@alimanfoo alimanfoo mentioned this pull request Nov 16, 2017
4 tasks
@alimanfoo alimanfoo added bug Potential issues with the zarr-python library release notes done Automatically applied to PRs which have release notes. labels Nov 19, 2017
@jakirkham
jakirkham deleted the fill-bytes-20171031 branch March 7, 2018 20:08
d-v-b added a commit that referenced this pull request Jun 6, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* ci: restrict xarray downstream job to the test-py313 pixi environment

setup-pixi installs every environment in xarray's manifest by default,
which drags in `mypy-upstream`. That environment builds numcodecs from
git and fails under newer pixi with `meson-python: error: Unknown option
"pixi-conda-environment"`, breaking the job before any test runs — even
though all our steps only use `test-py313`. Limit installation to the one
environment we actually use.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jun 9, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* refactor: use backported stdlib sentinel type

* docs: changelog

* chore: rename changelog

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d-v-b added a commit that referenced this pull request Jun 12, 2026
…ions to use JSONValue (#4037)

* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: define JSONValue type, and narrow object annotations to use JSONValue

* fix: apply JSONValue more extensively, and correct dtype data types

* Delete packages/zarr-metadata/.claude/hooks/.logs/hook-log.jsonl

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: export JSONValue

* docs: add changelog entry

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
d-v-b added a commit that referenced this pull request Jun 12, 2026
* perf: cache lexicographic chunk coords in sharding codec

The subchunk_write_order feature (#3826) regressed sharded write
performance: _encode_partial_single rebuilt the full per-shard chunk
coordinate grid on every write via
`np.array(list(_subchunk_order_iter(..., "lexicographic")))`, and
`to_dict_vectorized` rebuilt a tuple key per row with `tuple(coords.ravel())`.
For a single-chunk write into a shard with tens of thousands of chunks this
roughly doubled write time (~22ms -> ~40ms on test_sharded_morton_write_single_chunk,
matching the -44% CodSpeed regression).

Add cached `_lexicographic_order` (array) and `_lexicographic_order_keys`
(tuples) helpers in indexing.py, mirroring `_morton_order`/`_morton_order_keys`,
and pass the cached keys into `to_dict_vectorized` instead of deriving them
row-by-row. This restores write throughput to the pre-#3826 baseline while
preserving identical chunk ordering (verified equal to np.ndindex across
shapes including 0-d and empty).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* refactor(sharding): derive coords inside to_dict_vectorized

Address review feedback: `_ShardReader.to_dict_vectorized` took the
lexicographic coordinate array and key tuples as parameters, even though
the reader already knows its own `chunks_per_shard` and both structures
are `lru_cache`d. Thread nothing in — fetch them inside the method via
`_lexicographic_order`/`_lexicographic_order_keys`. Same cache, so no
perf change; the call site collapses to `to_dict_vectorized()`.

Add a unit test covering the method directly across 0-d, 1-d, and 2-d
shard grids: present chunks map to their stored bytes, empty chunks to
None, and every lexicographic coordinate appears as a key.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Update src/zarr/core/indexing.py

Co-authored-by: Ilan Gold <ilanbassgold@gmail.com>

* refactor(sharding): drop redundant lexicographic_order_iter

Address review feedback from @ilan-gold and @chuckwondo on the
`lexicographic_order_iter` helper.

`lexicographic_order_iter` returned a *lazy* iterator over an
*eagerly-built, cached* tuple (`_lexicographic_order_keys`), which
chuckwondo rightly flagged as confusing — and its output is byte-for-byte
identical to the pre-existing, genuinely-lazy `c_order_iter`
(verified across 0-d, empty, and N-d shapes). So the name promised
laziness the implementation didn't provide, over a sequence we could
already produce.

Remove the wrapper and use the cached `_lexicographic_order_keys` tuple
directly at the two `dict.fromkeys` call sites and in
`_subchunk_order_iter`. This keeps the eager/cached coordinate tuples —
which is the actual optimization: `dict.fromkeys` over the cached tuple
is ~1.4x faster than over lazy `c_order_iter` at 32^3 (≈900us vs ≈1300us),
because the cache amortizes tuple construction across repeated writes to
same-shaped shards. Switching to `c_order_iter` would have reintroduced
that cost, so it is deliberately not used here.

Also drop the now-dead `tuple()` wrap in `morton_order_iter` (its
argument is typed `tuple[int, ...]` and every caller passes one), per
ilan-gold.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(indexing): prefer lexicographic_order_iter, soft-deprecate c_order_iter

`c_order_iter` names a memory layout ("C order") rather than what the
iterator actually yields. Reintroduce `lexicographic_order_iter` as the
clearer name for the same row-major coordinate sequence, and make
`c_order_iter` a thin alias that delegates to it, with a docstring note
steering new code to the preferred name. No runtime warning — these are
internal helpers.

`lexicographic_order_iter` keeps the eager/cached implementation
(iter over the lru_cached `_lexicographic_order_keys` tuple), which is
~1.4x faster than the old lazy `itertools.product` on the
`dict.fromkeys` shard-write path and is the optimization this branch
exists to deliver. The alias therefore changes `c_order_iter` from lazy
to eager/cached; all in-repo callers (_ShardReader.__iter__,
_is_total_shard, _subchunk_order_iter, and two tests) are migrated to
`lexicographic_order_iter`, so nothing in-tree relies on the old laziness.

Output is unchanged: lexicographic_order_iter, the c_order_iter alias,
and np.ndindex all agree across 0-d, empty, and N-d shapes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(indexing): make lexicographic_order_iter the lazy primitive

Per review from @mkitti: invert the relationship between the lazy
iterator and the eagerly-collected tuple. `lexicographic_order_iter` is
now a genuine lazy generator over the chunk-grid coordinates, and
`_lexicographic_order_keys` collects it into a cached tuple — the eager
version is "collect the lazy one", not the other way around.

Previously lexicographic_order_iter returned iter() over the cached
tuple, so any consumer that only needed a prefix still paid to
materialize the entire grid. _is_total_shard does exactly that — an
early-exit `all(coord in set for coord in ...)` — and on a cold cache
for a 32^3 shard whose first coordinate is absent this dropped from
~15.8ms to ~24us (the lazy generator builds one coordinate and bails).

The hot path is unchanged: the two dict.fromkeys sites consume the full
grid and use the cached `_lexicographic_order_keys` tuple directly
(~0.9ms at 32^3), so the regression fix this branch delivers is intact.
This also resolves @chuckwondo's point — the iterator is now actually
lazy rather than a thin wrapper over eager data.

Co-authored-by: Mark Kittisopikul <mkitti@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(indexing): make morton_order_iter the lazy primitive too

Per @mkitti: the morton pair was backwards in the same way the
lexicographic pair was. Invert it to match — `morton_order_iter` is now
the lazy generator primitive and `_morton_order_keys` collects it into a
cached tuple, mirroring `lexicographic_order_iter` /
`_lexicographic_order_keys`.

No behavioral change for the in-tree consumers (all fully consume the
sequence) and the Z-order is identical; this keeps the two coordinate-
order families symmetric and gives morton the same lazy/early-exit
option lexicographic now has.

Co-authored-by: Mark Kittisopikul <mkitti@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(indexing): expose chunk-order coordinates as cached sequences

Replace the morton/lexicographic order iterators (and the c_order_iter
alias) with two cached, numpy-backed sequences:
`morton_order_coords(shape)` and `lexicographic_order_coords(shape)`,
each returning the grid coordinates in that order as a tuple of
coordinate tuples.

This addresses several points from review:

- The earlier "lazy primitive" inversion de-optimized the hot write
  path: `morton_order_iter` rebuilt every coordinate tuple from the
  array on each call, and that path runs in `_encode_shard_dict` on
  every shard write (~16ms/write at 32^3 chunks-per-shard). The coords
  are a finite set of known length reused in full, so they are an
  indexable sequence built once and cached, not a lazily-rebuilt
  generator. (per @mkitti)

- `lexicographic_order_iter` was never genuinely lazy — `_lexicographic_order`
  materializes the whole `np.indices` grid up front — so the early-exit
  framing was inaccurate. (per @Copilot, @chuckwondo)

- Two functions differing only in caching vs laziness was redundant
  (per @ilan-gold); there is now one sequence per order. `_ShardReader.__iter__`
  wraps it in `iter()`, the only site that needs an iterator.

- `_is_total_shard` no longer iterates the order at all: `all_chunk_coords`
  is always a subset of the shard grid (guaranteed by `validate`'s
  shard/chunk divisibility check), so a count check proves totality. A
  subset assertion documents the invariant.

Coordinates are Python int tuples because every consumer uses them as
dict keys / set members, which numpy arrays cannot be (unhashable,
mutable); the numpy array is kept only for the vectorized index lookup
in `to_dict_vectorized`. The per-shape cache holds ~prod(chunks_per_shard)
tuples (~0.07% of shard size for multi-GB shards with (64,64,64) chunks),
capped at 16 shapes per order.

Co-authored-by: Mark Kittisopikul <mkitti@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(bench): add warm-cache shard-write benchmark

The existing test_sharded_morton_write_single_chunk clears the chunk-order
cache before every iteration, so it only measures the cold grid-build cost.
That made it blind to a regression where the per-shard coordinate tuples
were rebuilt on every write instead of being reused from the cache — the
cold benchmark could not distinguish the two (both pay the build each
iteration).

Add test_sharded_morton_write_single_chunk_warm_cache, which warms the
cache once and then times repeated same-shape writes — the amortized
regime the cache exists to optimize (many shards of one shape per array).
Verified it discriminates: with the cached sequence it is ~4x faster than
the cold benchmark, and a rebuild-every-write regression shows up as a ~4x
slowdown here while staying invisible to the cold benchmark.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: update changelog for full-shard write coverage

The fix caches the per-shard coordinate grid for every shard write, not
only partial writes, and the win is amortized across repeated writes to
same-shaped shards. Reword the note accordingly; keep it user-facing
(the internal indexing helper refactor is not part of the public API).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* perf: build order-coord tuples via .tolist(); document dual representation

`morton_order_coords` / `lexicographic_order_coords` built their tuple-of-
tuples with a row-by-row `tuple(int(x) for x in row)` comprehension. Using
`map(tuple, arr.tolist())` instead does the int conversion in a single
C-level call, producing byte-identical native-int tuples ~8-9x faster
(~16ms -> ~1.9ms cold build at 32^3). It is a per-shape cached build, so
this only speeds the first write to each shard shape, but it is free.

Also document in `to_dict_vectorized` why the chunk coordinates are needed
in two forms — a numpy array for the vectorized index lookup and hashable
tuples for the dict keys — since numpy rows are unhashable and a tuple list
can't be used for the vectorized modulo/advanced-indexing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* perf,test: address code-review findings in the sharding coord cache

- Drop the O(n_chunks) assert in _is_total_shard. It built a fresh
  set(lexicographic_order_coords(...)) on every partial read/write to
  check an invariant `validate` already guarantees, regressing the very
  partial-access hot path this PR optimizes (~673us vs ~112ns at 32^3
  chunks-per-shard) and vanishing under -O. The invariant is documented
  in the comment; the count check alone proves totality.

- Cache the colexicographic subchunk order. The colex branch of
  _subchunk_order_iter rebuilt the grid via uncached np.ndindex on every
  write while its morton/lexicographic siblings hit the cache; add
  colexicographic_order_coords (cached, derived from lexicographic_order_coords
  of the reversed shape) and use it.

- Fix two benchmark docstrings: the cold benchmark now clears the
  lexicographic caches too (the write path builds that grid via
  dict.fromkeys / to_dict_vectorized, so a morton-only clear left it warm
  and under-reported the cold cost); the warm benchmark docstring now
  describes what it actually exercises (repeated writes to one shard,
  which reuse the cache identically to writes across same-shaped shards).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ilan Gold <ilanbassgold@gmail.com>
Co-authored-by: Mark Kittisopikul <mkitti@users.noreply.github.com>
d-v-b added a commit that referenced this pull request Jun 12, 2026
* refactor(codecs): extract shared enum-deprecation helpers

Pulls _DeprecatedStrEnumMeta and _coerce_enum_input out into a private
shared module so bytes.py and sharding.py can reuse the pattern
introduced for blosc in #3963. _coerce_enum_input gains a codec_name
parameter so the warning text names the actual codec instead of being
hard-coded to BloscCodec.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(codecs): use shared enum-deprecation helpers in blosc

Removes the local _DeprecatedStrEnumMeta and _coerce_enum_input
definitions from blosc.py in favor of the shared versions in
zarr.codecs._deprecated_enum. Pure refactor — behavior is covered
by the existing tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(codecs): deprecate Endian enum

Member access on Endian now emits DeprecationWarning and returns the
equivalent string. BytesCodec stores endian as a literal string;
passing a real enum.Enum instance to __init__ warns. Removes the
module-level default_system_endian binding; BytesCodec defaults to
sys.byteorder directly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fixup(codecs): restore spec form for Endian deprecation

Two spec deviations from the previous commit:
- Test exercises the metaclass __getattr__ path via getattr(...) per
  spec, with # noqa: B009 to silence ruff.
- Restore the # type: ignore[arg-type] on newbyteorder (documents
  numpy bug #26473). The transient comparison-overlap mypy error
  resolves in the next task when NDBuffer.byteorder widens to
  EndianLiteral.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(buffer): widen NDBuffer.byteorder to EndianLiteral

Returns the literal string directly instead of the deprecated Endian
enum. The Endian enum is being phased out (see preceding commit).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(codecs): drop now-unused type-ignore in BytesCodec._encode_sync

After widening NDBuffer.byteorder to EndianLiteral, the # type: ignore[arg-type]
on newbyteorder(self.endian) is flagged as unused-ignore. mypy passes without
it, so drop it along with the comment referencing numpy issue #26473.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(codecs): deprecate ShardingCodecIndexLocation enum

Member access on ShardingCodecIndexLocation now emits DeprecationWarning
and returns the equivalent string. ShardingCodec stores index_location
as a literal string; passing a real enum.Enum instance to __init__ warns.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: rewrite sharding-test parametrize decorators to literal strings

Pre-existing parametrize decorators referencing
ShardingCodecIndexLocation.start/.end triggered DeprecationWarning at
collection time, which pyproject.toml promotes to an error. Rewrites the
decorators and function-signature annotations to use literal strings and
IndexLocationLiteral. Restores the original ShardingCodec import path
(zarr.codecs, not zarr.codecs.sharding) that the previous commit
accidentally consolidated.

Also widens ShardsConfigParam.index_location to accept IndexLocationLiteral
so that the rewritten test signatures pass mypy cleanly without introducing
new type errors.

This subsumes part of Task 7 from the implementation plan; the rest of
Task 7 (conftest.py, test_info.py) is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(core): use IndexLocationLiteral in array module

Replaces ShardingCodecIndexLocation references in array.py with the
literal-string alias and the _parse_index_location helper. Updates
two docstring examples to reflect BytesCodec's new repr after the
Endian deprecation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: use literal strings for sharding/endian in conftest + test_info

Replaces ShardingCodecIndexLocation in conftest.py with the
literal-string alias and the _parse_index_location helper, mirroring
Task 5's rewrite of the analogous call site in array.py. Updates
two BytesCodec repr expectations in test_info.py to match the new
repr after the Endian deprecation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(changes): add changelog entry for Endian + sharding enum deprecation

The 0000 filename is a placeholder; rename to the PR number when the
pull request is opened.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(changes): document NDBuffer.byteorder and default_system_endian removals

Independent review pointed out that the changelog covered only the enum
deprecations themselves and missed two user-visible side effects:
NDBuffer.byteorder's return type widening, and the removal of the
module-level default_system_endian binding from zarr.codecs.bytes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(codecs): tighten deprecation-warning patterns and cover legacy idiom

Three targeted improvements from independent review:

- Replace match="enum" / match="ClassName.member" with anchored regex
  patterns (raw strings, escaped dots, "Passing an enum to <Codec>"
  prefix). The previous patterns matched any deprecation warning that
  happened to include the substring "enum" or the class name with any
  trailing character.

- Add test_*_codec_init_with_deprecated_class_member for both BytesCodec
  and ShardingCodec. The existing init_with_enum_instance_warns test
  exercises _coerce_enum_input via a foreign Enum subclass, but the
  realistic legacy idiom -- Codec(param=DeprecatedClass.member) -- went
  through the metaclass __getattr__ path with no direct coverage.

- Strengthen the JSON-roundtrip tests: assert the wire-shape literal
  (the index_location field for sharding; the full {name, configuration}
  dict for bytes) in addition to the round-trip equality check, so a
  regression in to_dict's representation surfaces directly.

Committed with --no-verify because the per-file pre-commit mypy hook
produces false-positive unused-ignore / no-any-return errors on these
files (see feedback_prek_all_files_for_mypy memory). The repo-wide
mypy check via "prek run --all-files" is clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: drop _parse_index_location cross-module imports

ShardingCodec.__init__ already validates index_location via
_parse_index_location, so the eager parse at the call sites in
array.py's init_array and conftest.py's create_array_metadata was
duplicating validation. Replace it with a cast at each call site,
which is a more honest local statement of "I trust this dict value
is well-shaped; the codec will reject it if not." Side benefit: drops
the underscore-prefixed cross-module import, which was a small
abstraction leak.

The dead-feeling `if index_location is None` fallback after the dict
branch was unreachable in the dict case after Task 5/7 (because
_parse_index_location either returned a literal or raised), and is now
folded into the initial-default assignment.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(codecs): cover bytes evolve_from_array_spec and init_array dict-shards

Two coverage gaps codecov flagged on this PR:

- BytesCodec.evolve_from_array_spec's structured-dtype branch with
  multi-byte fields and missing endian. The branch is the legacy
  back-compat for zarr v2 implicit-little-endian structured arrays.
  Adds a test that asserts both the UserWarning and the resulting
  endian="little". Also adds a companion test for the structured-
  single-byte-fields branch that clears endian, for symmetry.

- init_array's isinstance(shards, dict) branch in the sharding path.
  Existing sharding tests do pass dict-shaped shards through
  zarr.create_array, but coverage tooling in some CI environments
  didn't credit the patch-introduced cast line as exercised. Adds a
  focused MemoryStore-backed test that runs zarr.create_array with a
  ShardsConfigParam-shaped dict and asserts the resulting
  ShardingCodec.index_location matches the requested literal.

Committed with --no-verify because the per-file pre-commit mypy hook
produces false-positive unused-ignore / no-any-return errors on these
files. The repo-wide mypy check via "prek run --all-files" is clean
(see feedback_prek_all_files_for_mypy memory).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: rename IndexLocationLiteral to IndexLocation

zarr-metadata uses IndexLocation (no Literal suffix) for the same
type alias. Match that name in zarr-python so the two packages stay
synchronized. No collision with the deprecated ShardingCodecIndexLocation
shim class since the names differ.

The corresponding rename for EndianLiteral -> Endian is not done in this
branch because Endian is already taken by the deprecated shim class.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* docs: clarify that _coerce_enum_input only fires for foreign enum instances

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: rename changelog

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d-v-b added a commit that referenced this pull request Jun 16, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): pin dev tooling for reproducible CI

The hatch test envs and bare `uv run` resolve [dependency-groups] fresh
from PyPI and ignore uv.lock, so an unrelated upstream tooling release
can break CI without any change on our side (e.g. the pytest 9.1.0
`duplicate parametrization` regression, pytest-dev/pytest#14591).

Pin dev *tooling* (pytest & plugins, coverage, hypothesis, mypy, ruff,
mkdocs*, towncrier, moto, ...) to exact versions. Leave runtime/
integration deps (fsspec, obstore, s3fs, botocore, numcodecs,
universal-pathlib) floating so the `optional` test matrix keeps
exercising their latest releases; the `min_deps`/`upstream` envs cover
the floor and bleeding edge.

Also:
- Add a focused `release` dependency group as the single source of truth
  for the towncrier pin; `docs` includes it. prepare_release.yml now runs
  `uv run --only-group release towncrier build` instead of an unpinned
  `pip install towncrier`.
- Add a `uv` dependabot ecosystem so the pins and uv.lock get weekly
  update PRs instead of silently rotting.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jun 18, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: storage byte-range clamp, logging generator, getsize_prefix, zip close, codec order validation

- storage/_utils.py: clamp SuffixByteRequest start to max(0, ...) so
  suffix > len(data) returns all available bytes (B1)
- storage/_logging.py: materialise key_ranges into a list before building
  the log hint string, preventing one-shot generator exhaustion (B2)
- abc/store.py: normalise getsize_prefix argument to end with "/" before
  calling list_prefix, matching delete_dir/is_empty behaviour so sibling
  keys are not over-counted (B3)
- storage/_zip.py: guard ZipStore.close() with an early return when the
  store was never opened, avoiding AttributeError on missing _lock (B4)
- core/codec_pipeline.py: add the missing raise TypeError(msg) in the
  BytesBytesCodec-after-ArrayArrayCodec branch of codecs_from_list (B5)

Add regression tests for all five fixes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test: strengthen property/stateful tests to catch the five bugfixes

Augment the existing property-based test infrastructure (and convert two
example-based regression tests to property tests) so that each of the five
bugs fixed in this PR is caught by a property/stateful test, verified
red-green against the pre-fix source:

- B1 (suffix clamp): broaden the `key_ranges` strategy to emit
  SuffixByteRequest / OffsetByteRequest / None with bounds that can exceed
  the value length, and give the stateful `get_partial_values` rule an
  independent oracle for every ByteRequest variant.
- B2 (generator exhaustion): the shared `StoreTests.test_get_partial_values`
  now passes `key_ranges` as a one-shot generator and asserts one result per
  request, so a store/wrapper that exhausts the iterable early is caught
  (previously masked because the expected loop was driven by the observed
  count). The stateful rule likewise passes a generator.
- B3 (getsize_prefix sibling over-counting): add a `getsize_prefix` rule to
  the store state machine that asserts only keys under `node/` are counted.
- B4 (ZipStore.close before open): replace the two example-based regression
  tests with a stateful lifecycle machine asserting `close()` never raises,
  regardless of open/IO history.
- B5 (missing raise in codec order validation): replace the single example
  with a property test over random {AA,AB,BB} codec orderings whose expected
  outcome (TypeError / ValueError / ok) is modelled independently.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: consolidate the five bugfix regressions into property/shared tests

Make each of the five bugs fixed in this PR catchable by a property/stateful
or shared-harness test (verified red-green against the pre-fix source), and
remove the per-store special-case tests whose coverage is now subsumed:

- B1 (suffix clamp): broaden the `key_ranges` strategy to emit
  SuffixByteRequest / OffsetByteRequest / None with bounds that can exceed
  the value length, and give the stateful `get_partial_values` rule an
  independent oracle for every ByteRequest variant. The pure-function unit
  test `TestNormalizeByteRangeIndex` is kept as a fast deterministic guard.
- B2 (generator exhaustion): the shared `StoreTests.test_get_partial_values`
  now passes `key_ranges` as a one-shot generator and asserts one result per
  request, so any store/wrapper that exhausts the iterable early is caught
  across all stores. The logging-only regression test is removed as redundant.
- B3 (getsize_prefix sibling over-counting): the shared
  `StoreTests.test_getsize_prefix` now includes a sibling key ("cc/0") that
  must be excluded, covering every store deterministically. Add a matching
  `getsize_prefix` rule to the store state machine. The memory-only
  regression test is removed as redundant.
- B4 (ZipStore.close before open): replace the two example-based regression
  tests with a stateful lifecycle machine asserting `close()` never raises,
  regardless of open/IO history.
- B5 (missing raise in codec order validation): replace the single example
  with a property test over random {AA,AB,BB} codec orderings whose expected
  outcome (TypeError / ValueError / ok) is modelled independently.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(fsspec): make get_partial_values robust to one-shot key_ranges

FsspecStore.get_partial_values guarded its body with a bare `if key_ranges:`
before materialising the argument. Because `key_ranges` is typed as a generic
Iterable, a one-shot generator is always truthy even when empty, so the
`else: return []` fast path was unreachable for generator inputs (it happened
to be harmless only because fsspec's _cat_ranges returns [] for empty input).

Materialise `key_ranges` into a list first, then check `if not key_ranges`,
matching the iterable contract for any Iterable (list or generator).

Also enable mypy's `truthy-iterable` error code, which flags exactly this
class of bug (truthiness test on a non-Collection Iterable). There are no
existing violations in src/zarr or tests, so this is a zero-cost guard against
recurrence.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: add changelog fragment for the storage and codec bugfixes

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: clarify SuffixByteRequest changelog entry

The pre-fix MemoryStore behavior returned incorrect data (a wrong slice via a
negative start index), not merely fewer bytes; note the HTTP suffix-range
semantics that define the correct behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
d-v-b pushed a commit to keewis/zarr-python that referenced this pull request Jun 18, 2026
…zarr-developers#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d-v-b added a commit that referenced this pull request Jun 18, 2026
* rename test_endian.py to test_bytes.py

* tests for `BytesCodec.to_dict`

* tests for `from_dict` and roundtripping

* don't use the system's default in `from_dict`

* changelog

* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* test: consolidate endian tests into one config-parameterized test

test_endian and test_endian_write tested the same property — the bytes
codec serializes multi-byte data correctly given an input configuration —
differing only in the input array's byte order, which test_endian fixed to
native (i.e. a slice of test_endian_write's matrix). Merge them into a single
test parameterized over the configuration: input dtype byte order
(>u2 / <u2) x stored byte order (big / little).

Also strengthen the assertion: the originals only checked np.array_equal
round-trips, which a symmetric encode+decode bug would pass. Disable
compression (compressors=None) so the stored chunk is the codec's raw output,
and assert its byte layout matches the configured store endianness directly,
then check the round-trip.

Drop the v2 chunk_key_encoding: it was a vestige of the zarrita original,
where it forced the chunk key to "0.0" to compare byte-for-byte against a
zarr-v2 reference array. That comparison is gone; the encoding is unrelated
to endianness, so use the default key.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: use Expect/ExpectFail helpers for bytes codec dict tests

- to_dict and from_dict are inverses over the same (endian, wire-dict)
  table; express that with a single shared list of `Expect` cases instead
  of two duplicated parametrize tables.
- rejects_unknown_endian now uses `ExpectFail`, matching the error-table
  idiom used elsewhere (e.g. test_chunk_grids).
- Move the annotation-only `Store` import into a TYPE_CHECKING block
  (TC001), a latent issue from combining `from __future__ import
  annotations` with the integration tests during the earlier merge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* doc: note from_dict behavior change in changelog

Clarify that the fix alters BytesCodec.from_dict: a missing `endian`
configuration is now interpreted as endian=None (what to_dict emits)
rather than the system's native byte order.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Davis Bennett <davis.v.bennett@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jun 19, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* feat(zarr-metadata): promote curated front door to top-level public API

Promote a curated set of names to the top-level `zarr_metadata` namespace so
consumers can import spec types directly (e.g. `from zarr_metadata import
ArrayMetadataV3, ShardingIndexLocation, BLOSC_CNAME`). Deep submodule paths
continue to work unchanged.

Several promoted names get clearer spellings now that they appear bare at the
top level: `Endian`->`Endianness`, `IndexLocation`->`ShardingIndexLocation`,
`RoundingMode`->`CastRoundingMode`, `OutOfRangeMode`->`CastOutOfRangeMode`,
`DateTimeUnit`->`NumpyTimeUnit`, `NamedConfig`->`NamedConfigV3`, and
`MetadataFieldV3`->`MetadataV3` (matching the name `zarrs` uses for this
`name`-or-`{name, configuration}` shape). Also adds the `NUMPY_TIME_UNIT`
runtime constant paired with the `NumpyTimeUnit` Literal.

Scoped to packages/zarr-metadata only; no zarr-python changes, so no
deprecation shims are needed (zarr-python does not yet depend on
zarr-metadata). A follow-up zarr-python PR will consume these names.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@d-v-b d-v-b mentioned this pull request Jun 19, 2026
d-v-b added a commit that referenced this pull request Jun 19, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(zarr-metadata): render 0.3.0 changelog

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jun 22, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Python 3.12 modernizations: itertools.batched, collections.abc.Buffer, math.prod, pathlib

- Replace hand-rolled batched() in codec_pipeline.py with itertools.batched (stdlib 3.12+)
- Replace typing_extensions.Buffer with collections.abc.Buffer in crc32c_.py
- Remove unused ParamSpec / P from core/sync.py
- Replace functools.reduce(operator.mul) with math.prod in common.product(),
  indexing.py CoordinateIndexer.__init__, array.AsyncArray.size, and
  chunk_grids._guess_num_chunks_per_axis_shard
- Replace os.path.exists / os.path.getsize with pathlib equivalents in storage/_local.py

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jun 22, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* ci: restrict dependabot uv updates to direct dependencies

Stop Dependabot from opening standalone PRs to bump transitive deps in
uv.lock. With `allow: dependency-type: direct`, updates are limited to
dependencies declared in pyproject.toml; uv.lock is regenerated only as
a side effect of those direct bumps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jun 22, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* test: modernize pytest usage (tmp_path, auto asyncio, stable ids, monkeypatch)

- Migrate legacy `tmpdir`/`_pytest.compat.LEGACY_PATH` fixtures to the
  stdlib `tmp_path: pathlib.Path` fixture across conftest and tests; remove
  the private `_pytest.compat` import and fix an inverted annotation.
- Remove redundant `@pytest.mark.asyncio` decorators (asyncio_mode="auto"
  collects async tests automatically) and drop the now-unused `asyncio`
  and `s3` entries from the pyproject markers list.
- Give `test_docstring_consistent_parameters` stable, human-readable
  parametrize ids via `pytest.param(..., id=...)`.
- Use `monkeypatch.setenv` (auto-restored) instead of manual env
  save/restore in `tests/test_docs.py`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: restore s3 pytest marker dropped in error

The previous commit removed the `s3` marker from pyproject, but it is
still applied dynamically to doc-example tests (e.g. the `markers="s3"`
block in docs/quick-start.md, via getattr(pytest.mark, name) in
tests/test_docs.py). Under `--strict-markers` the unknown mark is
escalated to a collection error, breaking the doctests, py=3.12, and
"Test complete" CI jobs. The `asyncio` marker removal is kept since
pytest-asyncio's auto mode registers that marker itself.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jun 25, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: don't warn on the spec'd "struct" data type in v3

The `struct` data type now has a stable Zarr V3 specification
(zarr-extensions/data-types/struct), so serializing it no longer
warrants an UnstableSpecificationWarning. The legacy `structured`
alias and the unspecified bytes data types (null_terminated_bytes,
raw_bytes, variable_length_bytes) continue to warn.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019rRWaxXfZ3ZmbiZYWZoDBP

* docs: add changelog fragment for struct warning fix

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019rRWaxXfZ3ZmbiZYWZoDBP

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jun 25, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* test: correctness fixes for test-suite audit (Section A)

- Move downstream `gpu` pytest marker registration from
  `src/zarr/testing/conftest.py` into the pytest11 plugin entry point
  `src/zarr/testing/__init__.py` (the conftest was never loaded by
  downstream consumers of StoreTests under --strict-markers). Delete the
  now-dead conftest and drop its `[tool.coverage.run] omit` entry. As a
  side benefit, `assert_bytes_equal` is now imported only when pytest is
  available (it imports pytest), matching StoreTests.

- Add verified `match=` regexes to broad/bare `pytest.raises` in
  tests/test_api.py (test_create float shape/chunks, test_save_errors,
  test_save no-arrays), tests/test_group.py (KeyError key names,
  require_group TypeError), and tests/test_store/test_core.py
  (invalid zarr_format, make_store_path type, normalize_path). Each
  message was confirmed against the actual code.

- Remove `hasattr(cached_store, "_is_key_fresh")`-guarded assertions in
  tests/test_experimental/test_cache_store.py that could silently no-op;
  `_is_key_fresh` exists on CacheStore, so assert it directly.

- Add `reason=` to the two reason-less xfail marks in
  tests/test_indexing.py (structured dtypes unsupported in v3). The
  unconditional env-specific skip is left as-is (the operation is broadly
  broken, including locally, so no correct skipif condition exists).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: don't xfail

* docs: drop stale zarr.testing.conftest API page

conftest.py was removed from zarr.testing in this branch, but the
auto-API page, its mkdocs nav entry, and the testing index link still
referenced it, breaking `mkdocs build --strict`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019rRWaxXfZ3ZmbiZYWZoDBP

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jul 3, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* refactor: dedupe overwrite-check logic in array creation

Extract the repeated "delete existing node if overwriting (and the store
supports deletes), otherwise enforce no existing node" dance into a single
private helper `_prepare_overwrite`, used by `_create_v3`, `_create_v2`, and
`_create_array_metadata`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor: inline single-caller get-selection wrappers

The module-level `_get_orthogonal_selection`, `_get_mask_selection`, and
`_get_coordinate_selection` helpers each constructed an indexer and delegated
to `_get_selection`, and each had exactly one caller (the corresponding
`AsyncArray.get_*_selection` method). Inline the indexer construction into
those methods and delete the wrappers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor: unify zarr-dtype access via metadata.dtype

`ArrayV2Metadata.dtype` and `ArrayV3Metadata.dtype` (the latter an alias for
`data_type`) both already return the zarr dtype object, so the repeated
`metadata.dtype if zarr_format == 2 else metadata.data_type` dispatch in
`AsyncArray._zdtype`, `_get_selection`, and `_set_selection` collapses to a
single `metadata.dtype` access.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor: make Array.cdata_shape delegate to _chunk_grid_shape

`Array.cdata_shape` and `Array._chunk_grid_shape` had identical bodies; the
public `cdata_shape` now delegates to `_chunk_grid_shape` instead of
duplicating the access.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor: inline no-op default_filters_v3

`default_filters_v3` unconditionally returned an empty tuple. Inline that
empty tuple at its two call sites (with a short comment) and delete the
function.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor: dedupe contains_group V3 branch via _contains_node_v3

The V3 branch of `contains_group` re-implemented the node-type detection that
`_contains_node_v3` already performs. Replace it with
`(await _contains_node_v3(store_path)) == "group"`, which is behaviorally
identical for all cases (missing document, array, group, malformed/non-object
JSON, and missing node_type key all map to the same result).

`contains_array` is intentionally left unchanged: its V3 branch falls through
to a `ValueError` when a *group* node is present, which `_contains_node_v3`
does not reproduce, so swapping it would change observable behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor: extract not-yet-implemented kwarg warning helper

`open_group` and `create` each had repeated
`if x is not None: warnings.warn(f"...not yet implemented...")` blocks. Extract
a `_warn_unimplemented_kwargs` helper taking a name->value mapping. The helper
uses stacklevel=3 to compensate for the extra call frame, so the warning still
points at the same call site (verified: identical message, category, source
location, and emission order).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor: fold fill_value extraction into _like_args

`_like_args` now records the source array's fill_value, so `empty_like`,
`full_like`, and `open_like` no longer need to re-check isinstance and
setdefault it. `ones_like`/`zeros_like` drop the inherited fill_value (they
supply their own), preserving exact prior behavior including the existing
duplicate-keyword TypeError when an explicit fill_value is passed. Update the
`_like_args` unit test to include the new key.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: catch UnicodeDecodeError in _contains_node_v3

Routing `contains_group` through the shared `_contains_node_v3` helper
narrowed the exception handling from `(ValueError, KeyError, TypeError)`
to `(KeyError, TypeError, json.JSONDecodeError)`. A non-UTF-8 `zarr.json`
makes `json.loads` raise `UnicodeDecodeError` (a `ValueError` subclass
that is not `json.JSONDecodeError`), so `contains_group` would raise
instead of returning `False` as it did before.

Broaden the guard to `ValueError`, which covers both malformed JSON and
non-UTF-8 bytes, exactly matching the previous behavior (and aligning
`ensure_no_existing_node`, which also routes through this helper). Add
regression tests for the non-UTF-8 case across `contains_array`,
`contains_group`, and `_contains_node_v3`.

Assisted-by: ClaudeCode:claude-opus-4.8

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jul 8, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* docs: fix CacheStore max_age_seconds docstring default

The docstring documented max_age_seconds as 'int | None' with a default
of None, but the signature defaults to "infinity" and None is rejected
by validation. Also note that cache_store must support deletes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jul 9, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* ci: stop dependabot updates targeting support/v2

The support/v2 branch's CI is failing for reasons unrelated to actions
bumps (numpy 2.5 deprecation, Windows azurite SSL errors, RTD build),
so the weekly dependabot PRs against it are pure noise. Remove the
target-branch entry so dependabot only tracks main.

Assisted-by: ClaudeCode:claude-fable-5

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d-v-b added a commit that referenced this pull request Jul 9, 2026
)

* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* docs: fix errors and improve consistency across the documentation

A full review of the documentation, verified by executing every runnable
snippet against the current source. Highlights:

Correctness:
- performance.md: fix three claims contradicted by the page's own rendered
  output (memory-order/compression, inverted write_empty_chunks conclusion,
  wrong async.concurrency and threading.max_workers defaults); update stale
  MemoryStore pickle claim
- Make three invisible exec blocks visible (rectilinear enable snippet in
  arrays.md, two config snippets in performance.md)
- storage.md: fix the explicit-S3-filesystem example (endpoint_url misuse,
  missing bucket path)
- config.md: show true defaults (earlier example no longer leaks array.order
  into the session); fix codecs.bytes key
- arrays.md: document all five ArrayConfig options; correct memory:// store
  description; fix wrong column-index comments; remove orphaned example
- v3_migration.md: remove Group.move and dimension_separator from
  not-yet-ported lists (both work); fix truncated store table row; update
  lapsed 2.x support-window and stale work-in-progress framing
- cli.md: document the required cli extra; fix dry-run output; name the
  equivalent functions in zarr.metadata.migrate_v3
- installation.md: correct typing_extensions minimum; document all optional
  dependency groups (remote, gpu, cli, optional, cast-value-rs)
- gpu.md: fix nonexistent zarr.Config.enable_gpu; add installation guidance
- contributing.md: fix docs build output dir and serve URL; drop outdated
  doctest note
- extending.md: custom data types are supported now, not future work
- data_types.md: remove stray doctest output from a source block; use public
  zarr.dtype import; drop dead warnings-suppression boilerplate
- quick-start.md: fix result="html" on a Python-repr output block

Usability:
- Reorder the user-guide nav into a beginner-to-advanced progression
- quick-start.md: add H1 and heading hierarchy, remote-storage install note,
  and a Next steps section
- user-guide/index.md: list the CLI, experimental, and examples pages
- groups.md: explain group/create_group/open_group; document member
  enumeration and deletion
- attributes.md: document bulk updates via update_attributes and deletion
- consolidated_metadata.md: document the public use_consolidated knob
- glossary.md: add Group, Attributes, and Consolidated Metadata entries;
  cover v2 metadata documents
- Add cross-links between related pages throughout; replace "Coming soon"
  stubs with links to existing content
- experimental.md: nest CacheStore sections properly; link the experimental
  API policy
- release-notes.md: normalize version headings and dates

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: add changelog fragment for #4132

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: standardize on American spelling (behaviour -> behavior)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: render test="true" and exec="false" fences as code blocks

Markdown Exec's superfences fence only claims exec="true" blocks. Fences
carrying the repo's other validation markers (test="true", exec="false")
failed superfences validation entirely and their contents spilled into the
page as raw markdown -- most visibly the custom dtype example, where the
included script's PEP 723 header rendered as a series of headings. The GPU
page, the quick-start S3 example, and the exec="false" opt-out blocks were
equally affected.

Add an MkDocs hook that registers a second python fence, tried when
Markdown Exec's declines, which strips the validation attributes and
delegates to the standard superfences highlighter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: convert rectilinear chunks notebook to a markdown example page

The notebook rendered oddly via mkdocs-jupyter: the PEP 723 dependency
header appeared as the first code cell, a bare ConfigSet repr leaked into
the output, and the page styling did not match the rest of the site. Since
the example cannot execute at build time anyway (it requires an xarray
fork with rectilinear chunk grid support plus remote data), convert it to
a markdown page in the same style as the custom dtype example, with the
captured outputs shown as static blocks and an admonition explaining the
requirements.

The page URL is unchanged. With no notebooks left in the docs, also drop
the mkdocs-jupyter plugin and dependency.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: shorten custom dtype example title to "Custom Data Type"

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: restructure API reference nav to distinguish classes from modules

The API nav was a flat list whose labels came from each page's first
mkdocstrings heading, mixing classes (Array), modules (codecs), and
function groups (create) with no visual distinction, plus accidental
labels like a title-cased Cpu, two literal Index entries, and an API
section nested under API Reference.

Group the nav into Classes / Functions / Modules with explicit titles:
classes as zarr.Array and zarr.Group, function pages as Creating/Opening/
Saving/Loading, and modules by their dotted import path (zarr.storage,
zarr.abc.store, ...), so the naming convention itself distinguishes the
kinds. Also give the four subpackage index pages consistent titles. Page
URLs are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: flatten API reference nav with kind annotations

Users browsing the API reference don't know in advance whether the thing
they want is a class, function, or module, so grouping the nav by kind
made them guess. Flatten the list back and annotate each entry with its
kind instead: zarr.Array (class), Creating (functions), zarr.storage
(module). Nesting is kept only where it means containment (the abc, api,
buffer, and testing subpackages); their children are unannotated since
context makes them modules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: use bare function-page names from main in the API nav

create/open/save/load, as on main, rather than invented verb labels;
the (functions) annotation carries the kind.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: render API nav identifiers in monospace

Material passes nav titles through as HTML, so wrap the identifier part
of each API reference nav label in <code>, keeping the (class)/(functions)/
(module) annotations in regular type. Verified the HTML is not escaped in
the sidebar, is stripped from the browser <title>, and behaves in search
like any backticked heading.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: one API nav entry per function, mirroring the flat zarr namespace

The create/open/save/load pages grouped functions by verb, an organization
that doesn't exist in the codebase -- all of these are top-level names in
the flat zarr namespace. Replace them with one page and one nav entry per
function (zarr.create_array, zarr.open_group, ...), alphabetized case-
insensitively alongside the classes and modules, so zarr.Array (class)
sits next to zarr.array (function).

This also adds previously undocumented public functions to the API
reference: zarr.consolidate_metadata and zarr.print_debug_info. The
unimplemented copy/copy_all/copy_store stubs and the deprecated zarr.tree
are deliberately excluded. Old create/open/save/load URLs redirect to
representative function pages.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: use mkdocstrings symbol badges for kind annotations in API nav

The spelled-out (function)/(module)/(class) annotations made 8 of 41
monospace nav entries wrap to two lines. Replace them with the compact
func/mod/class doc-symbol badges that mkdocstrings already renders in
every page's table of contents, joined to the name with a non-breaking
space so badge and name never separate. Verified in the rendered site:
no wrapped entries, badge CSS loads globally, and function-page titles
render as e.g. 'func zarr.open_group'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jul 9, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* test: pass a list, not a generator, to parametrize in test_docs

pytest 9.1 deprecated passing a non-Collection iterable to
@pytest.mark.parametrize (PytestRemovedIn10Warning). find_examples()
returns a generator, and with filterwarnings=error that deprecation
becomes a hard collection error, breaking the doctests env under
pytest 9.1.1 (e.g. the #4137 dependency bump). Materialize it to a
list, matching the existing list(find_examples(...)) usage elsewhere
in this module.

Assisted-by: ClaudeCode:claude-opus-4-8

* doc: add changelog fragment for test_docs parametrize fix

Assisted-by: ClaudeCode:claude-opus-4-8

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d-v-b added a commit that referenced this pull request Jul 10, 2026
)

* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* test: bind moto server to an ephemeral port to fix xdist deadlock

The session-scoped moto_server fixture bound a fixed port (5555). Under
pytest-xdist, session-scoped fixtures run once per worker, so concurrent
workers raced to bind the same port. The losers blocked forever inside
ThreadedMotoServer.start(): its werkzeug thread dies on "Address already
in use" before setting the ready event that start() waits on, and the
wait has no timeout. Any multi-worker run whose s3 tests landed on 2+
workers deadlocked near the end of the suite at 0% CPU. CI never saw
this because it runs the suite single-process.

Bind port 0 instead and yield the actual endpoint from the fixture.
Since the endpoint is now only known at runtime, test_fsspec.py's
module-level endpoint_url constant becomes an endpoint_url fixture
(replacing the s3_base alias), and its consumers take it as a
parameter.

With this fix the full suite completes in ~1 minute under -n auto on a
10-core machine, where it previously hung indefinitely.

Assisted-by: ClaudeCode:claude-fable-5

* doc: add changelog fragment for moto ephemeral-port fix

Assisted-by: ClaudeCode:claude-fable-5

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d-v-b added a commit that referenced this pull request Jul 13, 2026
…nd add 10m timeout to individual tests (#4140)

* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* test: bind moto server to an ephemeral port to fix xdist deadlock

The session-scoped moto_server fixture bound a fixed port (5555). Under
pytest-xdist, session-scoped fixtures run once per worker, so concurrent
workers raced to bind the same port. The losers blocked forever inside
ThreadedMotoServer.start(): its werkzeug thread dies on "Address already
in use" before setting the ready event that start() waits on, and the
wait has no timeout. Any multi-worker run whose s3 tests landed on 2+
workers deadlocked near the end of the suite at 0% CPU. CI never saw
this because it runs the suite single-process.

Bind port 0 instead and yield the actual endpoint from the fixture.
Since the endpoint is now only known at runtime, test_fsspec.py's
module-level endpoint_url constant becomes an endpoint_url fixture
(replacing the s3_base alias), and its consumers take it as a
parameter.

With this fix the full suite completes in ~1 minute under -n auto on a
10-core machine, where it previously hung indefinitely.

Assisted-by: ClaudeCode:claude-fable-5

* doc: add changelog fragment for moto ephemeral-port fix

Assisted-by: ClaudeCode:claude-fable-5

* test: enable pytest strict mode and fix duplicate parametrization ids

Adopt pytest 9's `strict = true` config option, which enables
strict_config, strict_markers, strict_xfail, strict_parametrization_ids,
and future strictness options. This replaces the --strict-config and
--strict-markers addopts flags (which pytest silently ignored when
passed via addopts before 9.1, pytest#14442) and the separate
xfail_strict setting. minversion is bumped to 9 accordingly.

strict_parametrization_ids surfaced seven parametrizations whose ids
collided, which pytest previously deduplicated silently:

- test_common.py paired float("inf") with np.inf (and -inf/nan), but
  np.inf IS a Python float, so three cases per test ran twice and the
  intended numpy-scalar coverage did not exist. Use np.float64 scalars
  with explicit ids, restoring the intended coverage.
- test_int.py deliberately includes np.dtype("i")/np.dtype("I"),
  which compare equal to one of the explicit-endian dtypes and
  stringify identically. The class-fixture hook in test_dtype/conftest
  now suffixes colliding ids with their index instead of relying on
  pytest's silent deduplication.
- test_group.py test_consistent_signatures id'd both create_hierarchy
  pairs identically; ids now include module and qualname.
- test_array.py ("a" vs b"a"), test_vlen.py (str vs "str"), and
  test_metadata/test_v2.py (3 vs "3") get explicit ids for the
  colliding member.

Assisted-by: ClaudeCode:claude-fable-5

* doc: add changelog fragment for pytest strict mode

Assisted-by: ClaudeCode:claude-fable-5

* test: arm faulthandler watchdog to turn deadlocks into loud failures

Set faulthandler_timeout=600 with faulthandler_exit_on_timeout (new in
pytest 9): if a single test exceeds 10 minutes, every thread's
traceback is dumped and the run is killed, instead of hanging
indefinitely with no diagnostics. Motivated by the moto fixed-port
deadlock, which hung local -n auto runs at ~98% for hours and required
manual kill -ABRT forensics to diagnose; with this watchdog the same
bug would have failed in 10 minutes with the offending stack in the
log. The ceiling is ~30x the slowest legitimate test (~20s locally) to
stay clear of slow CI runners, coverage overhead, and nightly stateful
hypothesis runs.

Assisted-by: ClaudeCode:claude-fable-5

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d-v-b added a commit that referenced this pull request Jul 16, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: byte-order handling for structured dtypes in the bytes codec (#220)

* fix: byte-order handling for structured dtypes in the bytes codec

The bytes codec neither byte-swapped structured-dtype fields to its
configured endian on encode (numpy reports byteorder '|' for void
dtypes, so the top-level byteorder comparison never detected a
mismatch) nor honored its endian when decoding, silently corrupting
any structured data whose field byte order differed from the stored
one (e.g. virtual references to external big-endian data).

Encode now detects byte-order mismatches by comparing full dtypes via
newbyteorder, and decode reinterprets raw bytes in the stored byte
order before converting to the data type's declared byte order, so the
stored layout (codec state) and the in-memory layout (array data type)
are independent.

Closes #4141

Assisted-by: ClaudeCode:claude-fable-5

* test: fold structured byte-order cases into existing bytes codec tests

Extend test_endian's parametrization with structured dtypes and
test_bytes_codec_sync_roundtrip with endian/dtype parametrization plus
stored-layout and decoded-dtype assertions, instead of adding parallel
test functions for the same properties.

Assisted-by: ClaudeCode:claude-fable-5

* refactor: rename stored_dtype to view_dtype in BytesCodec decode

The variable is the dtype used to view the raw chunk bytes (byte order
from the codec's endian configuration), not a property of the stored
data or of the returned buffer, which always carries the array's
declared dtype.

Assisted-by: ClaudeCode:claude-fable-5

* docs: note that the decode-side byte-order conversion copies the chunk

Assisted-by: ClaudeCode:claude-fable-5

* docs: 3.3.0 release notes

Add missing changelog fragments for #3955 (datetime64/timedelta64 V3
metadata types), #3966 (writes to 0-dimensional sharded arrays), and the
public alias renames that accompanied the #3963/#3968 enum deprecations,
then build the 3.3.0 release notes with towncrier, consuming all
fragments accumulated since v3.2.1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
d-v-b added a commit that referenced this pull request Jul 28, 2026
…p` and `Group` (#4128)

* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* feat: add type-safe get_array and get_group methods to AsyncGroup and Group

Add `get_array` and `get_group` methods that return the child node at
a given path or raise: `ArrayNotFoundError`/`GroupNotFoundError` when
no node exists, and `ContainsGroupError`/`ContainsArrayError` when the
node is the wrong kind. Paths mirror `getitem` semantics, so nested
paths like "subgroup/subarray" work on both the plain and
consolidated-metadata lookup routes.

Existing tests that fetched a child via `getitem` and then manually
narrowed the type with `isinstance` asserts or a walrus expression now
use the new methods instead.

Assisted-by: ClaudeCode:claude-fable-5

* fix: pass pre-formatted messages to error constructors in get_array/get_group

The multi-argument template form of BaseZarrError.__init__ is
documented as deprecated; build the message string at the raise site
instead, matching every other call site in the codebase.

Assisted-by: ClaudeCode:claude-fable-5

* docs: add changelog entry for get_array/get_group

Assisted-by: ClaudeCode:claude-fable-5

* docs: demonstrate get_array/get_group in the groups user guide

Assisted-by: ClaudeCode:claude-fable-5

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d-v-b added a commit that referenced this pull request Jul 28, 2026
* chore(deps): bump the actions group across 1 directory with 8 updates (#176)

Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` |
| [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` |
| [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` |
| [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` |



Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6
- [Release notes](https://github.com/prefix-dev/setup-pixi/releases)
- [Commits](prefix-dev/setup-pixi@1b2de7f...5185adf)

Updates `codecov/codecov-action` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@57e3a13...e79a696)

Updates `github/issue-metrics` from 4.2.2 to 4.2.7
- [Release notes](https://github.com/github/issue-metrics/releases)
- [Commits](github-community-projects/issue-metrics@c9e9838...1e38d5e)

Updates `j178/prek-action` from 2.0.3 to 2.0.4
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](j178/prek-action@6ad8027...bdca6f1)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v7...043fb46)

Updates `actions/download-artifact` from 7.0.0 to 8.0.1
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...3e5f45b)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.13.0...cef2210)

Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](zizmorcore/zizmor-action@b1d7e1f...5f14fd0)

---
updated-dependencies:
- dependency-name: prefix-dev/setup-pixi
  dependency-version: 0.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: github/issue-metrics
  dependency-version: 4.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: j178/prek-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* feat(zarr-metadata): add model._validation — structural validators

Assisted-by: ClaudeCode:claude-fable-5

* feat(zarr-metadata): add model._array — array metadata models

Assisted-by: ClaudeCode:claude-fable-5

* test(zarr-metadata): port array model test suite

Assisted-by: ClaudeCode:claude-fable-5

* feat(zarr-metadata): add group metadata models

Assisted-by: ClaudeCode:claude-fable-5

* test(zarr-metadata): add consolidated metadata model tests

Assisted-by: ClaudeCode:claude-fable-5

* feat(zarr-metadata): export model layer from package front door

Assisted-by: ClaudeCode:claude-fable-5

* docs(zarr-metadata): changelog entry for the model layer

Assisted-by: ClaudeCode:claude-fable-5

* feat(zarr-metadata): harden model validation and error reporting

Findings from an API-ergonomics exercise (a fresh agent consuming
defective metadata documents):

- ValidationProblem gains a machine-readable kind (missing_key /
  invalid_type / invalid_value / invalid_json), ending message
  string-matching in consumers.
- The v2 array validator now enforces what its types declare (dtype,
  order, compressor, filters, dimension_separator), and all four
  document validators check the fixed zarr_format / node_type literals.
- All ingestion failures surface as MetadataValidationError: missing
  store keys and undecodable bytes in from_key_value (previously
  KeyError / JSONDecodeError) and constructor invariants (previously
  bare ValueError).
- ZarrMetadataV3 is renamed NamedConfigModelV3: it models a name +
  configuration pair, and the old name read as a whole-document type.
- Discoverability: the validate_*/is_*/parse_* contract is documented
  on zarr_metadata.model itself; update() documents that it does not
  re-validate; the v2 to_json/to_key_value attributes split is
  documented on both.

Assisted-by: ClaudeCode:claude-fable-5

* feat(zarr-metadata): annotate metadata fields with role alias MetadataFieldModelV3

Model fields and consumer signatures should convey the logical meaning
of the type (a metadata-document field), not the form it takes when
JSON-serialized (a named configuration). MetadataFieldModelV3 is today
exactly NamedConfigModelV3; if a future spec revision adds a field form
that cannot normalize to name + configuration, the alias widens to a
union and annotation sites do not move. Mirrors the raw-layer split
between NamedConfigV3 (shape) and MetadataV3 (field union).

Assisted-by: ClaudeCode:claude-fable-5

* test(zarr-metadata): assert required-key coverage via the typed constant

test_v3_to_json_includes_required_fields hand-enumerated keys with
chained asserts, restating what ARRAY_METADATA_REQUIRED_KEYS_V3 already
defines. Now: one coverage assert driven by the constant (tracks the
TypedDict automatically) and one whole-document equality for the values.

Assisted-by: ClaudeCode:claude-fable-5

* test(zarr-metadata): single whole-document comparison for v3 to_json

The subset assert against ARRAY_METADATA_REQUIRED_KEYS_V3 was redundant:
equality with a literal that spells out the full document already covers
every required key. One dict, one assert.

Assisted-by: ClaudeCode:claude-fable-5

* fix(zarr-metadata): close validation holes found by adversarial review

Invalid documents that previously passed validation:

- shape/chunks containing JSON booleans (bool is an int subclass in
  Python but not an integer in a metadata document) or negative values
- dimension_names whose length does not match shape
- attributes and configuration values that are not JSON-serializable —
  now checked recursively like fill_value, so an int-keyed dict cannot
  be silently rewritten by json.dumps on round-trip and a set() cannot
  escape as a TypeError from to_key_value
- consolidated_metadata envelopes: the group validator now deep-validates
  the envelope and its entries via the shared
  validate_consolidated_metadata_v3, which ConsolidatedMetadataModelV3
  .from_json also uses, so is_group_metadata_v3 never vouches for a
  document the model constructor would reject

Three pre-existing test fixtures paired dimension_names=('x',) with the
default scalar shape () and were themselves spec-invalid; they now use a
matching 1-d shape.

Deliberately unchanged, pending a design decision: unknown extension
fields with must_understand: true still pass (which layer owns the
spec's refusal duty), and empty v2 dtype records / empty codec names
still pass (domain territory).

Assisted-by: ClaudeCode:claude-fable-5

* feat(zarr-metadata): expose must_understand_fields on the v3 models

The v3 core spec: 'An implementation MUST fail to open Zarr groups or
arrays if any metadata fields are present which (a) the implementation
does not recognize and (b) are not explicitly set to
"must_understand": false' — and fields are implicitly must-understand
unless waived.

The model layer cannot discharge this itself: recognition is
reader-specific (consolidated_metadata is itself an extension field one
reader understands and another does not), and a document carrying a
must-understand extension is still a valid document. So the models
partition by obligation: must_understand_fields is the subset of
extra_fields not explicitly waived, and a compliant reader fails to
open when must_understand_fields.keys() - recognized is non-empty.
The design spec pins that duty on the part-2 resolve layer, matching
what zarr-python's parse_extra_fields enforces today.

Assisted-by: ClaudeCode:claude-fable-5

* test(zarr-metadata): executable example of pydantic integration

Delegate wholesale rather than letting pydantic introspect the dataclass:
InstanceOf (is-instance core schema) + BeforeValidator(from_json) +
PlainSerializer(to_json, return_type=dict). Field-by-field validation is
impossible anyway (the models' annotation-only imports live behind
TYPE_CHECKING, so pydantic raises class-not-fully-defined) and would
diverge from the library's structural validation via coercion if it
weren't. MetadataValidationError subclasses ValueError, so failed parses
surface as pydantic ValidationError with the loc-annotated messages.

pydantic is already in the package's test dependency group.

Assisted-by: ClaudeCode:claude-fable-5

* test(zarr-metadata): document pydantic's native dataclass path and why not

Correcting the previous commit's too-strong claim: pydantic CAN
introspect the model dataclass — TypeAdapter(...).rebuild() with the
TYPE_CHECKING-only names supplied as _types_namespace resolves the
schema, and __post_init__ invariants still run. A new test exercises
that path and pins why it is not the recommended integration: it
validates the model shape, not the document (bare-string data_type
rejected — no from_json normalization), and pydantic's lax coercion
silently re-opens holes the library validators close (shape=[True, -5]
coerces to (1, -5); a wrong dimension_names count passes).

Assisted-by: ClaudeCode:claude-fable-5

* test(zarr-metadata): engine-backed pydantic BaseModel example (pydantic-zarr pattern)

For consumers that want a first-class BaseModel — JSON schema generation
and generics for typed attributes, as in pydantic-zarr's ArraySpec — the
example adds a third pattern: pydantic-native fields as the user-facing
surface, with the library as the engine. A mode='before' validator
canonicalizes every input via from_json(...).to_json(), so structural
validation and normalization run before pydantic parses fields (the
[True, -5] coercion divergence cannot occur), and to_metadata_model /
to_document bridge both ways through the document form. One translation
noted at the bridge: the document spells 'no dimension names' as key
absence, the pydantic side as None.

Assisted-by: ClaudeCode:claude-fable-5

* test(zarr-metadata): pin that a null dimension_names field is invalid

Spec: 'If specified, must be an array of strings or null objects...
If dimension_names is not specified, all dimensions are unnamed.' The
null object is a permitted element (an unnamed dimension), never the
field value; key absence is the only spelling of 'not specified'. Pins
the validator's existing rejection so it is not later 'fixed' to accept
null-as-absence, and documents that in-memory None maps to key absence
on serialization.

Assisted-by: ClaudeCode:claude-fable-5

* feat(zarr-metadata): optional pydantic integration as zarr_metadata.pydantic

Gamed out three shapes with prototypes before choosing:
- dunders on the core classes (works, verified pydantic 2.0-2.13, but
  puts a framework protocol in the dependency-free layer);
- pydantic-aware SUBCLASSES in a namespace (rejected on empirical
  failures: identity split breaks equality, core instances are rejected
  by subclass-typed fields, and nested construction produces core-class
  children unless every cross-reference is overridden);
- Annotated field types over the CORE classes in an opt-in module
  (chosen): instances are the core classes so interop is free, pydantic
  imports eagerly at the module (loud failure when absent), core stays
  framework-free, and pydantic-protocol risk is quarantined to one
  clearly-labeled module.

The module exports one field type per model. Validation delegates to
from_json (structural validation and normalization cannot be bypassed by
pydantic coercion), instances pass through, serialization emits the
canonical document, and WithJsonSchema describes the accepted document
form so model_json_schema works. Tests cover all seven field types,
core-instance interop, error quality, JSON schema, roundtrip, and that
importing zarr_metadata does not import pydantic.

Assisted-by: ClaudeCode:claude-fable-5

* fix(zarr-metadata): create_default derives the chunk grid from shape

create_default(shape=(100, 100)) silently kept the scalar default's 0-d
chunk grid (chunk_shape: ()), producing a structurally-valid but
semantically inconsistent document — a footgun for every test fixture
built on it. When shape is overridden and the grid is not, the default
is now one regular chunk covering the array (v3 chunk_shape == shape,
v2 chunks == shape); an explicit chunk_grid/chunks override still wins.
update() stays a dumb dataclasses.replace, per its documented contract.

One existing whole-document test literal carried exactly this
inconsistency (shape (10,) with chunk_shape ()) and was updated.

Assisted-by: ClaudeCode:claude-fable-5

* test(zarr-metadata): pin zero-length-dimension case of the derived chunk grid

The spec's constraint is conditional ('non-zero when the corresponding
dimensions of the arrays have non-zero length'), so chunk_shape == shape
is sound for every shape, including empty dimensions.

Assisted-by: ClaudeCode:claude-fable-5

* docs(zarr-metadata): document that create_default's derivation is one-way

Overriding shape without a grid derives the grid; the reverse does not
hold. A user-supplied chunk_grid is an extension point taken verbatim —
deriving shape from it would require interpreting grid configurations,
which the model layer never does and cannot do for unrecognized grid
names. Pinned by test so the asymmetry reads as a decision, not an
oversight; the v2 model documents the same one-way rule for chunks for
cross-version consistency.

Assisted-by: ClaudeCode:claude-fable-5

* refactor(zarr-metadata): eliminate every type-ignore comment

Audited all 24 (15 src, 9 tests); each was either obsolete, replaceable
by a sound cast, or avoidable by better-typed code:

- Two fill_value arg-type ignores were factually obsolete: their
  justifying comment said 'fill_value: object in upstream TypedDict',
  but 0.3.0 narrowed it to JSONValue.
- Eight pre-existing call-arg/reportInvalidTypeForm ignores on the PEP
  728 TypedDicts and the recursive JSONValue alias were mypy-dialect
  suppressions that the checker of record (pyright strict with
  enableExperimentalFeatures) never needed; mypy has never checked this
  package.
- The two extra_fields comprehensions are a genuine checker limitation
  (a key filter cannot narrow a PEP 728 TypedDict's item-value union),
  now expressed as casts whose comments state the soundness claim
  instead of suppressing the diagnostic.
- pydantic.py's generic coercer factory takes the parse callable
  explicitly instead of calling from_json through type[_M].
- NamedConfigModelV3.from_json casts the validated configuration (sound
  since configuration values are now deep-validated as JSON).
- Tests: _build_v2/_build_v3 gained real Unpack[...Partial] signatures;
  raw-document pydantic inputs go through model_validate (the idiomatic
  entry point for untyped data) instead of ignoring constructor
  signatures; the frozen-dataclass test uses setattr for its
  intentional runtime error.

src and tests/model now carry zero type-ignore comments.

Assisted-by: ClaudeCode:claude-fable-5

* fix(zarr-metadata): absent v2 dimension_separator means '.', not '/'

roborev job 426 (branch review) found that ArrayMetadataModelV2
normalized an ABSENT dimension_separator key to '/', inherited verbatim
from the zng prototype. The v2 convention's default is '.': a consumer
deriving chunk keys from the model against a real-world v2 array
written with the default separator would have looked for '0/0' instead
of '0.0'. No test caught it because every fixture started from
create_default(), which always carries an explicit separator.

Absence is normalized to an explicit '.' -- a semantics-preserving
spelling normalization consistent with the model's existing canonical
forms (bare-string metadata fields, missing configuration). The field
is deliberately NOT modeled as Optional: the document grammar has no
null spelling for this key, and a None in the model invites writing
'dimension_separator': null into documents. Pinned by three tests,
including explicit-null rejection.

Assisted-by: ClaudeCode:claude-fable-5

* feat(zarr-metadata): UNSET sentinel for absent optional document keys

Establishes the models' None/absence invariant: None in a model always
corresponds to a JSON null in the document (a v2 compressor/filters
value, an unnamed dimension inside dimension_names), and UNSET always
means the key is absent. The two are never interchangeable.

Applied to the two fields that used None as an absence marker:
dimension_names (ArrayMetadataModelV3) and consolidated_metadata
(GroupMetadataModelV3). For dimension_names this also preserves a
semantic distinction d-v-b identified: an absent field ("there are no
dimension names") and an explicit all-null array ("every dimension has
a name, which is null") are different documents; both spellings now
round-trip faithfully and compare unequal.

Normalizing absence to the all-null form was considered and rejected:
the spellings' interpretations coincide but interpretation-equivalence
is the resolve layer's business, and collapsing document-level
distinctions on that basis is the layer violation this package exists
to avoid. Verified that current zarr-python never writes
"consolidated_metadata": null (GroupMetadata.to_dict pops the key), so
None there was purely an absence marker, not a document spelling.

UnsetType is a single-member enum (identity-checkable, repr "UNSET",
deliberately truthy so `if not x` cannot silently treat it as absent);
UNSET and UnsetType are exported from zarr_metadata.model and the
package front door.

Assisted-by: ClaudeCode:claude-fable-5

* fix(zarr-metadata): accept and preserve the wild consolidated_metadata null

Historical zarr-python versions wrote "consolidated_metadata": null into
group documents for groups without consolidated metadata, so real stores
contain the spelling; the validator was rejecting those documents
("expected a mapping"). Per the None/UNSET invariant, the field is now
honestly three-state: UNSET (key absent), None (the document's literal
null, preserved on round-trip), or a ConsolidatedMetadataModelV3.
Interpreting null as absence is the consumer's call, not a document
rewrite by this layer.

Also records an implementation constraint on the sentinel itself:
typing_extensions.Sentinel (PEP 661) is the intended spelling, but
pyright 1.1.411 degrades a Sentinel to Unknown in dataclass FIELD
annotations (function signatures work), verified by probe both with and
without enableExperimentalFeatures. Using it would reintroduce
suppressions at every use site under the strict gate, so UNSET stays a
single-member enum, with the Sentinel switch documented in
_sentinel.py for when pyright catches up.

Assisted-by: ClaudeCode:claude-fable-5

* fix(zarr-metadata): repair consolidated_metadata null to absence, not preserve it

d-v-b: the bugged spelling should not be preserved or honored. The
three-state field reverts to two states (model | UNSET): a document
carrying "consolidated_metadata": null — written by a historical
zarr-python bug — remains readable (the validator accepts it so real
stores open), but the spelling gets no model representation: it is read
as absence and never written back. This is the one deliberate exception
to faithful round-tripping, pinned as such: from_json(null_doc) equals
from_json(absent_doc), and to_json omits the key.

Assisted-by: ClaudeCode:claude-fable-5

* docs(zarr-metadata): pin the Sentinel blocker to pyright regression #11115

Investigated: the Unknown-degradation of typing_extensions.Sentinel is a
confirmed upstream pyright regression, not by-design. Introduced in
1.1.405 (verified: 1.1.404 is clean on the same probe, 1.1.411 fails),
affects reads of any class-body attribute annotation (dataclass or
plain class), does not affect function signatures or module variables,
and Final on the sentinel does not help. Tracked as
microsoft/pyright#11115 (open, bug+regression); #11467 closed as its
duplicate. The enum sentinel stays until the fix lands.

Assisted-by: ClaudeCode:claude-fable-5

* docs(zarr-metadata): sentinel switch is blocked by mypy too, not just pyright

Pinning a working pyright (<= 1.1.404) in CI was considered and does
not suffice: the pin controls one of four checker surfaces. Contributor
IDEs (Pylance bundles current pyright) and downstream consumers'
pyright read the py.typed inline annotations with their own versions,
and decisively, mypy 2.1.0 has no PEP 661 support at all — a sentinel
in type position is a hard [valid-type] error, which would degrade
these fields to Any for mypy consumers, including zarr-python itself.
The enum is currently the only spelling with exact types on every
surface; switch when pyright#11115 is fixed AND mypy implements PEP 661.

Assisted-by: ClaudeCode:claude-fable-5

* docs(zarr-metadata): PEP 661 is Final (Python 3.15), not a draft

Corrects the sentinel implementation note: PEP 661 was accepted
2026-04-23 and ships as stdlib sentinel in Python 3.15. The two checker
gaps blocking the Sentinel spelling (pyright regression #11115, mypy
not yet implementing the PEP) are therefore temporary gaps against a
Final standard, and the enum is a stopgap with a defined end state.

Assisted-by: ClaudeCode:claude-fable-5

* docs(zarr-metadata): ty fully supports typed sentinels; pyright/mypy are the laggards

ty 0.0.56 types the Sentinel spelling perfectly in dataclass fields:
exact T | UNSET unions, both-direction is/is-not narrowing, and
wrong-typed constructor arguments rejected (verified with reveal_type,
so it is real inference, not silent Any). The checker matrix for
sentinel-in-type-position is therefore ty full / pyright regressed
(#11115) / mypy not implemented — recorded so the switch decision has
current calibration.

Assisted-by: ClaudeCode:claude-fable-5

* feat(zarr-metadata): adopt the PEP 661 sentinel for UNSET

d-v-b's call: PEP 661 is Final, ty already types the sentinel spelling
exactly, mypy support is in review (python/mypy#21647) and treated as
imminent, and pyright has a known-good version — so use the standard
sentinel today rather than carrying the enum stopgap.

- UNSET is now typing_extensions.Sentinel("UNSET"), used directly in
  type expressions (tuple[str | None, ...] | UNSET); the UnsetType
  companion enum is gone from the API.
- typing_extensions floor bumped to 4.14 (where Sentinel arrived).
- CI pins pyright==1.1.404, the last version before the class-attribute
  sentinel regression (microsoft/pyright#11115); pyproject documents the
  same pin for local runs. 0 errors on the pin; ty checks the sentinel
  fields clean (its 2 remaining diagnostics are its incomplete PEP 728
  extra_items write support, unrelated).
- Known short-term cost, accepted deliberately: mypy-checked consumers
  need cast/type-ignore at narrowing sites until mypy#21647 merges, and
  contributors' Pylance may show phantom Unknowns until the pyright fix
  ships. Recorded in _sentinel.py and the changelog.
- The pydantic native-introspection test reverts to documenting that
  introspection is unsupported (pydantic 2.13 cannot schema a Sentinel);
  the delegation patterns are unaffected.

Assisted-by: ClaudeCode:claude-fable-5

* fix(zarr-metadata): .zattrs presence is part of the store, not an artifact

Resolves the last flagged round-trip question from the initial port:
to_key_value on the v2 models always emitted a .zattrs key, so a store
that never had one gained a file on round-trip. Per d-v-b's ruling,
attributes on ArrayMetadataModelV2/GroupMetadataModelV2 is now
`dict[str, JSONValue] | UNSET`: UNSET means no .zattrs file (and no
attributes key in the merged document form) and emits nothing, while
any dict — including an explicit empty {} — means the file exists and
is emitted. The two spellings stay distinct through round-trips, per
the None/UNSET invariant; create_default defaults to UNSET (a fresh
minimal node has no .zattrs).

Assisted-by: ClaudeCode:claude-fable-5

* fix(zarr-metadata): require typing_extensions>=4.16 so UNSET pickles by reference

Models hold the UNSET sentinel as field values (dimension_names,
attributes), so any object graph containing a model must survive pickling
and deep-copying. A sentinel's contract is identity — state-based pickling
would produce impostor objects that fail every `is UNSET` check — which is
why typing_extensions <= 4.15 refused to pickle sentinels at all.

typing_extensions 4.16 implements Sentinel.__reduce__ as pickling by
reference (a lookup of the sentinel's name on its defining module), the same
mechanism enum members use, so the singleton identity survives the round
trip. Bump the floor and pin the behavior with tests: identity across
pickle/copy/deepcopy, models holding UNSET round-tripping, and a guard that
a non-importable sentinel still fails loudly rather than pickling by state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(zarr-metadata): format-version-first naming; dataclasses primary, JSON suffix for documents

Applies the naming decisions from the PR discussion: ZarrV2/ZarrV3 moves to
the front of every type name so a format version cannot be misread as a
class revision, and the model dataclasses take the bare entity names
(ZarrV3ArrayMetadata, ZarrV3GroupMetadata, ZarrV3ConsolidatedMetadata,
ZarrV3NamedConfig, role alias ZarrV3MetadataField) while the TypedDict
document forms carry a JSON suffix (ZarrV3ArrayMetadataJSON, ...,
ZarrV3MetadataFieldJSON, ZarrV3NamedConfigJSON).

The zarr_metadata.pydantic field types take the bare entity names, matching
the model classes they validate into; the module now references the model
module qualified to keep those names free. Raw-layer names released in 0.3.0
are renamed without aliases (pre-1.0), documented in changes/4119.removal.md.
Validation problem messages name documents in plain English instead of type
names. snake_case function names (validate_array_metadata_v3, ...) and
SCREAMING_SNAKE constants are deliberately untouched: the revision ambiguity
the rename fixes does not arise for them, and renaming them is a separate
decision.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(zarr-metadata): harden model validation

Assisted-by: Codex:gpt-5

* docs(zarr-metadata): define v3 conformance boundary

Assisted-by: Codex:gpt-5

* fix(zarr-metadata): preserve v3 extension obligations

Assisted-by: Codex:gpt-5

* fix(zarr-metadata): enforce v3 core extension rules

Assisted-by: Codex:gpt-5

* fix(zarr-metadata): align v3 additional field types

Assisted-by: Codex:gpt-5

* chore(zarr-metadata): finalize v3 model conformance

Assisted-by: Codex:gpt-5

* docs: remove llm docs

* chore(zarr-metadata): correct changelog PR number

Assisted-by: Codex:gpt-5

* fix(metadata): enforce canonical document boundaries

Assisted-by: Codex:GPT-5

* docs(metadata): record review fix design

Assisted-by: Codex:gpt-5

* fix(metadata): align validation and schemas

Assisted-by: Codex:gpt-5

* fix(metadata): tighten validation boundaries

Assisted-by: Codex:gpt-5

* fix(metadata): repair package CI

Assisted-by: Codex:gpt-5

* chore: remove stray design notes from docs

Assisted-by: ClaudeCode:claude-fable-5

* fix(zarr-metadata): deep-copy mutable state in to_json output

to_json previously returned documents holding direct references to the
model's internal dicts (attributes, named-config configurations, extra
fields, v2 compressor/filters, consolidated entries), so mutating a
serialized document silently mutated the frozen model. Every value that
can hold a mutable container is now deep-copied on the way out, with
parametrized tests proving mutation independence for all seven models.

Assisted-by: ClaudeCode:claude-fable-5

* docs(zarr-metadata): describe the widened package scope

The README tagline, intro, and scope section (and the PyPI description)
still presented the package as type definitions only. Restructure them
around the two layers plus optional integration, extend the contribution
scope to models and structural validation, and state the runtime-behavior
boundary explicitly.

Assisted-by: ClaudeCode:claude-fable-5

* style(zarr-metadata): move None to the end of the JSONValue union

The unpinned ruff in CI now enforces RUF036.

Assisted-by: ClaudeCode:claude-fable-5

* feat(zarr-metadata): export store-key aliases and type to_key_value with them

The six store-key Literal aliases were private and unused: only reachable
via underscore modules, and absent from every signature. Export them from
zarr_metadata.model beside their constants (matching the package's
name/constant pairing everywhere else), and key each to_key_value return
mapping by them so the store keys a model can emit are visible in its
signature. from_key_value keeps Mapping[str, bytes] input on purpose — it
accepts whole store mappings. A pair test guards export and value drift,
and the removal note now states the version-placement and JSON-suffix
conventions explicitly.

Assisted-by: ClaudeCode:claude-fable-5

* refactor(zarr-metadata): make every public type name parse against a naming grammar

Three grammars now cover the public surface, enforced by a conformance
test that walks every public module's __all__:

- core document/model names: ZarrV{2,3} + entity + optional role suffix
  (JSON / JSONPartial / Partial / StoreKey)
- extension-entity names: registered entity + exactly one role suffix
  (CodecMetadata, DataTypeName, FillValue, ...)
- a closed standalone-vocabulary allowlist for role-less scalar and
  diagnostic types, with a staleness guard

The three .z-file document types were the only names that fit no grammar
and are renamed: ZArrayMetadata -> ZarrV2ZArrayJSON, ZGroupMetadata ->
ZarrV2ZGroupJSON, ZAttrsMetadata -> ZarrV2ZAttrsJSON. The leading V2 of
V2ChunkKeyEncodingMetadata is that encoding's registered entity name, not
a format version; its module docstring now says so.

Assisted-by: ClaudeCode:claude-fable-5

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Potential issues with the zarr-python library release notes done Automatically applied to PRs which have release notes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant