Skip to content

Commit addb785

Browse files
authored
Merge branch 'main' into creation-from-other-zarr
2 parents 4f3e156 + 45146ca commit addb785

File tree

13 files changed

+201
-67
lines changed

13 files changed

+201
-67
lines changed

.github/workflows/test.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@ jobs:
6060
hatch env run -e test.py${{ matrix.python-version }}-${{ matrix.numpy-version }}-${{ matrix.dependency-set }} list-env
6161
- name: Run Tests
6262
run: |
63-
hatch env run --env test.py${{ matrix.python-version }}-${{ matrix.numpy-version }}-${{ matrix.dependency-set }} run
63+
hatch env run --env test.py${{ matrix.python-version }}-${{ matrix.numpy-version }}-${{ matrix.dependency-set }} run-coverage
64+
- name: Upload coverage
65+
uses: codecov/codecov-action@v5
66+
with:
67+
token: ${{ secrets.CODECOV_TOKEN }}
68+
verbose: true # optional (default = false)
6469

6570
test-upstream-and-min-deps:
6671
name: py=${{ matrix.python-version }}-${{ matrix.dependency-set }}

codecov.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
coverage:
2+
status:
3+
patch:
4+
default:
5+
target: auto
6+
project:
7+
default:
8+
target: auto
9+
threshold: 0.1
10+
comment: false

docs/conf.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def skip_submodules(
9191

9292
# General information about the project.
9393
project = "zarr"
94-
copyright = "2024, Zarr Developers"
94+
copyright = "2025, Zarr Developers"
9595
author = "Zarr Developers"
9696

9797
version = get_version("zarr")
@@ -181,6 +181,7 @@ def skip_submodules(
181181
],
182182
"collapse_navigation": True,
183183
"navigation_with_keys": False,
184+
"announcement": "Zarr-Python 3 is here! Check out the release announcement <a href='https://zarr.dev/blog/zarr-python-3-release/'>here.</a>",
184185
}
185186

186187
# Add any paths that contain custom themes here, relative to this directory.

docs/developers/contributing.rst

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -329,10 +329,16 @@ Release procedure
329329
Most of the release process is now handled by GitHub workflow which should
330330
automatically push a release to PyPI if a tag is pushed.
331331

332-
Before releasing, make sure that all pull requests which will be
333-
included in the release have been properly documented in
334-
`docs/release.rst`.
335-
332+
Pre-release
333+
"""""""""""
334+
1. Make sure that all pull requests which will be
335+
included in the release have been properly documented in
336+
:file:`docs/release-notes.rst`.
337+
2. Rename the "Unreleased" section heading in :file:`docs/release-notes.rst`
338+
to the version you are about to release.
339+
340+
Releasing
341+
"""""""""
336342
To make a new release, go to
337343
https://github.com/zarr-developers/zarr-python/releases and
338344
click "Draft a new release". Choose a version number prefixed
@@ -355,5 +361,8 @@ https://readthedocs.io. Full releases will be available under
355361
pre-releases will be available under
356362
`/latest <https://zarr.readthedocs.io/en/latest>`_.
357363

358-
Also review and merge the https://github.com/conda-forge/zarr-feedstock
359-
pull request that will be automatically generated.
364+
Post-release
365+
""""""""""""
366+
367+
- Review and merge the pull request on the `conda-forge feedstock <https://github.com/conda-forge/zarr-feedstock>`_ that will be automatically generated.
368+
- Create a new "Unreleased" section in the release notes

