Skip to content

Commit 10f0d97

Browse files
committed
fixups
1 parent cb470d4 commit 10f0d97

File tree

12 files changed

+46
-73
lines changed

12 files changed

+46
-73
lines changed

src/zarr/abc/store.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ async def _ensure_open(self) -> None:
8282
if not self._is_open:
8383
await self._open()
8484

85-
async def empty(self, prefix: str = "") -> bool:
85+
async def empty_dir(self, prefix: str = "") -> bool:
8686
"""
8787
Check if the directory is empty.
8888
@@ -310,7 +310,7 @@ async def delete_dir(self, prefix: str) -> None:
310310
if not self.supports_listing:
311311
raise NotImplementedError
312312
self._check_writable()
313-
if not prefix.endswith("/"):
313+
if prefix and not prefix.endswith("/"):
314314
prefix += "/"
315315
async for key in self.list_prefix(prefix):
316316
await self.delete(key)

src/zarr/storage/common.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ def __init__(self, store: Store, path: str = "") -> None:
4545
self.store = store
4646
self.path = path
4747

48+
@property
49+
def readonly(self) -> bool:
50+
return self.store.readonly
51+
4852
@classmethod
4953
async def open(
5054
cls, store: Store, path: str, mode: AccessModeLiteral | None = None
@@ -79,7 +83,7 @@ async def open(
7983

8084
match mode:
8185
case "w-":
82-
if not await self.empty():
86+
if not await self.empty_dir():
8387
msg = (
8488
f"{self} is not empty, but `mode` is set to 'w-'."
8589
"Either remove the existing objects in storage,"
@@ -183,7 +187,7 @@ async def exists(self) -> bool:
183187
"""
184188
return await self.store.exists(self.path)
185189

186-
async def empty(self) -> bool:
190+
async def empty_dir(self) -> bool:
187191
"""
188192
Check if any keys exist in the store with the given prefix.
189193
@@ -192,7 +196,7 @@ async def empty(self) -> bool:
192196
bool
193197
True if no keys exist in the store with the given prefix, False otherwise.
194198
"""
195-
return await self.store.empty(self.path)
199+
return await self.store.empty_dir(self.path)
196200

197201
def __truediv__(self, other: str) -> StorePath:
198202
"""Combine this store path with another path"""

src/zarr/storage/logging.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,10 @@ async def _ensure_open(self) -> None:
135135
with self.log():
136136
return await self._store._ensure_open()
137137

138-
async def empty(self, prefix: str = "") -> bool:
138+
async def empty_dir(self, prefix: str = "") -> bool:
139139
# docstring inherited
140140
with self.log():
141-
return await self._store.empty(prefix=prefix)
141+
return await self._store.empty_dir(prefix=prefix)
142142

143143
async def clear(self) -> None:
144144
# docstring inherited

src/zarr/storage/memory.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@
1717
logger = getLogger(__name__)
1818

1919

