Skip to content

Commit c62294e

Browse files
Accept dictionaries for store argument (zarr-developers#2164)
* Accept dictionaries for `store` * fixup doc build warnings * Only support dictionaries
1 parent 726fdfb commit c62294e

File tree

6 files changed

+38
-12
lines changed

6 files changed

+38
-12
lines changed

src/zarr/api/asynchronous.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -497,8 +497,18 @@ async def open_group(
497497
498498
Parameters
499499
----------
500-
store : Store or string, optional
500+
store : Store, string, or mapping, optional
501501
Store or path to directory in file system or name of zip file.
502+
503+
Strings are interpreted as paths on the local file system
504+
and used as the ``root`` argument to :class:`zarr.store.LocalStore`.
505+
506+
Dictionaries are used as the ``store_dict`` argument in
507+
:class:`zarr.store.MemoryStore``.
508+
509+
By default (``store=None``) a new :class:`zarr.store.MemoryStore`
510+
is created.
511+
502512
mode : {'r', 'r+', 'a', 'w', 'w-'}, optional
503513
Persistence mode: 'r' means read only (must exist); 'r+' means
504514
read/write (must exist); 'a' means read/write (create if doesn't

src/zarr/core/buffer/core.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,8 @@ def from_buffer(cls, buffer: Buffer) -> Self:
195195
-------
196196
A new buffer representing the content of the input buffer
197197
198-
Note
199-
----
198+
Notes
199+
-----
200200
Subclasses of `Buffer` must override this method to implement
201201
more optimal conversions that avoid copies where possible
202202
"""

src/zarr/core/buffer/cpu.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ def from_buffer(cls, buffer: core.Buffer) -> Self:
7373
-------
7474
A new buffer representing the content of the input buffer
7575
76-
Note
77-
----
76+
Notes
77+
-----
7878
Subclasses of `Buffer` must override this method to implement
7979
more optimal conversions that avoid copies where possible
8080
"""

src/zarr/core/buffer/gpu.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ class Buffer(core.Buffer):
3838
array-like instance can be copied/converted to a regular Numpy array
3939
(host memory).
4040
41-
Note
42-
----
41+
Notes
42+
-----
4343
This buffer is untyped, so all indexing and sizes are in bytes.
4444
4545
Parameters
@@ -123,8 +123,8 @@ class NDBuffer(core.NDBuffer):
123123
ndarray-like instance can be copied/converted to a regular Numpy array
124124
(host memory).
125125
126-
Note
127-
----
126+
Notes
127+
-----
128128
The two buffer classes Buffer and NDBuffer are very similar. In fact, Buffer
129129
is a special case of NDBuffer where dim=1, stride=1, and dtype="b". However,
130130
in order to use Python's type system to differentiate between the contiguous
@@ -193,8 +193,8 @@ def from_numpy_array(cls, array_like: npt.ArrayLike) -> Self:
193193
def as_numpy_array(self) -> npt.NDArray[Any]:
194194
"""Returns the buffer as a NumPy array (host memory).
195195
196-
Warning
197-
-------
196+
Warnings
197+
--------
198198
Might have to copy data, consider using `.as_ndarray_like()` instead.
199199
200200
Returns

src/zarr/store/common.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def __eq__(self, other: Any) -> bool:
7171
return False
7272

7373

74-
StoreLike = Store | StorePath | Path | str
74+
StoreLike = Store | StorePath | Path | str | dict[str, Buffer]
7575

7676

7777
async def make_store_path(
@@ -94,6 +94,10 @@ async def make_store_path(
9494
return StorePath(await LocalStore.open(root=store_like, mode=mode or "r"))
9595
elif isinstance(store_like, str):
9696
return StorePath(await LocalStore.open(root=Path(store_like), mode=mode or "r"))
97+
elif isinstance(store_like, dict):
98+
# We deliberate only consider dict[str, Buffer] here, and not arbitrary mutable mappings.
99+
# By only allowing dictionaries, which are in-memory, we know that MemoryStore appropriate.
100+
return StorePath(await MemoryStore.open(store_dict=store_like, mode=mode))
97101
raise TypeError
98102

99103

tests/v3/test_group.py

+12
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import numpy as np
66
import pytest
77

8+
import zarr.api.asynchronous
89
from zarr import Array, AsyncArray, AsyncGroup, Group
10+
from zarr.api.synchronous import open_group
911
from zarr.core.buffer import default_buffer_prototype
1012
from zarr.core.common import ZarrFormat
1113
from zarr.core.group import GroupMetadata
@@ -820,3 +822,13 @@ async def test_require_array(store: LocalStore | MemoryStore, zarr_format: ZarrF
820822
_ = await root.create_group("bar")
821823
with pytest.raises(TypeError, match="Incompatible object"):
822824
await root.require_array("bar", shape=(10,), dtype="int8")
825+
826+
827+
async def test_open_mutable_mapping():
828+
group = await zarr.api.asynchronous.open_group(store={}, mode="w")
829+
assert isinstance(group.store_path.store, MemoryStore)
830+
831+
832+
def test_open_mutable_mapping_sync():
833+
group = open_group(store={}, mode="w")
834+
assert isinstance(group.store_path.store, MemoryStore)

0 commit comments

Comments
 (0)