Skip to content

Commit 8d3ead3

Browse files
AsyncGenerator → AsyncIterator
Refactor Store list methods.
1 parent 0dc2bc1 commit 8d3ead3

File tree

7 files changed

+66
-79
lines changed

7 files changed

+66
-79
lines changed

docs/roadmap.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,13 @@ expose the required methods as async methods.
234234
async def set_partial_values(self, key_start_values: List[Tuple[str, int, Union[bytes, bytearray, memoryview]]]) -> None:
235235
... # required for writable stores
236236
237-
async def list(self) -> List[str]:
237+
async def list(self) -> AsyncIterator[str]:
238238
... # required for listable stores
239239
240-
async def list_prefix(self, prefix: str) -> List[str]:
240+
async def list_prefix(self, prefix: str) -> AsyncIterator[str]:
241241
... # required for listable stores
242242
243-
async def list_dir(self, prefix: str) -> List[str]:
243+
async def list_dir(self, prefix: str) -> AsyncIterator[str]:
244244
... # required for listable stores
245245
246246
# additional (optional methods)

src/zarr/abc/store.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from typing import TYPE_CHECKING, NamedTuple, Protocol, runtime_checkable
66

77
if TYPE_CHECKING:
8-
from collections.abc import AsyncGenerator, Iterable
8+
from collections.abc import AsyncGenerator, AsyncIterator, Iterable
99
from types import TracebackType
1010
from typing import Any, Self, TypeAlias
1111

@@ -329,17 +329,17 @@ def supports_listing(self) -> bool:
329329
...
330330

331331
@abstractmethod
332-
async def list(self) -> AsyncGenerator[str]:
332+
async def list(self) -> AsyncIterator[str]:
333333
"""Retrieve all keys in the store.
334334
335335
Returns
336336
-------
337-
AsyncGenerator[str, None]
337+
AsyncIterator[str, None]
338338
"""
339-
yield ""
339+
return iter([])
340340

341341
@abstractmethod
342-
async def list_prefix(self, prefix: str) -> AsyncGenerator[str]:
342+
async def list_prefix(self, prefix: str) -> AsyncIterator[str]:
343343
"""
344344
Retrieve all keys in the store that begin with a given prefix. Keys are returned with the
345345
common leading prefix removed.
@@ -350,12 +350,12 @@ async def list_prefix(self, prefix: str) -> AsyncGenerator[str]:
350350
351351
Returns
352352
-------
353-
AsyncGenerator[str, None]
353+
AsyncIterator[str, None]
354354
"""
355-
yield ""
355+
return iter([])
356356

357357
@abstractmethod
358-
async def list_dir(self, prefix: str) -> AsyncGenerator[str]:
358+
async def list_dir(self, prefix: str) -> AsyncIterator[str]:
359359
"""
360360
Retrieve all keys and prefixes with a given prefix and which do not contain the character
361361
“/” after the given prefix.
@@ -366,9 +366,9 @@ async def list_dir(self, prefix: str) -> AsyncGenerator[str]:
366366
367367
Returns
368368
-------
369-
AsyncGenerator[str, None]
369+
AsyncIterator[str, None]
370370
"""
371-
yield ""
371+
return iter([])
372372

373373
def close(self) -> None:
374374
"""Close the store."""

src/zarr/storage/local.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from zarr.core.common import concurrent_map
1313

1414
if TYPE_CHECKING:
15-
from collections.abc import AsyncGenerator, Iterable
15+
from collections.abc import AsyncIterator, Iterable
1616

1717
from zarr.core.buffer import BufferPrototype
1818
from zarr.core.common import AccessModeLiteral
@@ -217,28 +217,26 @@ async def exists(self, key: str) -> bool:
217217
path = self.root / key
218218
return await asyncio.to_thread(path.is_file)
219219

220-
async def list(self) -> AsyncGenerator[str]:
220+
async def list(self) -> AsyncIterator[str]:
221221
# docstring inherited
222222
to_strip = str(self.root) + "/"
223-
for p in list(self.root.rglob("*")):
224-
if p.is_file():
225-
yield str(p).replace(to_strip, "")
223+
allfiles = [str(p).replace(to_strip, "") for p in self.root.rglob("*") if p.is_file()]
224+
return (onefile for onefile in allfiles)
226225

227-
async def list_prefix(self, prefix: str) -> AsyncGenerator[str]:
226+
async def list_prefix(self, prefix: str) -> AsyncIterator[str]:
228227
# docstring inherited
229228
to_strip = os.path.join(str(self.root / prefix))
230-
for p in (self.root / prefix).rglob("*"):
231-
if p.is_file():
232-
yield str(p.relative_to(to_strip))
229+
allfiles = [
230+
str(p.relative_to(to_strip)) for p in (self.root / prefix).rglob("*") if p.is_file()
231+
]
232+
return (onefile for onefile in allfiles)
233233