docs/quickstart.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Zarr supports data compression and filters. For example, to use Blosc compressio
7474
... "data/example-3.zarr",
7575
... mode="w", shape=(100, 100),
7676
... chunks=(10, 10), dtype="f4",
77-
... compressor=zarr.codecs.BloscCodec(cname="zstd", clevel=3, shuffle=zarr.codecs.BloscShuffle.SHUFFLE)
77+
... compressors=zarr.codecs.BloscCodec(cname="zstd", clevel=3, shuffle=zarr.codecs.BloscShuffle.shuffle)
7878
... )
7979
>>> z[:, :] = np.random.random((100, 100))
8080
>>>
@@ -101,7 +101,7 @@ Zarr allows you to create hierarchical groups, similar to directories::
101101
>>> root = zarr.group("data/example-2.zarr")
102102
>>> foo = root.create_group(name="foo")
103103
>>> bar = root.create_array(
104-
... name="bar", shape=(100, 10), chunks=(10, 10)
104+
... name="bar", shape=(100, 10), chunks=(10, 10), dtype="f4"
105105
... )
106106
>>> spam = foo.create_array(name="spam", shape=(10,), dtype="i4")
107107
>>>
@@ -112,6 +112,7 @@ Zarr allows you to create hierarchical groups, similar to directories::
112112
>>> # print the hierarchy
113113
>>> root.tree()
114114
/
115+
├── bar (100, 10) float32
115116
└── foo
116117
└── spam (10,) int32
117118
<BLANKLINE>
@@ -130,7 +131,7 @@ using external libraries like `s3fs <https://s3fs.readthedocs.io>`_ or
130131

131132
>>> import s3fs # doctest: +SKIP
132133
>>>
133-
>>> z = zarr.create_array("s3://example-bucket/foo", mode="w", shape=(100, 100), chunks=(10, 10)) # doctest: +SKIP
134+
>>> z = zarr.create_array("s3://example-bucket/foo", mode="w", shape=(100, 100), chunks=(10, 10), dtype="f4") # doctest: +SKIP
134135
>>> z[:, :] = np.random.random((100, 100)) # doctest: +SKIP
135136

136137
A single-file store can also be created using the the :class:`zarr.storage.ZipStore`::

docs/release-notes.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,29 @@
11
Release notes
22
=============
33

4+
Unreleased
5+
----------
6+
7+
New features
8+
~~~~~~~~~~~~
9+
10+
Bug fixes
11+
~~~~~~~~~
12+
* Fixes ``order`` argument for Zarr format 2 arrays (:issue:`2679`).
13+
14+
* Fixes a bug that prevented reading Zarr format 2 data with consolidated metadata written using ``zarr-python`` version 2 (:issue:`2694`).
15+
16+
* Ensure that compressor=None results in no compression when writing Zarr format 2 data (:issue:`2708`)
17+
18+
Behaviour changes
19+
~~~~~~~~~~~~~~~~~
20+
21+
Other
22+
~~~~~
23+
* Removed some unnecessary files from the source distribution
24+
to reduce its size. (:issue:`2686`)
25+
26+
427
.. _release_3.0.0:
528

629
3.0.0

pyproject.toml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
requires = ["hatchling", "hatch-vcs"]
33
build-backend = "hatchling.build"
44

5+
[tool.hatch.build.targets.sdist]
6+
exclude = [
7+
"/.github",
8+
"/bench",
9+
"/docs",
10+
"/notebooks"
11+
]
512

613
[project]
714
name = "zarr"
@@ -103,13 +110,13 @@ Homepage = "https://github.com/zarr-developers/zarr-python"
103110
[tool.coverage.report]
104111
exclude_lines = [
105112
"pragma: no cover",
113+
"if TYPE_CHECKING:",
106114
"pragma: ${PY_MAJOR_VERSION} no cover",
107115
'.*\.\.\.' # Ignore "..." lines
108116
]
109117

110118
[tool.coverage.run]
111119
omit = [
112-
"src/zarr/meta_v1.py",
113120
"bench/compress_normal.py",
114121
]
115122

@@ -140,8 +147,8 @@ numpy = ["1.25", "2.1"]
140147
features = ["gpu"]
141148

142149
[tool.hatch.envs.test.scripts]
143-
run-coverage = "pytest --cov-config=pyproject.toml --cov=pkg --cov=src"
144-
run-coverage-gpu = "pip install cupy-cuda12x && pytest -m gpu --cov-config=pyproject.toml --cov=pkg --cov=src"
150+
run-coverage = "pytest --cov-config=pyproject.toml --cov=pkg --cov-report xml --cov=src --junitxml=junit.xml -o junit_family=legacy"
151+
run-coverage-gpu = "pip install cupy-cuda12x && pytest -m gpu --cov-config=pyproject.toml --cov=pkg --cov-report xml --cov=src --junitxml=junit.xml -o junit_family=legacy"
145152
run = "run-coverage --no-cov"
146153
run-verbose = "run-coverage --verbose"
147154
run-mypy = "mypy src"
@@ -170,7 +177,7 @@ numpy = ["1.25", "2.1"]
170177
version = ["minimal"]
171178

172179
[tool.hatch.envs.gputest.scripts]
173-
run-coverage = "pytest -m gpu --cov-config=pyproject.toml --cov=pkg --cov=src"
180+
run-coverage = "pytest -m gpu --cov-config=pyproject.toml --cov=pkg --cov-report xml --cov=src --junitxml=junit.xml -o junit_family=legacy"
174181
run = "run-coverage --no-cov"
175182
run-verbose = "run-coverage --verbose"
176183
run-mypy = "mypy src"

