Skip to content

Commit 89dbb6e

Browse files
author
antoinegaston
committed
🐛 Fix obstore listdir method using _relativize_path
1 parent 4cddcf5 commit 89dbb6e

2 files changed

Lines changed: 32 additions & 16 deletions

File tree

src/zarr/storage/_obstore.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import contextlib
55
import pickle
66
from collections import defaultdict
7+
from itertools import chain
8+
from operator import itemgetter
79
from typing import TYPE_CHECKING, Generic, Self, TypedDict, TypeVar
810

911
from zarr.abc.store import (
@@ -15,6 +17,7 @@
1517
)
1618
from zarr.core.common import concurrent_map
1719
from zarr.core.config import config
20+
from zarr.storage._utils import _relativize_path
1821

1922
if TYPE_CHECKING:
2023
from collections.abc import AsyncGenerator, Coroutine, Iterable, Sequence
@@ -263,10 +266,11 @@ async def _transform_list_dir(
263266
# We assume that the underlying object-store implementation correctly handles the
264267
# prefix, so we don't double-check that the returned results actually start with the
265268
# given prefix.
266-
prefixes = [obj.lstrip(prefix).lstrip("/") for obj in list_result["common_prefixes"]]
267-
objects = [obj["path"].removeprefix(prefix).lstrip("/") for obj in list_result["objects"]]
268-
for item in prefixes + objects:
269-
yield item
269+
prefix = prefix.rstrip("/")
270+
for path in chain(
271+
list_result["common_prefixes"], map(itemgetter("path"), list_result["objects"])
272+
):
273+
yield _relativize_path(path=path, prefix=prefix)
270274

271275

272276
class _BoundedRequest(TypedDict):

src/zarr/testing/store.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -491,24 +491,36 @@ async def test_list_empty_path(self, store: S) -> None:
491491
assert observed_prefix_sorted == expected_prefix_sorted
492492

493493
async def test_list_dir(self, store: S) -> None:
494-
root = "foo"
495-
store_dict = {
496-
root + "/zarr.json": self.buffer_cls.from_bytes(b"bar"),
497-
root + "/c/1": self.buffer_cls.from_bytes(b"\x01"),
498-
}
494+
roots_and_keys: list[tuple[str, dict[str, Buffer]]] = [
495+
(
496+
"foo",
497+
{
498+
"foo/zarr.json": self.buffer_cls.from_bytes(b"bar"),
499+
"foo/c/1": self.buffer_cls.from_bytes(b"\x01"),
500+
},
501+
),
502+
(
503+
"foo/bar",
504+
{
505+
"foo/bar/foobar_first_child": self.buffer_cls.from_bytes(b"1"),
506+
"foo/bar/foobar_second_child/zarr.json": self.buffer_cls.from_bytes(b"2"),
507+
},
508+
),
509+
]
499510

500511
assert await _collect_aiterator(store.list_dir("")) == ()
501-
assert await _collect_aiterator(store.list_dir(root)) == ()
502512

503-
await store._set_many(store_dict.items())
513+
for root, store_dict in roots_and_keys:
514+
assert await _collect_aiterator(store.list_dir(root)) == ()
504515

505-
keys_observed = await _collect_aiterator(store.list_dir(root))
506-
keys_expected = {k.removeprefix(root + "/").split("/")[0] for k in store_dict}
516+
await store._set_many(store_dict.items())
507517

508-
assert sorted(keys_observed) == sorted(keys_expected)
518+
keys_observed = await _collect_aiterator(store.list_dir(root))
519+
keys_expected = {k.removeprefix(root + "/").split("/")[0] for k in store_dict}
520+
assert sorted(keys_observed) == sorted(keys_expected)
509521

510-
keys_observed = await _collect_aiterator(store.list_dir(root + "/"))
511-
assert sorted(keys_expected) == sorted(keys_observed)
522+
keys_observed = await _collect_aiterator(store.list_dir(root + "/"))
523+
assert sorted(keys_expected) == sorted(keys_observed)
512524

513525
async def test_set_if_not_exists(self, store: S) -> None:
514526
key = "k"

0 commit comments

Comments
 (0)