Skip to content

Commit d4409e8

Browse files
author
NIK-TIGER-BILL
committed
fix(storage): add _is_open guard in ZipStore.exists to prevent AttributeError
ZipStore.exists() did not call self._sync_open() before accessing self._lock, causing AttributeError when called on an unopened store. Add the same _is_open check that other ZipStore methods (get, set, set_if_not_exists, delete) already use. Also add a regression test that instantiates ZipStore without an explicit .open() call and verifies exists() works correctly. Fixes #3588 Signed-off-by: NIK-TIGER-BILL <nik.tiger.bill@github.com>
1 parent 3a2ce2f commit d4409e8

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

src/zarr/storage/_zip.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ async def delete(self, key: str) -> None:
245245

246246
async def exists(self, key: str) -> bool:
247247
# docstring inherited
248+
if not self._is_open:
249+
self._sync_open()
248250
with self._lock:
249251
try:
250252
self._zf.getinfo(key)

tests/test_store/test_zip.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,24 @@ def test_externally_zipped_store(self, tmp_path: Path) -> None:
139139
assert isinstance(group := zipped["foo"], Group)
140140
assert list(group.keys()) == list(group.keys())
141141

142+
async def test_exists_without_explicit_open(self, tmp_path: Path) -> None:
143+
"""Regression test for https://github.com/zarr-developers/zarr-python/issues/3588.
144+
145+
ZipStore.exists() must not raise AttributeError when the store has not
146+
been explicitly opened beforehand (i.e. _sync_open() was not yet called).
147+
"""
148+
zip_path = tmp_path / "test.zip"
149+
# Create a zip file with one entry so exists() can return True
150+
with zipfile.ZipFile(zip_path, mode="w") as zf:
151+
zf.writestr("zarr.json", b"{}")
152+
153+
# Instantiate without calling .open() — this is the scenario from the issue
154+
store = ZipStore(zip_path, mode="r")
155+
# Before the fix this raised AttributeError: '_lock' attribute not found
156+
assert await store.exists("zarr.json") is True
157+
assert await store.exists("nonexistent") is False
158+
store.close()
159+
142160
async def test_move(self, tmp_path: Path) -> None:
143161
origin = tmp_path / "origin.zip"
144162
destination = tmp_path / "some_folder" / "destination.zip"

0 commit comments

Comments
 (0)