Skip to content

Commit e0fe40a

Browse files
authored
Merge pull request #37 from fsspec/enable_simplecache
implement _get_file()
2 parents bc376ae + 7d7b0a9 commit e0fe40a

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

ipfsspec/async_ipfs.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import weakref
55
from functools import lru_cache
66
from pathlib import Path
7+
from contextlib import asynccontextmanager
78
import warnings
89

910
import asyncio
@@ -12,6 +13,8 @@
1213

1314
from fsspec.asyn import AsyncFileSystem, sync, sync_wrapper
1415
from fsspec.exceptions import FSTimeoutError
16+
from fsspec.callbacks import DEFAULT_CALLBACK
17+
from fsspec.utils import isfilelike
1518

1619
from multiformats import CID, multicodec
1720
from . import unixfsv1
@@ -118,6 +121,17 @@ async def cat(self, path, session):
118121
self._raise_not_found_for_status(res, path)
119122
return await res.read()
120123

124+
@asynccontextmanager
125+
async def iter_chunked(self, path, session, chunk_size):
126+
res = await self.get(path, session)
127+
async with res:
128+
self._raise_not_found_for_status(res, path)
129+
try:
130+
size = int(res.headers["content-length"])
131+
except (ValueError, KeyError):
132+
size = None
133+
yield size, res.content.iter_chunked(chunk_size)
134+
121135
async def ls(self, path, session, detail=False):
122136
res = await self.get(path, session, headers={"Accept": "application/vnd.ipld.raw"}, params={"format": "raw"})
123137
self._raise_not_found_for_status(res, path)
@@ -293,6 +307,28 @@ async def _cat_file(self, path, start=None, end=None, **kwargs):
293307
session = await self.set_session()
294308
return (await self.gateway.cat(path, session))[start:end]
295309

310+
async def _get_file(
311+
self, rpath, lpath, chunk_size=5 * 2**20, callback=DEFAULT_CALLBACK, **kwargs
312+
):
313+
logger.debug(rpath)
314+
rpath = self._strip_protocol(rpath)
315+
session = await self.set_session()
316+
317+
if isfilelike(lpath):
318+
outfile = lpath
319+
else:
320+
outfile = open(lpath, "wb") # noqa: ASYNC101, ASYNC230
321+
322+
try:
323+
async with self.gateway.iter_chunked(rpath, session, chunk_size) as (size, chunks):
324+
callback.set_size(size)
325+
async for chunk in chunks:
326+
outfile.write(chunk)
327+
callback.relative_update(len(chunk))
328+
finally:
329+
if not isfilelike(lpath):
330+
outfile.close()
331+
296332
async def _info(self, path, **kwargs):
297333
path = self._strip_protocol(path)
298334
session = await self.set_session()

test/test_async.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ async def test_cat_file(fs):
8080
assert res == REF_CONTENT[3:7]
8181

8282

83+
@pytest.mark.asyncio
84+
async def test_get_file(fs, tmp_path):
85+
await fs._get_file(TEST_ROOT + "/default", tmp_path / "default")
86+
assert open(tmp_path / "default", "rb").read() == REF_CONTENT
87+
88+
8389
@pytest.mark.asyncio
8490
async def test_exists(fs):
8591
res = await fs._exists(TEST_ROOT + "/default")

0 commit comments

Comments
 (0)