Skip to content

Commit efeb440

Browse files
committed
Allow mode casting
1 parent fafd0bf commit efeb440

File tree

7 files changed

+43
-2
lines changed

7 files changed

+43
-2
lines changed

src/zarr/abc/store.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ async def empty(self) -> bool: ...
8181
@abstractmethod
8282
async def clear(self) -> None: ...
8383

84+
@abstractmethod
85+
def with_mode(self, mode: AccessModeLiteral) -> Self:
86+
"""
87+
Return a new store pointing to the same location with a new mode.
88+
"""
89+
...
90+
8491
@property
8592
def mode(self) -> AccessMode:
8693
"""Access mode of the store."""

src/zarr/store/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ async def make_store_path(
9090
result = store_like
9191
elif isinstance(store_like, Store):
9292
if mode is not None:
93-
assert AccessMode.from_literal(mode) == store_like.mode
93+
store_like = store_like.with_mode(mode)
9494
await store_like._ensure_open()
9595
result = StorePath(store_like)
9696
elif store_like is None:

src/zarr/store/local.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from pathlib import Path
77
from typing import TYPE_CHECKING
88

9+
from typing_extensions import Self
10+
911
from zarr.abc.store import Store
1012
from zarr.core.buffer import Buffer
1113
from zarr.core.common import concurrent_map, to_thread
@@ -103,6 +105,9 @@ async def empty(self) -> bool:
103105
else:
104106
return True
105107

108+
def with_mode(self, mode: AccessModeLiteral) -> Self:
109+
return type(self)(root=self.root, mode=mode)
110+
106111
def __str__(self) -> str:
107112
return f"file://{self.root}"
108113

src/zarr/store/memory.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from collections.abc import AsyncGenerator, MutableMapping
44
from typing import TYPE_CHECKING
55

6+
from typing_extensions import Self
7+
68
from zarr.abc.store import Store
79
from zarr.core.buffer import Buffer, gpu
810
from zarr.core.common import concurrent_map
@@ -42,6 +44,9 @@ async def empty(self) -> bool:
4244
async def clear(self) -> None:
4345
self._store_dict.clear()
4446

47+
def with_mode(self, mode: AccessModeLiteral) -> Self:
48+
return type(self)(store_dict=self._store_dict, mode=mode)
49+
4550
def __str__(self) -> str:
4651
return f"memory://{id(self._store_dict)}"
4752

src/zarr/store/remote.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from typing import TYPE_CHECKING, Any
44

55
import fsspec
6+
from typing_extensions import Self
67

78
from zarr.abc.store import Store
89
from zarr.store.common import _dereference_path
@@ -95,6 +96,14 @@ async def clear(self) -> None:
9596
async def empty(self) -> bool:
9697
return not await self.fs._find(self.path, withdirs=True)
9798

99+
def with_mode(self, mode: AccessModeLiteral) -> Self:
100+
return type(self)(
101+
fs=self.fs,
102+
mode=mode,
103+
path=self.path,
104+
allowed_exceptions=self.allowed_exceptions,
105+
)
106+
98107
def __repr__(self) -> str:
99108
return f"<RemoteStore({type(self.fs).__name__}, {self.path})>"
100109

src/zarr/store/zip.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
from pathlib import Path
88
from typing import TYPE_CHECKING, Any, Literal
99

10+
from typing_extensions import Self
11+
1012
from zarr.abc.store import Store
1113
from zarr.core.buffer import Buffer, BufferPrototype
1214

@@ -115,6 +117,11 @@ async def empty(self) -> bool:
115117
else:
116118
return True
117119

120+
def with_mode(self, mode: ZipStoreAccessModeLiteral) -> Self: # type: ignore[override]
121+
return type(self)(
122+
path=self.path, mode=mode, compression=self.compression, allowZip64=self.allowZip64
123+
)
124+
118125
def __str__(self) -> str:
119126
return f"zip://{self.path}"
120127

src/zarr/testing/store.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import pickle
2-
from typing import Any, Generic, TypeVar
2+
from typing import Any, Generic, TypeVar, cast
33

44
import pytest
55

66
from zarr.abc.store import AccessMode, Store
77
from zarr.core.buffer import Buffer, default_buffer_prototype
8+
from zarr.core.common import AccessModeLiteral
89
from zarr.core.sync import _collect_aiterator
910
from zarr.store._utils import _normalize_interval_index
1011
from zarr.testing.utils import assert_bytes_equal
@@ -251,3 +252,10 @@ async def test_list_dir(self, store: S) -> None:
251252

252253
keys_observed = await _collect_aiterator(store.list_dir(root + "/"))
253254
assert sorted(keys_expected) == sorted(keys_observed)
255+
256+
async def test_with_mode(self, store: S) -> None:
257+
for mode in ["r", "w"]:
258+
mode = cast(AccessModeLiteral, mode)
259+
result = store.with_mode(mode)
260+
assert result.mode == AccessMode.from_literal(mode)
261+
assert isinstance(result, type(store))

0 commit comments

Comments
 (0)