diff --git a/changes/3068.bugfix.rst b/changes/3068.bugfix.rst deleted file mode 100644 index 9ada322c13..0000000000 --- a/changes/3068.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Trying to open an array with ``mode='r'`` when the store is not read-only now raises an error. diff --git a/src/zarr/storage/_common.py b/src/zarr/storage/_common.py index f264728cf2..c351ec4702 100644 --- a/src/zarr/storage/_common.py +++ b/src/zarr/storage/_common.py @@ -3,7 +3,7 @@ import importlib.util import json from pathlib import Path -from typing import TYPE_CHECKING, Any, Literal, Self, TypeAlias +from typing import TYPE_CHECKING, Any, Literal, TypeAlias from zarr.abc.store import ByteRequest, Store from zarr.core.buffer import Buffer, default_buffer_prototype @@ -55,7 +55,9 @@ def read_only(self) -> bool: return self.store.read_only @classmethod - async def open(cls, store: Store, path: str, mode: AccessModeLiteral | None = None) -> Self: + async def open( + cls, store: Store, path: str, mode: AccessModeLiteral | None = None + ) -> StorePath: """ Open StorePath based on the provided mode. @@ -72,9 +74,6 @@ async def open(cls, store: Store, path: str, mode: AccessModeLiteral | None = No ------ FileExistsError If the mode is 'w-' and the store path already exists. - ValueError - If the mode is not "r" and the store is read-only, or - if the mode is "r" and the store is not read-only. """ await store._ensure_open() @@ -86,8 +85,6 @@ async def open(cls, store: Store, path: str, mode: AccessModeLiteral | None = No if store.read_only and mode != "r": raise ValueError(f"Store is read-only but mode is '{mode}'") - if not store.read_only and mode == "r": - raise ValueError(f"Store is not read-only but mode is '{mode}'") match mode: case "w-": diff --git a/tests/test_api.py b/tests/test_api.py index 2a95d7b97c..c75e85e7f6 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -171,7 +171,7 @@ def test_v2_and_v3_exist_at_same_path(store: Store) -> None: zarr.create_array(store, shape=(10,), dtype="uint8", zarr_format=2) msg = f"Both zarr.json (Zarr format 3) and .zarray (Zarr format 2) metadata objects exist at {store}. Zarr v3 will be used." with pytest.warns(UserWarning, match=re.escape(msg)): - zarr.open(store=store) + zarr.open(store=store, mode="r") @pytest.mark.parametrize("store", ["memory"], indirect=True) @@ -1318,7 +1318,7 @@ def test_no_overwrite_open(tmp_path: Path, open_func: Callable, mode: str) -> No existing_fpath = add_empty_file(tmp_path) assert existing_fpath.exists() - with contextlib.suppress(FileExistsError, FileNotFoundError, ValueError): + with contextlib.suppress(FileExistsError, FileNotFoundError): open_func(store=store, mode=mode) if mode == "w": assert not existing_fpath.exists() diff --git a/tests/test_array.py b/tests/test_array.py index 3fc7b3938c..3e8ef293ff 100644 --- a/tests/test_array.py +++ b/tests/test_array.py @@ -1479,7 +1479,7 @@ async def test_name(store: Store, zarr_format: ZarrFormat, path: str | None) -> for parent_path in parents: # this will raise if these groups were not created _ = await zarr.api.asynchronous.open_group( - store=store, path=parent_path, zarr_format=zarr_format + store=store, path=parent_path, mode="r", zarr_format=zarr_format ) @@ -1667,7 +1667,7 @@ def test_roundtrip_numcodecs() -> None: BYTES_CODEC = {"name": "bytes", "configuration": {"endian": "little"}} # Read in the array again and check compressor config - root = zarr.open_group(store) + root = zarr.open_group(store, mode="r") metadata = root["test"].metadata.to_dict() expected = (*filters, BYTES_CODEC, *compressors) assert metadata["codecs"] == expected diff --git a/tests/test_store/test_core.py b/tests/test_store/test_core.py index e9c9319ad3..2677a83241 100644 --- a/tests/test_store/test_core.py +++ b/tests/test_store/test_core.py @@ -4,7 +4,6 @@ import pytest from _pytest.compat import LEGACY_PATH -import zarr from zarr import Group from zarr.core.common import AccessModeLiteral, ZarrFormat from zarr.storage import FsspecStore, LocalStore, MemoryStore, StoreLike, StorePath @@ -261,10 +260,3 @@ def test_relativize_path_invalid() -> None: msg = f"The first component of {path} does not start with {prefix}." with pytest.raises(ValueError, match=msg): _relativize_path(path="a/b/c", prefix="b") - - -def test_invalid_open_mode() -> None: - store = MemoryStore() - zarr.create((100,), store=store, zarr_format=2, path="a") - with pytest.raises(ValueError, match="Store is not read-only but mode is 'r'"): - zarr.open_array(store=store, path="a", zarr_format=2, mode="r")