20-
logger = getLogger(__name__)
21-
22-
2320
class MemoryStore(Store):
2421
"""
2522
In-memory store for testing purposes.

src/zarr/storage/zip.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,13 @@ def __init__(
6565
path: Path | str,
6666
*,
6767
mode: ZipStoreAccessModeLiteral = "r",
68-
readonly: bool = True,
68+
readonly: bool | None = None,
6969
compression: int = zipfile.ZIP_STORED,
7070
allowZip64: bool = True,
7171
) -> None:
72+
if readonly is None:
73+
readonly = mode == "r"
74+
7275
super().__init__(readonly=readonly)
7376

7477
if isinstance(path, str):
@@ -210,6 +213,8 @@ async def set_if_not_exists(self, key: str, value: Buffer) -> None:
210213
self._set(key, value)
211214

212215
async def delete_dir(self, prefix: str) -> None:
216+
# only raise NotImplementedError if any keys are found
217+
self._check_writable()
213218
if not prefix.endswith("/"):
214219
prefix += "/"
215220
async for _ in self.list_prefix(prefix):
@@ -219,6 +224,7 @@ async def delete(self, key: str) -> None:
219224
# docstring inherited
220225
# we choose to only raise NotImplementedError here if the key exists
221226
# this allows the array/group APIs to avoid the overhead of existence checks
227+
self._check_writable()
222228
if await self.exists(key):
223229
raise NotImplementedError
224230

src/zarr/testing/store.py

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ async def test_store_open_readonly(self, store_kwargs: dict[str, Any], readonly:
7575
assert store._is_open
7676
assert store.readonly == readonly
7777

78-
async def test_not_writable_store_raises(self, store_kwargs: dict[str, Any]) -> None:
78+
async def test_readonly_store_raises(self, store_kwargs: dict[str, Any]) -> None:
7979
kwargs = {**store_kwargs, "readonly": True}
8080
store = await self.store_cls.open(**kwargs)
8181
assert store.readonly
@@ -228,19 +228,21 @@ async def test_delete_dir(self, store: S) -> None:
228228
assert not await store.exists("foo/zarr.json")
229229
assert not await store.exists("foo/c/0")
230230

231-
async def test_empty(self, store: S) -> None:
232-
assert await store.empty()
231+
async def test_empty_dir(self, store: S) -> None:
232+
assert await store.empty_dir()
233233
await self.set(
234-
store, "key", self.buffer_cls.from_bytes(bytes("something", encoding="utf-8"))
234+
store, "foo/bar", self.buffer_cls.from_bytes(bytes("something", encoding="utf-8"))
235235
)
236-
assert not await store.empty()
236+
assert not await store.empty_dir()
237+
assert not await store.empty_dir("foo")
238+
assert await store.empty_dir("spam/")
237239

238240
async def test_clear(self, store: S) -> None:
239241
await self.set(
240242
store, "key", self.buffer_cls.from_bytes(bytes("something", encoding="utf-8"))
241243
)
242244
await store.clear()
243-
assert await store.empty()
245+
assert await store.empty_dir()
244246

245247
async def test_list(self, store: S) -> None:
246248
assert await _collect_aiterator(store.list()) == ()
@@ -297,40 +299,6 @@ async def test_list_dir(self, store: S) -> None:
297299
keys_observed = await _collect_aiterator(store.list_dir(root + "/"))
298300
assert sorted(keys_expected) == sorted(keys_observed)
299301

300-
# async def test_with_mode(self, store: S) -> None:
301-
# data = b"0000"
302-
# await self.set(store, "key", self.buffer_cls.from_bytes(data))
303-
# assert (await self.get(store, "key")).to_bytes() == data
304-
305-
# modes: list[StoreAccessMode] = ["r", "w"]
306-
# for mode in modes:
307-
# clone = store.with_mode(mode)
308-
# await clone._ensure_open()
309-
# assert clone.mode == mode
310-
# assert isinstance(clone, type(store))
311-
312-
# # earlier writes are visible
313-
# result = await clone.get("key", default_buffer_prototype())
314-
# assert result is not None
315-
# assert result.to_bytes() == data
316-
317-
# # writes to original after with_mode is visible
318-
# await self.set(store, "key-2", self.buffer_cls.from_bytes(data))
319-
# result = await clone.get("key-2", default_buffer_prototype())
320-
# assert result is not None
321-
# assert result.to_bytes() == data
322-
323-
# if mode == "w":
324-
# # writes to clone is visible in the original
325-
# await clone.set("key-3", self.buffer_cls.from_bytes(data))
326-
# result = await clone.get("key-3", default_buffer_prototype())
327-
# assert result is not None
328-
# assert result.to_bytes() == data
329-
330-
# else:
331-
# with pytest.raises(ValueError, match="store mode"):
332-
# await clone.set("key-3", self.buffer_cls.from_bytes(data))
333-
334302
async def test_set_if_not_exists(self, store: S) -> None:
335303
key = "k"
336304
data_buf = self.buffer_cls.from_bytes(b"0000")

src/zarr/testing/strategies.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
import zarr
1010
from zarr.core.array import Array
11-
12-
# from zarr.core.group import Group
1311
from zarr.storage import MemoryStore, StoreLike
1412

1513
# Copied from Xarray

tests/conftest.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ async def parse_store(
2828
store: Literal["local", "memory", "remote", "zip"], path: str
2929
) -> LocalStore | MemoryStore | RemoteStore | ZipStore:
3030
if store == "local":
31-
return await LocalStore.open(path, readonly=False)
31+
return await LocalStore.open(path)
3232
if store == "memory":
3333
return await MemoryStore.open(readonly=False)
3434
if store == "remote":
35-
return await RemoteStore.open(url=path, readonly=False)
35+
return await RemoteStore.open(url=path)
3636
if store == "zip":
37-
return await ZipStore.open(path + "/zarr.zip", readonly=False, mode="w")
37+
return await ZipStore.open(path + "/zarr.zip", mode="w")
3838
raise AssertionError
3939

4040

@@ -46,18 +46,18 @@ def path_type(request: pytest.FixtureRequest) -> Any:
4646
# todo: harmonize this with local_store fixture
4747
@pytest.fixture
4848
async def store_path(tmpdir: LEGACY_PATH) -> StorePath:
49-
store = await LocalStore.open(str(tmpdir), readonly=False)
49+
store = await LocalStore.open(str(tmpdir))
5050
return StorePath(store)
5151

5252

5353
@pytest.fixture
5454
async def local_store(tmpdir: LEGACY_PATH) -> LocalStore:
55-
return await LocalStore.open(str(tmpdir), readonly=False)
55+
return await LocalStore.open(str(tmpdir))
5656

5757

5858
@pytest.fixture
5959
async def remote_store(url: str) -> RemoteStore:
60-
return await RemoteStore.open(url, readonly=False)
60+
return await RemoteStore.open(url)
6161

6262

6363
@pytest.fixture
@@ -67,7 +67,7 @@ async def memory_store() -> MemoryStore:
6767

6868
@pytest.fixture
6969
async def zip_store(tmpdir: LEGACY_PATH) -> ZipStore:
70-
return await ZipStore.open(str(tmpdir / "zarr.zip"), mode="w", readonly=False)
70+
return await ZipStore.open(str(tmpdir / "zarr.zip"), mode="w")
7171

7272

7373
@pytest.fixture

tests/test_store/test_core.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ async def test_make_store_path_local(
4040
assert isinstance(store_path.store, LocalStore)
4141
assert Path(store_path.store.root) == Path(tmpdir)
4242
assert store_path.path == normalize_path(path)
43-
assert store_path.store.readonly == (mode == "r")
43+
assert store_path.readonly == (mode == "r")
4444

4545

4646
@pytest.mark.parametrize("path", [None, "", "bar"])
@@ -60,7 +60,7 @@ async def test_make_store_path_store_path(
6060
path_normalized = normalize_path(path)
6161
assert store_path.path == (store_like / path_normalized).path
6262

63-
assert store_path.store.readonly == (mode == "r")
63+
assert store_path.readonly == ro
6464

6565

6666
async def test_make_store_path_invalid() -> None:

tests/test_store/test_local.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ def test_store_supports_listing(self, store: LocalStore) -> None:
4343
assert store.supports_listing
4444

4545
async def test_empty_with_empty_subdir(self, store: LocalStore) -> None:
46-
assert await store.empty()
46+
assert await store.empty_dir()
4747
(store.root / "foo/bar").mkdir(parents=True)
48-
assert await store.empty()
48+
assert await store.empty_dir()
4949

5050
def test_creates_new_directory(self, tmp_path: pathlib.Path):
5151
target = tmp_path.joinpath("a", "b", "c")

0 commit comments

Comments
 (0)