Skip to content

Commit 9ab9fee

Browse files
authored
Merge branch 'main' into catch-warnings
2 parents b2d02a2 + 40da497 commit 9ab9fee

File tree

4 files changed

+42
-1
lines changed

4 files changed

+42
-1
lines changed

.github/labeler.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- needs release notes:
1+
needs release notes:
22
- all:
33
- changed-files:
44
- any-glob-to-any-file: 'changes/*.rst'

changes/2533.bigfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Wrap sync fsspec filesystems with AsyncFileSystemWrapper in xarray.to_zarr

src/zarr/storage/_fsspec.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,17 @@ def from_url(
172172
opts = {"asynchronous": True, **opts}
173173

174174
fs, path = url_to_fs(url, **opts)
175+
if not fs.async_impl:
176+
try:
177+
from fsspec.implementations.asyn_wrapper import AsyncFileSystemWrapper
178+
179+
fs = AsyncFileSystemWrapper(fs)
180+
except ImportError as e:
181+
raise ImportError(
182+
f"The filesystem for URL '{url}' is synchronous, and the required "
183+
"AsyncFileSystemWrapper is not available. Upgrade fsspec to version "
184+
"2024.12.0 or later to enable this functionality."
185+
) from e
175186

176187
# fsspec is not consistent about removing the scheme from the path, so check and strip it here
177188
# https://github.com/fsspec/filesystem_spec/issues/1722

tests/test_store/test_fsspec.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import pytest
99
from botocore.session import Session
10+
from packaging.version import parse as parse_version
1011

1112
import zarr.api.asynchronous
1213
from zarr.abc.store import OffsetByteRequest
@@ -227,3 +228,31 @@ async def test_empty_nonexistent_path(self, store_kwargs) -> None:
227228
store_kwargs["path"] += "/abc"
228229
store = await self.store_cls.open(**store_kwargs)
229230
assert await store.is_empty("")
231+
232+
233+
@pytest.mark.skipif(
234+
parse_version(fsspec.__version__) < parse_version("2024.12.0"),
235+
reason="No AsyncFileSystemWrapper",
236+
)
237+
def test_wrap_sync_filesystem():
238+
"""The local fs is not async so we should expect it to be wrapped automatically"""
239+
from fsspec.implementations.asyn_wrapper import AsyncFileSystemWrapper
240+
241+
store = FsspecStore.from_url("local://test/path")
242+
243+
assert isinstance(store.fs, AsyncFileSystemWrapper)
244+
assert store.fs.async_impl
245+
246+
247+
@pytest.mark.skipif(
248+
parse_version(fsspec.__version__) < parse_version("2024.12.0"),
249+
reason="No AsyncFileSystemWrapper",
250+
)
251+
def test_no_wrap_async_filesystem():
252+
"""An async fs should not be wrapped automatically; fsspec's https filesystem is such an fs"""
253+
from fsspec.implementations.asyn_wrapper import AsyncFileSystemWrapper
254+
255+
store = FsspecStore.from_url("https://test/path")
256+
257+
assert not isinstance(store.fs, AsyncFileSystemWrapper)
258+
assert store.fs.async_impl

0 commit comments

Comments
 (0)