1010from abc import ABC
1111from abc import abstractmethod
1212from typing import Any
13+ from typing import cast
1314from typing import Dict
1415from typing import List
16+ from typing import Literal
1517from typing import Optional
18+ from typing import overload
1619from typing import Union
1720
1821from .. import config
@@ -427,7 +430,7 @@ def listdir(
427430 path : PathLike = '/' ,
428431 * ,
429432 recursive : bool = False ,
430- ) -> List [str ]:
433+ ) -> Union [ List [str ], List [ Union [ str , Dict [ str , Any ]]] ]:
431434 pass
432435
433436 @abstractmethod
@@ -908,7 +911,11 @@ def is_file(self, path: PathLike) -> bool:
908911 return False
909912 raise
910913
911- def _listdir (self , path : PathLike , * , recursive : bool = False , return_meta : bool = False ) -> List [Union [str , Dict [str , Any ]]]:
914+ def _listdir (
915+ self , path : PathLike , * ,
916+ recursive : bool = False ,
917+ return_meta : bool = False ,
918+ ) -> List [Union [str , Dict [str , Any ]]]:
912919 """
913920 Return the names (or metadata) of files in a directory.
914921
@@ -929,24 +936,55 @@ def _listdir(self, path: PathLike, *, recursive: bool = False, return_meta: bool
929936 out : List [Union [str , Dict [str , Any ]]] = []
930937 for item in res .get ('content' ) or []:
931938 if return_meta :
932- out .append ({'path' : item ['path' ], 'type' : item ['type' ]})
939+ out .append (
940+ {'path' : item ['path' ], 'type' : item ['type' ]},
941+ )
933942 else :
934943 out .append (item ['path' ])
935944 if item ['type' ] == 'directory' :
936- out .extend (self ._listdir (item ['path' ], recursive = recursive , return_meta = return_meta ))
945+ out .extend (
946+ self ._listdir (
947+ item ['path' ],
948+ recursive = recursive ,
949+ return_meta = return_meta ,
950+ ),
951+ )
937952 return out
938953
939954 if return_meta :
940- return [{'path' : x ['path' ], 'type' : x ['type' ]} for x in (res .get ('content' ) or [])]
955+ return [
956+ {'path' : x ['path' ], 'type' : x ['type' ]}
957+ for x in (res .get ('content' ) or [])
958+ ]
941959 return [x ['path' ] for x in (res .get ('content' ) or [])]
942960
961+ @overload
962+ def listdir (
963+ self ,
964+ path : PathLike = '/' ,
965+ * ,
966+ recursive : bool = False ,
967+ return_meta : Literal [True ] = ...,
968+ ) -> List [Dict [str , Any ]]:
969+ ...
970+
971+ @overload
972+ def listdir (
973+ self ,
974+ path : PathLike = '/' ,
975+ * ,
976+ recursive : bool = False ,
977+ return_meta : Literal [False ] = ...,
978+ ) -> List [str ]:
979+ ...
980+
943981 def listdir (
944982 self ,
945983 path : PathLike = '/' ,
946984 * ,
947985 recursive : bool = False ,
948986 return_meta : bool = False ,
949- ) -> List [ Union [str , Dict [str , Any ]]]:
987+ ) -> Union [List [ str ], List [ Dict [str , Any ]]]:
950988 """
951989 List the files / folders at the given path.
952990
@@ -972,16 +1010,23 @@ def listdir(
9721010 except Exception as exc :
9731011 # If the path doesn't exist or isn't a directory, _listdir will fail
9741012 raise NotADirectoryError (f'path is not a directory: { path } ' ) from exc
1013+
9751014 if path != '/' :
9761015 path_n = len (path .split ('/' )) - 1
9771016 if return_meta :
978- for i in range (len (out )):
979- if isinstance (out [i ], dict ):
980- rel = '/' .join (out [i ]['path' ].split ('/' )[path_n :])
981- out [i ]['path' ] = rel
982- else :
983- out = ['/' .join (str (x ).split ('/' )[path_n :]) for x in out ]
984- return out
1017+ result : List [Dict [str , Any ]] = []
1018+ for item in out :
1019+ if isinstance (item , dict ):
1020+ rel = '/' .join (item ['path' ].split ('/' )[path_n :])
1021+ item ['path' ] = rel
1022+ result .append (item )
1023+ return result
1024+ return ['/' .join (str (x ).split ('/' )[path_n :]) for x in out ]
1025+
1026+ # _listdir guarantees homogeneous type based on return_meta
1027+ if return_meta :
1028+ return cast (List [Dict [str , Any ]], out )
1029+ return cast (List [str ], out )
9851030
9861031 def download_file (
9871032 self ,
@@ -1106,9 +1151,14 @@ def download_folder(
11061151 os .makedirs (target_dir , exist_ok = True )
11071152 continue
11081153 remote_path = os .path .join (path , rel_path )
1109- target_file = os .path .normpath (os .path .join (local_path , rel_path ))
1154+ target_file = os .path .normpath (
1155+ os .path .join (local_path , rel_path ),
1156+ )
11101157 os .makedirs (os .path .dirname (target_file ), exist_ok = True )
1111- self ._download_file (remote_path , target_file , overwrite = overwrite , _skip_dir_check = True )
1158+ self ._download_file (
1159+ remote_path , target_file ,
1160+ overwrite = overwrite , _skip_dir_check = True ,
1161+ )
11121162
11131163 def remove (self , path : PathLike ) -> None :
11141164 """
0 commit comments