Skip to content

fix: replace runtime assert statements with explicit checks - #4363

Merged
d-v-b merged 4 commits into
zarr-developers:mainfrom
d-v-b:claude/audit-remove-asserts-7936f9
Sep 16, 2026
Merged

d-v-b merged 4 commits into
zarr-developers:mainfrom
d-v-b:claude/audit-remove-asserts-7936f9

Conversation

@d-v-b

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

Copy link
Copy Markdown
Contributor

AI-authored PR that removes runtime assert statements. closes #4362

🤖 AI text below 🤖

Summary

Removes every assert statement from runtime code under src/zarr/ and enables ruff's S101 rule so new ones are flagged. Asserts are stripped under python -O, so any check that matters for correctness or for narrowing a type must be an explicit if/raise.

Two of the 47 asserts were load-bearing:

  • GroupMetadata.from_dict asserted that node_type was "group", and zarr.api.asynchronous.open caught AssertionError to fall back from array to group. Under -O that fallback silently disappeared. It now raises NodeTypeValidationError, which that call site already catches, and the AssertionError catch is gone.
  • make_store asserted on mode, but the real validation lives downstream in StorePath.open. A bad user-supplied mode now raises the same ValueError there.

The rest fall into three buckets:

  • Deleted (25): redundant with type annotations (isinstance(key, str) in the stores, isinstance(chunk_array, NDBuffer) in codecs) or with an existing check (Buffer.combine dtype checks the constructor already enforces).
  • Restructured so mypy narrows on its own (11): locals in _get_loop and _validate_scalar_map, a hoisted sync_transform in the codec-pipeline write path, and get_array_metadata returning from each branch via two small helpers.
  • Converted to explicit raises (11): user-reachable ones raise ValueError; unsupported-feature ones in the shard byte getter/setter raise ValueError/NotImplementedError; impossible-state ones (a None shard index, a missing sync transform) raise RuntimeError.

src/zarr/testing/ is excluded from S101 along with tests/: the store conformance suite and hypothesis strategies assert on purpose.

For reviewers

Behavior is meant to be unchanged for anyone not running under -O. Worth a second look:

  • The exception types chosen for the converted asserts, especially RuntimeError for the impossible-state cases in sharding.py and codec_pipeline.py.
  • The get_array_metadata restructure in array.py. It is the largest diff and the only one that moves logic around rather than swapping a line.
  • The import-time version check in zarr/__init__.py now raises RuntimeError unconditionally instead of only outside -O.

Author attestation

  • I am a human, these are my changes, and I have reviewed and understood every change and can explain why each is correct.

