Skip to content

Commit f9dbd5b

Browse files
committed
respond to reviews
1 parent ebe8b67 commit f9dbd5b

File tree

6 files changed

+38
-22
lines changed

6 files changed

+38
-22
lines changed

docs/guide/storage.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ filesystem.
4343
.. code-block:: python
4444
4545
>>> import zarr
46-
>>> store = zarr.storage.LocalStore("data/foo/bar", readonly=True)
46+
>>> store = zarr.storage.LocalStore("data/foo/bar", read_only=True)
4747
>>> zarr.open(store=store)
4848
<Group file://data/foo/bar>
4949
@@ -72,7 +72,7 @@ that implements the `AbstractFileSystem` API,
7272
.. code-block:: python
7373
7474
>>> import zarr
75-
>>> store = zarr.storage.RemoteStore.from_url("gs://foo/bar", readonly=True)
75+
>>> store = zarr.storage.RemoteStore.from_url("gs://foo/bar", read_only=True)
7676
>>> zarr.open(store=store)
7777
<Array <RemoteStore(GCSFileSystem, foo/bar)> shape=(10, 20) dtype=float32>
7878

src/zarr/abc/store.py

Lines changed: 11 additions & 6 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_dir(self, prefix: str = "") -> bool:
85+
async def empty_dir(self, prefix: str) -> bool:
8686
"""
8787
Check if the directory is empty.
8888
@@ -96,8 +96,9 @@ async def empty_dir(self, prefix: str = "") -> bool:
9696
bool
9797
True if the store is empty, False otherwise.
9898
"""
99-
100-
if prefix and not prefix.endswith("/"):
99+
if not self.supports_listing:
100+
raise NotImplementedError
101+
if prefix != "" and not prefix.endswith("/"):
101102
prefix += "/"
102103
async for _ in self.list_prefix(prefix):
103104
return False
@@ -109,8 +110,12 @@ async def clear(self) -> None:
109110
110111
Remove all keys and values from the store.
111112
"""
112-
async for key in self.list():
113-
await self.delete(key)
113+
if not self.supports_deletes:
114+
raise NotImplementedError
115+
if not self.supports_listing:
116+
raise NotImplementedError
117+
self._check_writable()
118+
await self.delete_dir("")
114119

115120
@property
116121
def read_only(self) -> bool:
@@ -319,7 +324,7 @@ async def delete_dir(self, prefix: str) -> None:
319324
if not self.supports_listing:
320325
raise NotImplementedError
321326
self._check_writable()
322-
if prefix and not prefix.endswith("/"):
327+
if prefix != "" and not prefix.endswith("/"):
323328
prefix += "/"
324329
async for key in self.list_prefix(prefix):
325330
await self.delete(key)

src/zarr/api/asynchronous.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@
7171

7272

7373
def _infer_exists_ok(mode: AccessModeLiteral) -> bool:
74+
"""
75+
Check that an ``AccessModeLiteral`` is compatible with overwriting an existing Zarr node.
76+
"""
7477
return mode in _OVERWRITE_MODES
7578

7679

@@ -410,13 +413,14 @@ async def save_array(
410413
arr = np.array(arr)
411414
shape = arr.shape
412415
chunks = getattr(arr, "chunks", None) # for array-likes with chunks attribute
416+
exists_ok = kwargs.pop("exists_ok", None) or _infer_exists_ok(mode)
413417
new = await AsyncArray.create(
414418
store_path,
415419
zarr_format=zarr_format,
416420
shape=shape,
417421
dtype=arr.dtype,
418422
chunks=chunks,
419-
exists_ok=kwargs.pop("exists_ok", None) or _infer_exists_ok(mode),
423+
exists_ok=exists_ok,
420424
**kwargs,
421425
)
422426
await new.setitem(slice(None), arr)
@@ -617,9 +621,10 @@ async def group(
617621
try:
618622
return await AsyncGroup.open(store=store_path, zarr_format=zarr_format)
619623
except (KeyError, FileNotFoundError):
624+
_zarr_format = zarr_format or _default_zarr_version()
620625
return await AsyncGroup.from_store(
621626
store=store_path,
622-
zarr_format=zarr_format or _default_zarr_version(),
627+
zarr_format=_zarr_format,
623628
exists_ok=overwrite,
624629
attributes=attributes,
625630
)
@@ -726,10 +731,12 @@ async def open_group(
726731
except (KeyError, FileNotFoundError):
727732
pass
728733
if mode in _CREATE_MODES:
734+
exists_ok = _infer_exists_ok(mode)
735+
_zarr_format = zarr_format or _default_zarr_version()
729736
return await AsyncGroup.from_store(
730737
store_path,
731-
zarr_format=zarr_format or _default_zarr_version(),
732-
exists_ok=_infer_exists_ok(mode),
738+
zarr_format=_zarr_format,
739+
exists_ok=exists_ok,
733740
attributes=attributes,
734741
)
735742
raise FileNotFoundError(f"Unable to find group: {store_path}")
@@ -904,7 +911,7 @@ async def create(
904911
dtype=dtype,
905912
compressor=compressor,
906913
fill_value=fill_value,
907-
exists_ok=overwrite, # TODO: name change
914+
exists_ok=overwrite,
908915
filters=filters,
909916
dimension_separator=dimension_separator,
910917
zarr_format=zarr_format,
@@ -1074,7 +1081,7 @@ async def open_array(
10741081
If using an fsspec URL to create the store, these will be passed to
10751082
the backend implementation. Ignored otherwise.
10761083
**kwargs
1077-
Any keyword arguments to pass to the ``create``.
1084+
Any keyword arguments to pass to ``create``.
10781085
10791086
Returns
10801087
-------
@@ -1091,10 +1098,12 @@ async def open_array(
10911098
return await AsyncArray.open(store_path, zarr_format=zarr_format)
10921099
except FileNotFoundError:
10931100
if not store_path.read_only:
1101+
exists_ok = _infer_exists_ok(mode)
1102+
_zarr_format = zarr_format or _default_zarr_version()
10941103
return await create(
10951104
store=store_path,
1096-
zarr_format=zarr_format or _default_zarr_version(),
1097-
overwrite=_infer_exists_ok(mode),
1105+
zarr_format=_zarr_format,
1106+
overwrite=exists_ok,
10981107
**kwargs,
10991108
)
11001109
raise

src/zarr/testing/store.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,11 +231,13 @@ async def test_delete_dir(self, store: S) -> None:
231231
assert not await store.exists("foo/c/0")
232232

233233
async def test_empty_dir(self, store: S) -> None:
234-
assert await store.empty_dir()
234+
assert await store.empty_dir("")
235235
await self.set(
236236
store, "foo/bar", self.buffer_cls.from_bytes(bytes("something", encoding="utf-8"))
237237
)
238-
assert not await store.empty_dir()
238+
assert not await store.empty_dir("")
239+
assert await store.empty_dir("fo")
240+
assert not await store.empty_dir("foo/")
239241
assert not await store.empty_dir("foo")
240242
assert await store.empty_dir("spam/")
241243

@@ -244,7 +246,7 @@ async def test_clear(self, store: S) -> None:
244246
store, "key", self.buffer_cls.from_bytes(bytes("something", encoding="utf-8"))
245247
)
246248
await store.clear()
247-
assert await store.empty_dir()
249+
assert await store.empty_dir("")
248250

249251
async def test_list(self, store: S) -> None:
250252
assert await _collect_aiterator(store.list()) == ()

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_dir()
46+
assert await store.empty_dir("")
4747
(store.root / "foo/bar").mkdir(parents=True)
48-
assert await store.empty_dir()
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")

tests/test_store/test_remote.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,4 @@ async def test_empty_nonexistent_path(self, store_kwargs) -> None:
213213
# regression test for https://github.com/zarr-developers/zarr-python/pull/2343
214214
store_kwargs["path"] += "/abc"
215215
store = await self.store_cls.open(**store_kwargs)
216-
assert await store.empty_dir()
216+
assert await store.empty_dir("")

0 commit comments

Comments
 (0)