@@ -207,6 +207,7 @@ def info(self, path: str, **kwargs: Any) -> Any:
207207 kwargs ["keep_protocol" ] = True
208208 res = super ().ls (path , detail = True , ** kwargs )
209209 if res [0 ]["type" ] != "file" :
210+ kwargs .pop ("keep_protocol" , None )
210211 res = super ().info (path , ** kwargs )
211212 if path .split ("/" )[- 2 ] == "datasets" :
212213 target = path .split ("/" )[- 1 ]
@@ -220,15 +221,20 @@ def info(self, path: str, **kwargs: Any) -> Any:
220221
221222 async def _info (self , path : str , ** kwargs : Any ) -> Any :
222223 await self ._async_startup ()
223- path = await self ._decorate_url_a (path )
224+ path = self ._decorate_url (path )
224225 kwargs ["keep_protocol" ] = True
225226 res = await super ()._ls (path , detail = True , ** kwargs )
226227 if res [0 ]["type" ] != "file" :
228+ kwargs .pop ("keep_protocol" , None )
227229 res = await super ()._info (path , ** kwargs )
228230 if path .split ("/" )[- 2 ] == "datasets" :
229231 target = path .split ("/" )[- 1 ]
230232 args = ["/" .join (path .split ("/" )[:- 1 ]) + f"/changes?datasets={ quote (target )} " ]
231233 res ["changes" ] = await self ._changes (* args )
234+ if res ["size" ] is None and (res ["mimetype" ] == "application/json" ) and (res ["type" ] == "file" ):
235+ res ["size" ] = 0
236+ res .pop ("mimetype" , None )
237+ res ["type" ] = "directory"
232238 split_path = path .split ("/" )
233239 if len (split_path ) > 1 and split_path [- 2 ] == "distributions" :
234240 res = res [0 ]
@@ -325,6 +331,29 @@ async def _cat(self, url: str, start: Optional[int] = None, end: Optional[int] =
325331 out = await super ()._cat (url , start = start , end = end , ** kwargs )
326332 return out
327333
334+ async def _stream_file (self , url : str , chunk_size : int = 100 ) -> AsyncGenerator [bytes , None ]:
335+ """Return an async stream to file at the given url.
336+
337+ Args:
338+ url (str): File url. Appends Fusion.root_url if http prefix not present.
339+ chunk_size (int, optional): Size for each chunk in async stream. Defaults to 100.
340+
341+ Returns:
342+ AsyncGenerator[bytes, None]: Async generator object.
343+
344+ Yields:
345+ Iterator[AsyncGenerator[bytes, None]]: Next set of bytes read from the file at given url.
346+ """
347+ await self ._async_startup ()
348+ url = self ._decorate_url (url )
349+ f = await self .open_async (url , "rb" )
350+ async with f :
351+ while True :
352+ chunk = await f .read (chunk_size )
353+ if not chunk :
354+ break
355+ yield chunk
356+
328357 async def _fetch_range (
329358 self ,
330359 session : aiohttp .ClientSession ,
0 commit comments