Skip to content

fix(api): accept create keyword arguments when zarr.array copies a zarr array - #4419

Draft
d-v-b wants to merge 2 commits into
zarr-developers:mainfrom
d-v-b:fix/array-from-zarr-array
Draft

d-v-b wants to merge 2 commits into
zarr-developers:mainfrom
d-v-b:fix/array-from-zarr-array

Conversation

@d-v-b

@d-v-b d-v-b commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

🤖 AI text below 🤖

zarr.array documents its keyword arguments as "passed through to create". Since #2622, though, a zarr Array passed as data was sent to from_array instead. from_array requires store and takes a different set of arguments, so the same call behaved differently depending on the type of data:

src = zarr.create_array({}, shape=(6,), chunks=(2,), dtype="int32")

zarr.array(src[:])                     # works
zarr.array(src)                        # TypeError: from_array() missing ... 'store'
zarr.array(src, store={}, mode="w")    # TypeError: unexpected keyword argument 'mode'
zarr.array(src, store={}, dtype="f8")  # TypeError: unexpected keyword argument 'dtype'

The agent found this in an audit of **kwargs forwarding (see #4408).

Change

A zarr Array now takes the same create path as any other data:

  • Defaults from the source: shape, dtype and chunks. The dtype default is the source's zarr data type, not its native dtype, which can't identify string types. from_array makes the same distinction.
  • Rectilinear sources: chunks is undefined for an unsharded rectilinear grid, so the default falls back to read_chunk_sizes and the grid is kept. Creating that array still needs array.rectilinear_chunks enabled.
  • Streaming is kept. Data is still copied one shard region at a time, not read into memory. The copy loop is now _copy_from_array, factored out of from_array and shared by both functions.

The docstring now points to from_array for copying a zarr array's codecs and other settings.

Behaviour change

Before this PR, calls with a zarr source that happened to use only arguments from_array accepts (for example zarr.array(src, store=s, overwrite=True)) worked, and inherited the source's codecs, fill value, attributes and zarr format. They now get create's defaults for those, exactly as NumPy data does. Code that relies on inheriting those settings should call zarr.from_array, which is the dedicated API for it.

Tests

  • test_array_from_zarr_array: sources (v2, v3, sharded, rectilinear, variable-length string) × argument sets (none, store, store+path+mode+attributes, chunks, zarr_format, fill_value). Checks shape, data, zarr dtype, chunks, format, attributes, fill value and path. On main, 25 of the 29 cases fail; only the four store-only cases pass.
  • One test per error case: test_array_from_zarr_array_rectilinear_v2 (format 2 cannot hold a rectilinear grid) and test_array_from_zarr_array_read_only. Both fail on main, where a zarr source raises TypeError from from_array instead.

The full test suite passes locally, and so does mypy.

🤖 Generated with Claude Code

…rr array

zarr.array documents its keyword arguments as passed through to create,
but a zarr Array as data was sent to from_array instead, which requires
store and takes a different set of arguments. zarr.array(zarr_array)
raised "missing store", and create arguments such as compressor, mode or
read_only raised TypeError, while the same call with NumPy data worked.

A zarr Array now takes the create path like any other data. Its zarr
dtype (not the native dtype, which cannot identify string types), shape
and chunks are the defaults, and a rectilinear grid is kept through
read_chunk_sizes. The data is still streamed one shard region at a time
by _copy_from_array, factored out of from_array.

Assisted-by: ClaudeCode:claude-opus-5-5
@github-actions github-actions Bot added the needs release notes Automatically applied to PRs which haven't added release notes label Sep 26, 2026
Assisted-by: ClaudeCode:claude-opus-5-5
@github-actions github-actions Bot removed the needs release notes Automatically applied to PRs which haven't added release notes label Sep 26, 2026
@codecov

codecov Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.39%. Comparing base (f58644a) to head (95513ca).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4419      +/-   ##
==========================================
+ Coverage   94.37%   94.39%   +0.01%     
==========================================
  Files          93       93              
  Lines       13171    13179       +8     
==========================================
+ Hits        12430    12440      +10     
+ Misses        741      739       -2     
Files with missing lines Coverage Δ
src/zarr/api/asynchronous.py 96.76% <100.00%> (+0.43%) ⬆️
src/zarr/api/synchronous.py 92.95% <ø> (ø)
src/zarr/core/array.py 98.18% <100.00%> (+0.09%) ⬆️
🚀 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 added this to the 3.5.0 milestone Sep 29, 2026

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant