Skip to content

Commit 857267f

Browse files
authored
Merge branch 'main' into deterministic-chunk-padding
2 parents b438ba8 + f4278a5 commit 857267f

File tree

6 files changed

+66
-1
lines changed

6 files changed

+66
-1
lines changed

.github/workflows/test.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ jobs:
4545

4646
steps:
4747
- uses: actions/checkout@v4
48+
with:
49+
fetch-depth: 0 # grab all branches and tags
4850
- name: Set up Python
4951
uses: actions/setup-python@v5
5052
with:
@@ -82,6 +84,8 @@ jobs:
8284
dependency-set: upstream
8385
steps:
8486
- uses: actions/checkout@v4
87+
with:
88+
fetch-depth: 0
8589
- name: Set up Python
8690
uses: actions/setup-python@v5
8791
with:

changes/2758.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix zip-store path checking for stores with directories listed as files.

changes/2811.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Update numcodecs to not overwrite codec configuration ever. Closes :issue:`2800`.

src/zarr/storage/_zip.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ async def list_dir(self, prefix: str) -> AsyncIterator[str]:
283283
yield key
284284
else:
285285
for key in keys:
286-
if key.startswith(prefix + "/") and key != prefix:
286+
if key.startswith(prefix + "/") and key.strip("/") != prefix:
287287
k = key.removeprefix(prefix + "/").split("/")[0]
288288
if k not in seen:
289289
seen.add(k)

tests/test_array.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import numcodecs
1111
import numpy as np
1212
import pytest
13+
from packaging.version import Version
1314

1415
import zarr.api.asynchronous
1516
import zarr.api.synchronous as sync_api
@@ -1337,3 +1338,47 @@ async def test_orthogonal_set_total_slice() -> None:
13371338
array = zarr.create_array(store, shape=(20, 20), chunks=(1, 2), dtype=int, fill_value=-1)
13381339
with mock.patch("zarr.storage.MemoryStore.get", side_effect=ValueError):
13391340
array[0, slice(4, 10)] = np.arange(6)
1341+
1342+
1343+
@pytest.mark.skipif(
1344+
Version(numcodecs.__version__) < Version("0.15.1"),
1345+
reason="codec configuration is overwritten on older versions. GH2800",
1346+
)
1347+
def test_roundtrip_numcodecs() -> None:
1348+
store = MemoryStore()
1349+
1350+
compressors = [
1351+
{"name": "numcodecs.shuffle", "configuration": {"elementsize": 2}},
1352+
{"name": "numcodecs.zlib", "configuration": {"level": 4}},
1353+
]
1354+
filters = [
1355+
{
1356+
"name": "numcodecs.fixedscaleoffset",
1357+
"configuration": {
1358+
"scale": 100.0,
1359+
"offset": 0.0,
1360+
"dtype": "<f8",
1361+
"astype": "<i2",
1362+
},
1363+
},
1364+
]
1365+
1366+
# Create the array with the correct codecs
1367+
root = zarr.group(store)
1368+
root.create_array(
1369+
"test",
1370+
shape=(720, 1440),
1371+
chunks=(720, 1440),
1372+
dtype="float64",
1373+
compressors=compressors,
1374+
filters=filters,
1375+
fill_value=-9.99,
1376+
dimension_names=["lat", "lon"],
1377+
)
1378+
1379+
BYTES_CODEC = {"name": "bytes", "configuration": {"endian": "little"}}
1380+
# Read in the array again and check compressor config
1381+
root = zarr.open_group(store, mode="r")
1382+
metadata = root["test"].metadata.to_dict()
1383+
expected = (*filters, BYTES_CODEC, *compressors)
1384+
assert metadata["codecs"] == expected

tests/test_store/test_zip.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import os
4+
import shutil
45
import tempfile
56
import zipfile
67
from typing import TYPE_CHECKING
@@ -14,6 +15,7 @@
1415
from zarr.testing.store import StoreTests
1516

1617
if TYPE_CHECKING:
18+
from pathlib import Path
1719
from typing import Any
1820

1921

@@ -111,3 +113,15 @@ async def test_zip_open_mode_translation(
111113
kws = {**store_kwargs, "mode": zip_mode}
112114
store = await self.store_cls.open(**kws)
113115
assert store.read_only == read_only
116+
117+
def test_externally_zipped_store(self, tmp_path: Path) -> None:
118+
# See: https://github.com/zarr-developers/zarr-python/issues/2757
119+
zarr_path = tmp_path / "foo.zarr"
120+
root = zarr.open_group(store=zarr_path, mode="w")
121+
root.require_group("foo")
122+
root["foo"]["bar"] = np.array([1])
123+
shutil.make_archive(zarr_path, "zip", zarr_path)
124+
zip_path = tmp_path / "foo.zarr.zip"
125+
zipped = zarr.open_group(ZipStore(zip_path, mode="r"), mode="r")
126+
assert list(zipped.keys()) == list(root.keys())
127+
assert list(zipped["foo"].keys()) == list(root["foo"].keys())

0 commit comments

Comments
 (0)