Skip to content

Commit 11cfc45

Browse files
committed
obstore implementations for .getsize and .getsize_prefix
1 parent bbdefac commit 11cfc45

File tree

2 files changed

+42
-20
lines changed

2 files changed

+42
-20
lines changed

src/zarr/storage/_obstore.py

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from zarr.core.config import config
1717

1818
if TYPE_CHECKING:
19-
from collections.abc import AsyncGenerator, Coroutine, Iterable
19+
from collections.abc import AsyncGenerator, Coroutine, Iterable, Sequence
2020
from typing import Any
2121

2222
from obstore import ListResult, ListStream, ObjectMeta, OffsetRange, SuffixRange
@@ -212,41 +212,48 @@ def supports_listing(self) -> bool:
212212
# docstring inherited
213213
return True
214214

215-
def list(self) -> AsyncGenerator[str, None]:
216-
# docstring inherited
215+
async def _list(self, prefix: str | None = None) -> AsyncGenerator[ObjectMeta, None]:
217216
import obstore as obs
218217

219-
objects: ListStream[list[ObjectMeta]] = obs.list(self.store)
220-
return _transform_list(objects)
218+
objects: ListStream[Sequence[ObjectMeta]] = obs.list(self.store, prefix=prefix)
219+
async for batch in objects:
220+
for item in batch:
221+
yield item
221222

222-
def list_prefix(self, prefix: str) -> AsyncGenerator[str, None]:
223+
# return (obj async for obj in _transform_list(objects))
224+
225+
def list(self) -> AsyncGenerator[str, None]:
223226
# docstring inherited
224-
import obstore as obs
227+
return (obj["path"] async for obj in self._list())
225228

226-
objects: ListStream[list[ObjectMeta]] = obs.list(self.store, prefix=prefix)
227-
return _transform_list(objects)
229+
def list_prefix(self, prefix: str) -> AsyncGenerator[str, None]:
230+
# docstring inherited
231+
return (obj["path"] async for obj in self._list(prefix))
228232

229233
def list_dir(self, prefix: str) -> AsyncGenerator[str, None]:
230234
# docstring inherited
231235
import obstore as obs
232236

233-
coroutine = obs.list_with_delimiter_async(self.store, prefix=prefix)
237+
coroutine: Coroutine[Any, Any, ListResult[Sequence[ObjectMeta]]] = (
238+
obs.list_with_delimiter_async(self.store, prefix=prefix)
239+
)
234240
return _transform_list_dir(coroutine, prefix)
235241

242+
async def getsize(self, key: str) -> int:
243+
# docstring inherited
244+
import obstore as obs
236245

237-
async def _transform_list(
238-
list_stream: ListStream[list[ObjectMeta]],
239-
) -> AsyncGenerator[str, None]:
240-
"""
241-
Transform the result of list into an async generator of paths.
242-
"""
243-
async for batch in list_stream:
244-
for item in batch:
245-
yield item["path"]
246+
resp = await obs.head_async(self.store, key)
247+
return resp["size"]
248+
249+
async def getsize_prefix(self, prefix: str) -> int:
250+
# docstring inherited
251+
sizes = [obj["size"] async for obj in self._list(prefix=prefix)]
252+
return sum(sizes)
246253

247254

248255
async def _transform_list_dir(
249-
list_result_coroutine: Coroutine[Any, Any, ListResult[list[ObjectMeta]]], prefix: str
256+
list_result_coroutine: Coroutine[Any, Any, ListResult[Sequence[ObjectMeta]]], prefix: str
250257
) -> AsyncGenerator[str, None]:
251258
"""
252259
Transform the result of list_with_delimiter into an async generator of paths.

tests/test_store/test_object.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,21 @@ def test_store_init_raises(self) -> None:
7575
with pytest.raises(TypeError):
7676
ObjectStore("path/to/store")
7777

78+
async def test_store_getsize(self, store: ObjectStore) -> None:
79+
buf = cpu.Buffer.from_bytes(b"\x01\x02\x03\x04")
80+
await self.set(store, "key", buf)
81+
size = await store.getsize("key")
82+
assert size == len(buf)
83+
84+
async def test_store_getsize_prefix(self, store: ObjectStore) -> None:
85+
buf = cpu.Buffer.from_bytes(b"\x01\x02\x03\x04")
86+
await self.set(store, "c/key1/0", buf)
87+
await self.set(store, "c/key2/0", buf)
88+
size = await store.getsize_prefix("c/key1")
89+
assert size == len(buf)
90+
total_size = await store.getsize_prefix("c")
91+
assert total_size == len(buf) * 2
92+
7893

7994
@pytest.mark.slow_hypothesis
8095
def test_zarr_hierarchy():

0 commit comments

Comments
 (0)