diff --git a/src/zarr/api/asynchronous.py b/src/zarr/api/asynchronous.py index f206d48377..0cde9103bf 100644 --- a/src/zarr/api/asynchronous.py +++ b/src/zarr/api/asynchronous.py @@ -673,13 +673,6 @@ async def group( zarr_format = _handle_zarr_version_or_format(zarr_version=zarr_version, zarr_format=zarr_format) - mode: AccessModeLiteral - if overwrite: - mode = "w" - else: - mode = "r+" - store_path = await make_store_path(store, path=path, mode=mode, storage_options=storage_options) - if chunk_store is not None: warnings.warn("chunk_store is not yet implemented", ZarrRuntimeWarning, stacklevel=2) if cache_attrs is not None: @@ -689,20 +682,7 @@ async def group( if meta_array is not None: warnings.warn("meta_array is not yet implemented", ZarrRuntimeWarning, stacklevel=2) - if attributes is None: - attributes = {} - - try: - return await AsyncGroup.open(store=store_path, zarr_format=zarr_format) - except (KeyError, FileNotFoundError): - _zarr_format = zarr_format or _default_zarr_format() - return await AsyncGroup.from_store( - store=store_path, - zarr_format=_zarr_format, - overwrite=overwrite, - attributes=attributes, - ) - + return await create_group(store=store, path=path, overwrite=overwrite, zarr_format=zarr_format, attributes=attributes, storage_options=storage_options) async def create_group( *, @@ -742,9 +722,7 @@ async def create_group( if zarr_format is None: zarr_format = _default_zarr_format() - mode: Literal["a"] = "a" - - store_path = await make_store_path(store, path=path, mode=mode, storage_options=storage_options) + store_path = await make_store_path(store, path=path, mode="a", storage_options=storage_options) return await AsyncGroup.from_store( store=store_path, diff --git a/tests/test_api/test_asynchronous.py b/tests/test_api/test_asynchronous.py index 910fd2883c..bd54c1b1d3 100644 --- a/tests/test_api/test_asynchronous.py +++ b/tests/test_api/test_asynchronous.py @@ -8,10 +8,12 @@ import pytest from zarr import create_array -from zarr.api.asynchronous import _get_shape_chunks, _like_args, open +from zarr.api.asynchronous import _get_shape_chunks, _like_args, group, open from zarr.core.buffer.core import default_buffer_prototype +from zarr.errors import ContainsGroupError if TYPE_CHECKING: + from pathlib import Path from typing import Any import numpy.typing as npt @@ -103,3 +105,27 @@ async def test_open_no_array() -> None: TypeError, match=r"open_group\(\) got an unexpected keyword argument 'shape'" ): await open(store=store, shape=(1,)) + + +async def test_open_group_new_path(tmp_path: Path) -> None: + """ + Test that zarr.api.asynchronous.group properly handles a string representation of a local file + path that does not yet exist. + + See https://github.com/zarr-developers/zarr-python/issues/3406 + """ + # tmp_path exists, but tmp_path / "test.zarr" will not, which is important for this test + store = tmp_path / "test.zarr" + await group(store=store) + + +async def test_open_group_old_path(tmp_path: Path) -> None: + """ + Test that zarr.api.asynchronous.group will not overwrite an existing file. + + See https://github.com/zarr-developers/zarr-python/issues/3406 + """ + store = tmp_path + await group(store=store, overwrite=True, attributes={"existing_group": True}) + with pytest.raises(ContainsGroupError): + await group(store=store) diff --git a/tests/test_group.py b/tests/test_group.py index 2d9070bd67..485412cce5 100644 --- a/tests/test_group.py +++ b/tests/test_group.py @@ -2159,7 +2159,7 @@ def test_group_members_performance(store: Store) -> None: latency_store = LatencyStore(store, get_latency=get_latency) # create a group with some latency on get operations - group_read = zarr.group(store=latency_store) + group_read = zarr.open_group(store=latency_store) # check how long it takes to iterate over the groups # if .members is sensitive to IO latency,