Skip to content

Commit 6547b7f

Browse files
authored
Refactor make_store_path for clarity (#3308)
1 parent e410173 commit 6547b7f

File tree

2 files changed

+57
-46
lines changed

2 files changed

+57
-46
lines changed

src/zarr/storage/_common.py

Lines changed: 55 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -323,54 +323,65 @@ async def make_store_path(
323323
"""
324324
from zarr.storage._fsspec import FsspecStore # circular import
325325

326-
used_storage_options = False
327326
path_normalized = normalize_path(path)
328-
if isinstance(store_like, StorePath):
329-
result = store_like / path_normalized
330-
else:
331-
assert mode in (None, "r", "r+", "a", "w", "w-")
332-
# if mode 'r' was provided, we'll open any new stores as read-only
333-
_read_only = mode == "r"
334-
if isinstance(store_like, Store):
335-
store = store_like
336-
elif store_like is None:
337-
store = await MemoryStore.open(read_only=_read_only)
338-
elif isinstance(store_like, Path):
339-
store = await LocalStore.open(root=store_like, read_only=_read_only)
340-
elif isinstance(store_like, str):
341-
storage_options = storage_options or {}
342-
343-
if _is_fsspec_uri(store_like):
344-
used_storage_options = True
345-
store = FsspecStore.from_url(
346-
store_like, storage_options=storage_options, read_only=_read_only
347-
)
348-
else:
349-
store = await LocalStore.open(root=Path(store_like), read_only=_read_only)
350-
elif isinstance(store_like, dict):
351-
# We deliberate only consider dict[str, Buffer] here, and not arbitrary mutable mappings.
352-
# By only allowing dictionaries, which are in-memory, we know that MemoryStore appropriate.
353-
store = await MemoryStore.open(store_dict=store_like, read_only=_read_only)
354-
elif _has_fsspec and isinstance(store_like, FSMap):
355-
if path:
356-
raise ValueError(
357-
"'path' was provided but is not used for FSMap store_like objects. Specify the path when creating the FSMap instance instead."
358-
)
359-
if storage_options:
360-
raise ValueError(
361-
"'storage_options was provided but is not used for FSMap store_like objects. Specify the storage options when creating the FSMap instance instead."
362-
)
363-
store = FsspecStore.from_mapper(store_like, read_only=_read_only)
364-
else:
365-
raise TypeError(f"Unsupported type for store_like: '{type(store_like).__name__}'")
366327

367-
result = await StorePath.open(store, path=path_normalized, mode=mode)
328+
if (
329+
not (isinstance(store_like, str) and _is_fsspec_uri(store_like))
330+
and storage_options is not None
331+
):
332+
raise TypeError(
333+
"'storage_options' was provided but unused. "
334+
"'storage_options' is only used when the store is passed as a FSSpec URI string.",
335+
)
368336

369-
if storage_options and not used_storage_options:
370-
msg = "'storage_options' was provided but unused. 'storage_options' is only used for fsspec filesystem stores."
371-
raise TypeError(msg)
337+
assert mode in (None, "r", "r+", "a", "w", "w-")
338+
_read_only = mode == "r"
372339

373-
return result
340+
if isinstance(store_like, StorePath):
341+
# Already a StorePath
342+
return store_like / path_normalized
343+
344+
elif isinstance(store_like, Store):
345+
# Already a Store
346+
store = store_like
347+
348+
elif isinstance(store_like, dict):
349+
# Already a dictionary that can be a MemoryStore
350+
#
351+
# We deliberate only consider dict[str, Buffer] here, and not arbitrary mutable mappings.
352+
# By only allowing dictionaries, which are in-memory, we know that MemoryStore appropriate.
353+
store = await MemoryStore.open(store_dict=store_like, read_only=_read_only)
354+
355+
elif store_like is None:
356+
# Create a new in-memory store
357+
return await make_store_path({}, path=path, mode=mode, storage_options=storage_options)
358+
359+
elif isinstance(store_like, Path):
360+
# Create a new LocalStore
361+
store = await LocalStore.open(root=store_like, read_only=_read_only)
362+
363+
elif isinstance(store_like, str):
364+
# Either a FSSpec URI or a local filesystem path
365+
if _is_fsspec_uri(store_like):
366+
store = FsspecStore.from_url(
367+
store_like, storage_options=storage_options, read_only=_read_only
368+
)
369+
else:
370+
# Assume a filesystem path
371+
return await make_store_path(
372+
Path(store_like), path=path, mode=mode, storage_options=storage_options
373+
)
374+
375+
elif _has_fsspec and isinstance(store_like, FSMap):
376+
if path:
377+
raise ValueError(
378+
"'path' was provided but is not used for FSMap store_like objects. Specify the path when creating the FSMap instance instead."
379+
)
380+
store = FsspecStore.from_mapper(store_like, read_only=_read_only)
381+
else:
382+
raise TypeError(f"Unsupported type for store_like: '{type(store_like).__name__}'")
383+
384+
return await StorePath.open(store, path=path_normalized, mode=mode)
374385

375386

376387
def _is_fsspec_uri(uri: str) -> bool:

tests/test_store/test_fsspec.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,8 @@ def test_open_s3map_raises() -> None:
388388
):
389389
zarr.open(store=mapper, path="bar", mode="w", shape=(3, 3))
390390
with pytest.raises(
391-
ValueError,
392-
match="'storage_options was provided but is not used for FSMap store_like objects",
391+
TypeError,
392+
match="'storage_options' is only used when the store is passed as a FSSpec URI string.",
393393
):
394394
zarr.open(store=mapper, storage_options={"anon": True}, mode="w", shape=(3, 3))
395395

0 commit comments

Comments
 (0)