Skip to content

Commit 0c154c3

Browse files
Wrap sync fs for xarray.to_zarr (#2533)
Co-authored-by: Martin Durant <[email protected]>
1 parent 2be9f36 commit 0c154c3

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

Diff for: changes/2533.bigfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Wrap sync fsspec filesystems with AsyncFileSystemWrapper in xarray.to_zarr

Diff for: src/zarr/storage/_fsspec.py

+11
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

Diff for: tests/test_store/test_fsspec.py

+29
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import pytest
88
from botocore.session import Session
9+
from packaging.version import parse as parse_version
910

1011
import zarr.api.asynchronous
1112
from zarr.abc.store import OffsetByteRequest
@@ -215,3 +216,31 @@ async def test_empty_nonexistent_path(self, store_kwargs) -> None:
215216
store_kwargs["path"] += "/abc"
216217
store = await self.store_cls.open(**store_kwargs)
217218
assert await store.is_empty("")
219+
220+
221+
@pytest.mark.skipif(
222+
parse_version(fsspec.__version__) < parse_version("2024.12.0"),
223+
reason="No AsyncFileSystemWrapper",
224+
)
225+
def test_wrap_sync_filesystem():
226+
"""The local fs is not async so we should expect it to be wrapped automatically"""
227+
from fsspec.implementations.asyn_wrapper import AsyncFileSystemWrapper
228+
229+
store = FsspecStore.from_url("local://test/path")
230+
231+
assert isinstance(store.fs, AsyncFileSystemWrapper)
232+
assert store.fs.async_impl
233+
234+
235+
@pytest.mark.skipif(
236+
parse_version(fsspec.__version__) < parse_version("2024.12.0"),
237+
reason="No AsyncFileSystemWrapper",
238+
)
239+
def test_no_wrap_async_filesystem():
240+
"""An async fs should not be wrapped automatically; fsspec's https filesystem is such an fs"""
241+
from fsspec.implementations.asyn_wrapper import AsyncFileSystemWrapper
242+
243+
store = FsspecStore.from_url("https://test/path")
244+
245+
assert not isinstance(store.fs, AsyncFileSystemWrapper)
246+
assert store.fs.async_impl

0 commit comments

Comments
 (0)