TODO

  • Add unit tests and/or doctests in docstrings (one test per new user-reachable error)
  • Add docstrings and API docs for any new/modified user-facing classes and functions (none)
  • New/modified features documented in docs/user-guide/*.md (n/a)
  • Changes documented as a new file in changes/
  • GitHub Actions have all passed
  • Test coverage is 100% (Codecov passes)

🤖 Generated with Claude Code

Asserts are stripped under `python -O`, so checks that matter for
correctness or type narrowing must be explicit. Two were load-bearing:
`GroupMetadata.from_dict` asserted on node_type and the array-to-group
fallback in `zarr.api.asynchronous.open` caught the AssertionError, and
`make_store` asserted on mode ahead of the real validation.

Redundant asserts are deleted, narrowing asserts are restructured so
mypy narrows on its own, and the rest become explicit raises. Ruff S101
is enabled with `tests/` and `src/zarr/testing/` excluded.

Assisted-by: ClaudeCode:claude-fable-5-1
Assisted-by: ClaudeCode:claude-fable-5-1
@read-the-docs-community

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

Copy link
Copy Markdown

@d-v-b d-v-b mentioned this pull request Sep 16, 2026
The S101 per-file ignores only covered the root tests/ and
src/zarr/testing/. The packages under packages/ inherit the root ruff
config, so the rule fired on 1524 asserts in their tests, examples, and
test-support modules and broke the ruff, Lint, pre-commit.ci, and
zarr-http-server jobs. Widen the ignores to **/tests/**, **/examples/**,
and **/testing/**, and exclude zarr-indexing's runtime source for now;
its own asserts are tracked as a separate change.

Assisted-by: ClaudeCode:claude-fable-5-1
@codecov

codecov Bot commented Sep 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.51948% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.22%. Comparing base (b6c592e) to head (89bfbd0).

Files with missing lines Patch % Lines
src/zarr/codecs/sharding.py 50.00% 5 Missing ⚠️
src/zarr/core/codec_pipeline.py 78.94% 4 Missing ⚠️
src/zarr/core/group.py 66.66% 3 Missing ⚠️
src/zarr/__init__.py 50.00% 1 Missing ⚠️
src/zarr/codecs/cast_value.py 80.00% 1 Missing ⚠️
src/zarr/core/buffer/gpu.py 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4363      +/-   ##
==========================================
- Coverage   94.34%   94.22%   -0.12%     
==========================================
  Files          92       92              
  Lines       12948    12942       -6     
==========================================
- Hits        12216    12195      -21     
- Misses        732      747      +15     
Files with missing lines Coverage Δ
src/zarr/api/asynchronous.py 96.32% <100.00%> (ø)
src/zarr/codecs/bytes.py 98.78% <ø> (-0.03%) ⬇️
src/zarr/codecs/vlen_utf8.py 96.61% <ø> (-0.36%) ⬇️
src/zarr/core/array.py 98.09% <100.00%> (+<0.01%) ⬆️
src/zarr/core/buffer/cpu.py 100.00% <ø> (ø)
src/zarr/core/sync.py 94.23% <100.00%> (ø)
src/zarr/storage/_common.py 93.17% <100.00%> (+0.03%) ⬆️
src/zarr/storage/_local.py 97.61% <ø> (-0.06%) ⬇️
src/zarr/storage/_memory.py 96.18% <ø> (-0.10%) ⬇️
src/zarr/storage/_zip.py 98.16% <ø> (-0.02%) ⬇️
... and 6 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@d-v-b
d-v-b marked this pull request as ready for review September 16, 2026 10:55
@d-v-b

d-v-b commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

this gets merged when it's green

@d-v-b
d-v-b merged commit 9f0ae4e into zarr-developers:main Sep 16, 2026
39 checks passed
d-v-b added a commit to d-v-b/zarr-python that referenced this pull request Sep 16, 2026
Resolves the conflict in `LocalStore.get`, where main's zarr-developers#4363 removed the
redundant `assert isinstance(key, str)` on a line adjacent to this branch's
switch from the inline `if not self._is_open: await self._open()` to
`await self._ensure_open()`. Both changes are kept: the lazy open goes through
the race-tolerant `_ensure_open`, without the assert.

The four other asserts zarr-developers#4363 removed from this file merged cleanly, and the
S101 lint it enabled is satisfied - this branch adds asserts only under
tests/, which the rule excludes.

Assisted-by: ClaudeCode:claude-opus-5
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
d-v-b added a commit to d-v-b/zarr-python that referenced this pull request Sep 19, 2026
…eate_* factories

Upstream enabled ruff S101 for runtime code (zarr-developers#4363). The six
parse-then-raise factories share a _parsed_or_raise helper that narrows
the parsed document, and the rule-registration import uses
importlib.import_module instead of an assert to keep it referenced.

Assisted-by: ClaudeCode:claude-opus-5
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
d-v-b added a commit to d-v-b/zarr-python that referenced this pull request Sep 19, 2026
…eate_* factories

Upstream enabled ruff S101 for runtime code (zarr-developers#4363). The six
parse-then-raise factories share a _parsed_or_raise helper that narrows
the parsed document, and the rule-registration import uses
importlib.import_module instead of an assert to keep it referenced.

Assisted-by: ClaudeCode:claude-opus-5
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bad assert usage

1 participant