234-
async def list_dir(self, prefix: str) -> AsyncGenerator[str]:
234+
async def list_dir(self, prefix: str) -> AsyncIterator[str]:
235235
# docstring inherited
236236
base = self.root / prefix
237237
to_strip = str(base) + "/"
238-
239238
try:
240-
key_iter = base.iterdir()
241-
for key in key_iter:
242-
yield str(key).replace(to_strip, "")
239+
allfiles = [str(key).replace(to_strip, "") for key in base.iterdir()]
240+
return (onefile for onefile in allfiles)
243241
except (FileNotFoundError, NotADirectoryError):
244-
pass
242+
return iter([])

src/zarr/storage/logging.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from zarr.abc.store import AccessMode, ByteRangeRequest, Store
1111

1212
if TYPE_CHECKING:
13-
from collections.abc import AsyncGenerator, Generator, Iterable
13+
from collections.abc import AsyncIterator, Generator, Iterable
1414

1515
from zarr.core.buffer import Buffer, BufferPrototype
1616
from zarr.core.common import AccessModeLiteral
@@ -204,23 +204,20 @@ async def set_partial_values(
204204
with self.log(keys):
205205
return await self._store.set_partial_values(key_start_values=key_start_values)
206206

207-
async def list(self) -> AsyncGenerator[str]:
207+
async def list(self) -> AsyncIterator[str]:
208208
# docstring inherited
209209
with self.log():
210-
async for key in self._store.list():
211-
yield key
210+
return (key async for key in self._store.list())
212211

213-
async def list_prefix(self, prefix: str) -> AsyncGenerator[str]:
212+
async def list_prefix(self, prefix: str) -> AsyncIterator[str]:
214213
# docstring inherited
215214
with self.log(prefix):
216-
async for key in self._store.list_prefix(prefix=prefix):
217-
yield key
215+
return (key async for key in self._store.list_prefix(prefix=prefix))
218216

219-
async def list_dir(self, prefix: str) -> AsyncGenerator[str]:
217+
async def list_dir(self, prefix: str) -> AsyncIterator[str]:
220218
# docstring inherited
221219
with self.log(prefix):
222-
async for key in self._store.list_dir(prefix=prefix):
223-
yield key
220+
return (key async for key in self._store.list_dir(prefix=prefix))
224221

225222
def with_mode(self, mode: AccessModeLiteral) -> Self:
226223
# docstring inherited

src/zarr/storage/memory.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from zarr.storage._utils import _normalize_interval_index
99

1010
if TYPE_CHECKING:
11-
from collections.abc import AsyncGenerator, Iterable, MutableMapping
11+
from collections.abc import AsyncIterator, Iterable, MutableMapping
1212

1313
from zarr.core.buffer import BufferPrototype
1414
from zarr.core.common import AccessModeLiteral
@@ -143,18 +143,15 @@ async def set_partial_values(self, key_start_values: Iterable[tuple[str, int, by
143143
# docstring inherited
144144
raise NotImplementedError
145145

146-
async def list(self) -> AsyncGenerator[str]:
146+
async def list(self) -> AsyncIterator[str]:
147147
# docstring inherited
148-
for key in self._store_dict:
149-
yield key
148+
return (key for key in self._store_dict)
150149

151-
async def list_prefix(self, prefix: str) -> AsyncGenerator[str]:
150+
async def list_prefix(self, prefix: str) -> AsyncIterator[str]:
152151
# docstring inherited
153-
for key in self._store_dict:
154-
if key.startswith(prefix):
155-
yield key.removeprefix(prefix)
152+
return (key.removeprefix(prefix) for key in self._store_dict if key.startswith(prefix))
156153

157-
async def list_dir(self, prefix: str) -> AsyncGenerator[str]:
154+
async def list_dir(self, prefix: str) -> AsyncIterator[str]:
158155
# docstring inherited
159156
if prefix.endswith("/"):
160157
prefix = prefix[:-1]
@@ -171,8 +168,7 @@ async def list_dir(self, prefix: str) -> AsyncGenerator[str]:
171168
if key.startswith(prefix + "/") and key != prefix
172169
}
173170

174-
for key in keys_unique:
175-
yield key
171+
return (key for key in keys_unique)
176172

177173

178174
class GpuMemoryStore(MemoryStore):

src/zarr/storage/remote.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from zarr.storage.common import _dereference_path
99

1010
if TYPE_CHECKING:
11-
from collections.abc import AsyncGenerator, Iterable
11+
from collections.abc import AsyncIterator, Iterable
1212

1313
from fsspec.asyn import AsyncFileSystem
1414

@@ -280,24 +280,25 @@ async def set_partial_values(
280280
# docstring inherited
281281
raise NotImplementedError
282282

283-
async def list(self) -> AsyncGenerator[str]:
283+
async def list(self) -> AsyncIterator[str]:
284284
# docstring inherited
285285
allfiles = await self.fs._find(self.path, detail=False, withdirs=False)
286-
for onefile in (a.replace(self.path + "/", "") for a in allfiles):
287-
yield onefile
286+
return (onefile for onefile in (a.replace(self.path + "/", "") for a in allfiles))
288287

289-
async def list_dir(self, prefix: str) -> AsyncGenerator[str]:
288+
async def list_dir(self, prefix: str) -> AsyncIterator[str]:
290289
# docstring inherited
291290
prefix = f"{self.path}/{prefix.rstrip('/')}"
292291
try:
293292
allfiles = await self.fs._ls(prefix, detail=False)
294293
except FileNotFoundError:
295-
return
296-
for onefile in (a.replace(prefix + "/", "") for a in allfiles):
297-
yield onefile.removeprefix(self.path).removeprefix("/")
294+
return iter([])
295+
return (
296+
onefile.removeprefix(self.path).removeprefix("/")
297+
for onefile in (a.replace(prefix + "/", "") for a in allfiles)
298+
)
298299

299-
async def list_prefix(self, prefix: str) -> AsyncGenerator[str]:
300+
async def list_prefix(self, prefix: str) -> AsyncIterator[str]:
300301
# docstring inherited
301302
find_str = f"{self.path}/{prefix}"
302-
for onefile in await self.fs._find(find_str, detail=False, maxdepth=None, withdirs=False):
303-
yield onefile.removeprefix(find_str)
303+
allfiles = await self.fs._find(find_str, detail=False, maxdepth=None, withdirs=False)
304+
return (onefile.removeprefix(find_str) for onefile in allfiles)

src/zarr/storage/zip.py

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from zarr.core.buffer import Buffer, BufferPrototype
1212

1313
if TYPE_CHECKING:
14-
from collections.abc import AsyncGenerator, Iterable
14+
from collections.abc import AsyncIterator, Iterable
1515

1616
ZipStoreAccessModeLiteral = Literal["r", "w", "a"]
1717

@@ -231,19 +231,16 @@ async def exists(self, key: str) -> bool:
231231
else:
232232
return True
233233

234-
async def list(self) -> AsyncGenerator[str]:
234+
async def list(self) -> AsyncIterator[str]:
235235
# docstring inherited
236236
with self._lock:
237-
for key in self._zf.namelist():
238-
yield key
237+
return (key for key in self._zf.namelist())
239238

240-
async def list_prefix(self, prefix: str) -> AsyncGenerator[str]:
239+
async def list_prefix(self, prefix: str) -> AsyncIterator[str]:
241240
# docstring inherited
242-
async for key in self.list():
243-
if key.startswith(prefix):
244-
yield key.removeprefix(prefix)
241+
return (key.removeprefix(prefix) async for key in self.list() if key.startswith(prefix))
245242

246-
async def list_dir(self, prefix: str) -> AsyncGenerator[str]:
243+
async def list_dir(self, prefix: str) -> AsyncIterator[str]:
247244
# docstring inherited
248245
if prefix.endswith("/"):
249246
prefix = prefix[:-1]
@@ -252,14 +249,12 @@ async def list_dir(self, prefix: str) -> AsyncGenerator[str]:
252249
seen = set()
253250
if prefix == "":
254251
keys_unique = {k.split("/")[0] for k in keys}
255-
for key in keys_unique:
256-
if key not in seen:
257-
seen.add(key)
258-
yield key
252+
return (key for key in keys_unique if key not in seen and not seen.add(key))
259253
else:
260-
for key in keys:
261-
if key.startswith(prefix + "/") and key != prefix:
262-
k = key.removeprefix(prefix + "/").split("/")[0]
263-
if k not in seen:
264-
seen.add(k)
265-
yield k
254+
return (
255+
k
256+
for key in keys
257+
if key.startswith(prefix + "/") and key != prefix
258+
for k in [key.removeprefix(prefix + "/").split("/")[0]]
259+
if k not in seen and not seen.add(k)
260+
)

0 commit comments

Comments
 (0)