src/zarr/core/array.py

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import warnings
55
from asyncio import gather
66
from collections.abc import Iterable
7-
from dataclasses import dataclass, field
7+
from dataclasses import dataclass, field, replace
88
from itertools import starmap
99
from logging import getLogger
1010
from typing import (
@@ -1227,14 +1227,17 @@ async def _get_selection(
12271227
fill_value=self.metadata.fill_value,
12281228
)
12291229
if product(indexer.shape) > 0:
1230+
# need to use the order from the metadata for v2
1231+
_config = self._config
1232+
if self.metadata.zarr_format == 2:
1233+
_config = replace(_config, order=self.metadata.order)
1234+
12301235
# reading chunks and decoding them
12311236
await self.codec_pipeline.read(
12321237
[
12331238
(
12341239
self.store_path / self.metadata.encode_chunk_key(chunk_coords),
1235-
self.metadata.get_chunk_spec(
1236-
chunk_coords, self._config, prototype=prototype
1237-
),
1240+
self.metadata.get_chunk_spec(chunk_coords, _config, prototype=prototype),
12381241
chunk_selection,
12391242
out_selection,
12401243
)
@@ -1351,12 +1354,17 @@ async def _set_selection(
13511354
# Buffer and NDBuffer between components.
13521355
value_buffer = prototype.nd_buffer.from_ndarray_like(value)
13531356

1357+
# need to use the order from the metadata for v2
1358+
_config = self._config
1359+
if self.metadata.zarr_format == 2:
1360+
_config = replace(_config, order=self.metadata.order)
1361+
13541362
# merging with existing data and encoding chunks
13551363
await self.codec_pipeline.write(
13561364
[
13571365
(
13581366
self.store_path / self.metadata.encode_chunk_key(chunk_coords),
1359-
self.metadata.get_chunk_spec(chunk_coords, self._config, prototype),
1367+
self.metadata.get_chunk_spec(chunk_coords, _config, prototype),
13601368
chunk_selection,
13611369
out_selection,
13621370
)
@@ -4393,15 +4401,22 @@ def _parse_chunk_encoding_v3(
43934401

43944402

43954403
def _parse_deprecated_compressor(
4396-
compressor: CompressorLike | None, compressors: CompressorsLike
4404+
compressor: CompressorLike | None, compressors: CompressorsLike, zarr_format: int = 3
43974405
) -> CompressorsLike | None:
4398-
if compressor:
4406+
if compressor != "auto":
43994407
if compressors != "auto":
44004408
raise ValueError("Cannot specify both `compressor` and `compressors`.")
4401-
warn(
4402-
"The `compressor` argument is deprecated. Use `compressors` instead.",
4403-
category=UserWarning,
4404-
stacklevel=2,
4405-
)
4406-
compressors = (compressor,)
4409+
if zarr_format == 3:
4410+
warn(
4411+
"The `compressor` argument is deprecated. Use `compressors` instead.",
4412+
category=UserWarning,
4413+
stacklevel=2,
4414+
)
4415+
if compressor is None:
4416+
# "no compression"
4417+
compressors = ()
4418+
else:
4419+
compressors = (compressor,)
4420+
elif zarr_format == 2 and compressor == compressors == "auto":
4421+
compressors = ({"id": "blosc"},)
44074422
return compressors

src/zarr/core/group.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -573,8 +573,8 @@ def _from_bytes_v2(
573573
v2_consolidated_metadata = json.loads(consolidated_metadata_bytes.to_bytes())
574574
v2_consolidated_metadata = v2_consolidated_metadata["metadata"]
575575
# We already read zattrs and zgroup. Should we ignore these?
576-
v2_consolidated_metadata.pop(".zattrs")
577-
v2_consolidated_metadata.pop(".zgroup")
576+
v2_consolidated_metadata.pop(".zattrs", None)
577+
v2_consolidated_metadata.pop(".zgroup", None)
578578

579579
consolidated_metadata: defaultdict[str, dict[str, Any]] = defaultdict(dict)
580580

@@ -1011,7 +1011,7 @@ async def create_array(
10111011
shards: ShardsLike | None = None,
10121012
filters: FiltersLike = "auto",
10131013
compressors: CompressorsLike = "auto",
1014-
compressor: CompressorLike = None,
1014+
compressor: CompressorLike = "auto",
10151015
serializer: SerializerLike = "auto",
10161016
fill_value: Any | None = 0,
10171017
order: MemoryOrder | None = None,
@@ -1114,8 +1114,9 @@ async def create_array(
11141114
AsyncArray
11151115
11161116
"""
1117-
1118-
compressors = _parse_deprecated_compressor(compressor, compressors)
1117+
compressors = _parse_deprecated_compressor(
1118+
compressor, compressors, zarr_format=self.metadata.zarr_format
1119+
)
11191120
return await create_array(
11201121
store=self.store_path,
11211122
name=name,
@@ -2244,7 +2245,7 @@ def create_array(
22442245
shards: ShardsLike | None = None,
22452246
filters: FiltersLike = "auto",
22462247
compressors: CompressorsLike = "auto",
2247-
compressor: CompressorLike = None,
2248+
compressor: CompressorLike = "auto",
22482249
serializer: SerializerLike = "auto",
22492250
fill_value: Any | None = 0,
22502251
order: MemoryOrder | None = "C",
@@ -2346,7 +2347,9 @@ def create_array(
23462347
-------
23472348
AsyncArray
23482349
"""
2349-
compressors = _parse_deprecated_compressor(compressor, compressors)
2350+
compressors = _parse_deprecated_compressor(
2351+
compressor, compressors, zarr_format=self.metadata.zarr_format
2352+
)
23502353
return Array(
23512354
self._sync(
23522355
self._async_group.create_array(

tests/test_group.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import numpy as np
1111
import pytest
12-
from numcodecs import Zstd
12+
from numcodecs import Blosc
1313

1414
import zarr
1515
import zarr.api.asynchronous
@@ -499,7 +499,7 @@ def test_group_child_iterators(store: Store, zarr_format: ZarrFormat, consolidat
499499
"chunks": (1,),
500500
"order": "C",
501501
"filters": None,
502-
"compressor": Zstd(level=0),
502+
"compressor": Blosc(),
503503
"zarr_format": zarr_format,
504504
},
505505
"subgroup": {
@@ -1505,13 +1505,3 @@ def test_group_members_concurrency_limit(store: MemoryStore) -> None:
15051505
elapsed = time.time() - start
15061506

15071507
assert elapsed > num_groups * get_latency
1508-
1509-
1510-
@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"])
1511-
def test_deprecated_compressor(store: Store) -> None:
1512-
g = zarr.group(store=store, zarr_format=2)
1513-
with pytest.warns(UserWarning, match="The `compressor` argument is deprecated.*"):
1514-
a = g.create_array(
1515-
"foo", shape=(100,), chunks=(10,), dtype="i4", compressor={"id": "blosc"}
1516-
)
1517-
assert a.metadata.compressor.codec_id == "blosc"

0 commit comments

Comments
 (0)