@@ -86,8 +86,21 @@ async def _async_raise_not_found_for_status(self, response: Any, url: str) -> No
8686 finally :
8787 self ._raise_not_found_for_status (response , url )
8888
89+ def _check_session_open (self ) -> bool :
90+ # Check that _session is active. Expects that if _session is populated with .set_session, result
91+ # result was already awaited
92+ if self ._session is None :
93+ return False
94+ return not self ._session .closed
95+
96+ async def _async_startup (self ) -> None :
97+ await self .set_session ()
98+ if not self ._check_session_open ():
99+ raise RuntimeError ("FusionFS session closed before operation" )
100+
89101 async def _decorate_url_a (self , url : str ) -> str :
90102 url = urljoin (f"{ self .client_kwargs ['root_url' ]} catalogs/" , url ) if "http" not in url else url
103+ url = url [:- 1 ] if url [- 1 ] == "/" else url
91104 return url
92105
93106 def _decorate_url (self , url : str ) -> str :
@@ -105,6 +118,16 @@ async def _isdir(self, path: str) -> bool:
105118 return False
106119
107120 async def _changes (self , url : str ) -> dict [Any , Any ]:
121+ """Get from given url.
122+
123+ Currently called within the context of the /changes api endpoint.
124+
125+ Args:
126+ url: str
127+
128+ Returns:
129+ Dict containing json-ified return from endpoint.
130+ """
108131 url = self ._decorate_url (url )
109132 try :
110133 session = await self .set_session ()
@@ -120,7 +143,7 @@ async def _changes(self, url: str) -> dict[Any, Any]:
120143 logger .log (VERBOSE_LVL , f"Artificial error, { ex } " )
121144 raise ex
122145
123- async def _ls_real (self , url : str , detail : bool = True , ** kwargs : Any ) -> Any :
146+ async def _ls_real (self , url : str , detail : bool = False , ** kwargs : Any ) -> Any :
124147 # ignoring URL-encoded arguments
125148 clean_url = url
126149 if "http" not in url :
@@ -195,9 +218,21 @@ def info(self, path: str, **kwargs: Any) -> Any:
195218
196219 return res
197220
198- async def _ls (self , url : str , detail : bool = True , ** kwargs : Any ) -> Any :
199- url = await self ._decorate_url_a (url )
200- return await super ()._ls (url , detail , ** kwargs )
221+ async def _info (self , path : str , ** kwargs : Any ) -> Any :
222+ await self ._async_startup ()
223+ path = await self ._decorate_url_a (path )
224+ kwargs ["keep_protocol" ] = True
225+ res = await super ()._ls (path , detail = True , ** kwargs )
226+ if res [0 ]["type" ] != "file" :
227+ res = await super ()._info (path , ** kwargs )
228+ if path .split ("/" )[- 2 ] == "datasets" :
229+ target = path .split ("/" )[- 1 ]
230+ args = ["/" .join (path .split ("/" )[:- 1 ]) + f"/changes?datasets={ quote (target )} " ]
231+ res ["changes" ] = await self ._changes (* args )
232+ split_path = path .split ("/" )
233+ if len (split_path ) > 1 and split_path [- 2 ] == "distributions" :
234+ res = res [0 ]
235+ return res
201236
202237 def ls (self , url : str , detail : bool = False , ** kwargs : Any ) -> Any :
203238 """List resources.
@@ -223,7 +258,21 @@ def ls(self, url: str, detail: bool = False, **kwargs: Any) -> Any:
223258
224259 return ret
225260
226- def exists (self , url : str , detail : bool = True , ** kwargs : Any ) -> Any :
261+ async def _ls (self , url : str , detail : bool = False , ** kwargs : Any ) -> Any :
262+ await self ._async_startup ()
263+ url = await self ._decorate_url_a (url )
264+ ret = await super ()._ls (url , detail , ** kwargs )
265+ keep_protocol = kwargs .pop ("keep_protocol" , False )
266+ if detail :
267+ if not keep_protocol :
268+ for k in ret :
269+ k ["name" ] = k ["name" ].split (f"{ self .client_kwargs ['root_url' ]} catalogs/" )[- 1 ]
270+ elif not keep_protocol :
271+ return [x .split (f"{ self .client_kwargs ['root_url' ]} catalogs/" )[- 1 ] for x in ret ]
272+
273+ return ret
274+
275+ def exists (self , url : str , ** kwargs : Any ) -> Any :
227276 """Check existence.
228277
229278 Args:
@@ -235,7 +284,13 @@ def exists(self, url: str, detail: bool = True, **kwargs: Any) -> Any:
235284
236285 """
237286 url = self ._decorate_url (url )
238- return super ().exists (url , detail , ** kwargs )
287+ return super ().exists (url , ** kwargs )
288+
289+ async def _exists (self , url : str , ** kwargs : Any ) -> Any :
290+ await self ._async_startup ()
291+ url = self ._decorate_url (url )
292+ out = await super ()._exists (url , ** kwargs )
293+ return out
239294
240295 def isfile (self , path : str ) -> Union [bool , Any ]:
241296 """Is path a file.
@@ -264,6 +319,12 @@ def cat(self, url: str, start: Optional[int] = None, end: Optional[int] = None,
264319 url = self ._decorate_url (url )
265320 return super ().cat (url , start = start , end = end , ** kwargs )
266321
322+ async def _cat (self , url : str , start : Optional [int ] = None , end : Optional [int ] = None , ** kwargs : Any ) -> Any :
323+ await self ._async_startup ()
324+ url = self ._decorate_url (url )
325+ out = await super ()._cat (url , start = start , end = end , ** kwargs )
326+ return out
327+
267328 async def _fetch_range (
268329 self ,
269330 session : aiohttp .ClientSession ,
@@ -836,6 +897,12 @@ def find(self, path: str, maxdepth: Optional[int] = None, withdirs: bool = False
836897 path = self ._decorate_url (path )
837898 return super ().find (path , maxdepth = maxdepth , withdirs = withdirs , ** kwargs )
838899
900+ async def _find (self , path : str , maxdepth : Optional [int ] = None , withdirs : bool = False , ** kwargs : Any ) -> Any :
901+ await self ._async_startup ()
902+ path = self ._decorate_url (path )
903+ out = await super ()._find (path , maxdepth = maxdepth , withdirs = withdirs , ** kwargs )
904+ return out
905+
839906 def glob (self , path : str , ** kwargs : Any ) -> Any :
840907 """Glob.
841908
@@ -849,6 +916,10 @@ def glob(self, path: str, **kwargs: Any) -> Any:
849916
850917 return super ().glob (path , ** kwargs )
851918
919+ async def _glob (self , path : str , ** kwargs : Any ) -> Any :
920+ out = await super ()._glob (path , ** kwargs )
921+ return out
922+
852923 def open (
853924 self ,
854925 path : str ,
0 commit comments