Skip to content

Commit 14d319c

Browse files
authored
Merge pull request #1376 from dandi/open-readable
Properly open filehandles for `RemoteReadableAsset`s
2 parents a51e0a7 + cef7192 commit 14d319c

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

dandi/misctypes.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,10 @@ def open(self) -> IO[bytes]:
345345
# Optional dependency:
346346
import fsspec
347347

348-
return cast(IO[bytes], fsspec.open(self.url, mode="rb"))
348+
# We need to call open() on the return value of fsspec.open() because
349+
# otherwise the filehandle will only be opened when used to enter a
350+
# context manager.
351+
return cast(IO[bytes], fsspec.open(self.url, mode="rb").open())
349352

350353
def get_size(self) -> int:
351354
return self.size

dandi/tests/test_dandiapi.py

+25-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@
2525
dandiset_identifier_regex,
2626
dandiset_metadata_file,
2727
)
28-
from ..dandiapi import DandiAPIClient, RemoteAsset, RemoteZarrAsset, Version
28+
from ..dandiapi import (
29+
DandiAPIClient,
30+
RemoteAsset,
31+
RemoteBlobAsset,
32+
RemoteZarrAsset,
33+
Version,
34+
)
2935
from ..download import download
3036
from ..exceptions import NotFoundError, SchemaVersionError
3137
from ..files import GenericAsset, dandi_file
@@ -745,3 +751,21 @@ def test_rename_type_mismatch(text_dandiset: SampleDandiset, dest: str) -> None:
745751
assert asset1a.get_raw_metadata()["path"] == "file.txt"
746752
with pytest.raises(NotFoundError):
747753
text_dandiset.dandiset.get_asset_by_path(dest)
754+
755+
756+
def test_asset_as_readable_open(new_dandiset: SampleDandiset, tmp_path: Path) -> None:
757+
p = tmp_path / "foo.txt"
758+
# Write bytes so that the LF doesn't get converted on Windows:
759+
p.write_bytes(b"This is test text.\n")
760+
d = new_dandiset.dandiset
761+
d.upload_raw_asset(p, {"path": "foo.txt"})
762+
(asset,) = d.get_assets()
763+
assert isinstance(asset, RemoteBlobAsset)
764+
# The purpose of this test is to check that RemoteReadableAsset.open()
765+
# returns a filehandle that can immediately be used, so don't use a `with`
766+
# block here, as that opens fsspec file objects.
767+
fp = asset.as_readable().open()
768+
try:
769+
assert fp.read() == b"This is test text.\n"
770+
finally:
771+
fp.close()

0 commit comments

Comments
 (0)