dirfs.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. from .. import filesystem
  2. from ..asyn import AsyncFileSystem
  3. from .chained import ChainedFileSystem
  4. class DirFileSystem(AsyncFileSystem, ChainedFileSystem):
  5. """Directory prefix filesystem
  6. The DirFileSystem is a filesystem-wrapper. It assumes every path it is dealing with
  7. is relative to the `path`. After performing the necessary paths operation it
  8. delegates everything to the wrapped filesystem.
  9. """
  10. protocol = "dir"
  11. def __init__(
  12. self,
  13. path=None,
  14. fs=None,
  15. fo=None,
  16. target_protocol=None,
  17. target_options=None,
  18. **storage_options,
  19. ):
  20. """
  21. Parameters
  22. ----------
  23. path: str
  24. Path to the directory.
  25. fs: AbstractFileSystem
  26. An instantiated filesystem to wrap.
  27. target_protocol, target_options:
  28. if fs is none, construct it from these
  29. fo: str
  30. Alternate for path; do not provide both
  31. """
  32. super().__init__(**storage_options)
  33. if fs is None:
  34. fs = filesystem(protocol=target_protocol, **(target_options or {}))
  35. path = path or fo
  36. if self.asynchronous and not fs.async_impl:
  37. raise ValueError("can't use asynchronous with non-async fs")
  38. if fs.async_impl and self.asynchronous != fs.asynchronous:
  39. raise ValueError("both dirfs and fs should be in the same sync/async mode")
  40. self.path = fs._strip_protocol(path)
  41. self.fs = fs
  42. def _join(self, path):
  43. if isinstance(path, str):
  44. if not self.path:
  45. return path
  46. if not path:
  47. return self.path
  48. return self.fs.sep.join((self.path, self._strip_protocol(path)))
  49. if isinstance(path, dict):
  50. return {self._join(_path): value for _path, value in path.items()}
  51. return [self._join(_path) for _path in path]
  52. def _relpath(self, path):
  53. if isinstance(path, str):
  54. if not self.path:
  55. return path
  56. # We need to account for S3FileSystem returning paths that do not
  57. # start with a '/'
  58. if path == self.path or (
  59. self.path.startswith(self.fs.sep) and path == self.path[1:]
  60. ):
  61. return ""
  62. prefix = self.path + self.fs.sep
  63. if self.path.startswith(self.fs.sep) and not path.startswith(self.fs.sep):
  64. prefix = prefix[1:]
  65. assert path.startswith(prefix)
  66. return path[len(prefix) :]
  67. return [self._relpath(_path) for _path in path]
  68. # Wrappers below
  69. @property
  70. def sep(self):
  71. return self.fs.sep
  72. async def set_session(self, *args, **kwargs):
  73. return await self.fs.set_session(*args, **kwargs)
  74. async def _rm_file(self, path, **kwargs):
  75. return await self.fs._rm_file(self._join(path), **kwargs)
  76. def rm_file(self, path, **kwargs):
  77. return self.fs.rm_file(self._join(path), **kwargs)
  78. async def _rm(self, path, *args, **kwargs):
  79. return await self.fs._rm(self._join(path), *args, **kwargs)
  80. def rm(self, path, *args, **kwargs):
  81. return self.fs.rm(self._join(path), *args, **kwargs)
  82. async def _cp_file(self, path1, path2, **kwargs):
  83. return await self.fs._cp_file(self._join(path1), self._join(path2), **kwargs)
  84. def cp_file(self, path1, path2, **kwargs):
  85. return self.fs.cp_file(self._join(path1), self._join(path2), **kwargs)
  86. async def _copy(
  87. self,
  88. path1,
  89. path2,
  90. *args,
  91. **kwargs,
  92. ):
  93. return await self.fs._copy(
  94. self._join(path1),
  95. self._join(path2),
  96. *args,
  97. **kwargs,
  98. )
  99. def copy(self, path1, path2, *args, **kwargs):
  100. return self.fs.copy(
  101. self._join(path1),
  102. self._join(path2),
  103. *args,
  104. **kwargs,
  105. )
  106. async def _pipe(self, path, *args, **kwargs):
  107. return await self.fs._pipe(self._join(path), *args, **kwargs)
  108. def pipe(self, path, *args, **kwargs):
  109. return self.fs.pipe(self._join(path), *args, **kwargs)
  110. async def _pipe_file(self, path, *args, **kwargs):
  111. return await self.fs._pipe_file(self._join(path), *args, **kwargs)
  112. def pipe_file(self, path, *args, **kwargs):
  113. return self.fs.pipe_file(self._join(path), *args, **kwargs)
  114. async def _cat_file(self, path, *args, **kwargs):
  115. return await self.fs._cat_file(self._join(path), *args, **kwargs)
  116. def cat_file(self, path, *args, **kwargs):
  117. return self.fs.cat_file(self._join(path), *args, **kwargs)
  118. async def _cat(self, path, *args, **kwargs):
  119. ret = await self.fs._cat(
  120. self._join(path),
  121. *args,
  122. **kwargs,
  123. )
  124. if isinstance(ret, dict):
  125. return {self._relpath(key): value for key, value in ret.items()}
  126. return ret
  127. def cat(self, path, *args, **kwargs):
  128. ret = self.fs.cat(
  129. self._join(path),
  130. *args,
  131. **kwargs,
  132. )
  133. if isinstance(ret, dict):
  134. return {self._relpath(key): value for key, value in ret.items()}
  135. return ret
  136. async def _put_file(self, lpath, rpath, **kwargs):
  137. return await self.fs._put_file(lpath, self._join(rpath), **kwargs)
  138. def put_file(self, lpath, rpath, **kwargs):
  139. return self.fs.put_file(lpath, self._join(rpath), **kwargs)
  140. async def _put(
  141. self,
  142. lpath,
  143. rpath,
  144. *args,
  145. **kwargs,
  146. ):
  147. return await self.fs._put(
  148. lpath,
  149. self._join(rpath),
  150. *args,
  151. **kwargs,
  152. )
  153. def put(self, lpath, rpath, *args, **kwargs):
  154. return self.fs.put(
  155. lpath,
  156. self._join(rpath),
  157. *args,
  158. **kwargs,
  159. )
  160. async def _get_file(self, rpath, lpath, **kwargs):
  161. return await self.fs._get_file(self._join(rpath), lpath, **kwargs)
  162. def get_file(self, rpath, lpath, **kwargs):
  163. return self.fs.get_file(self._join(rpath), lpath, **kwargs)
  164. async def _get(self, rpath, *args, **kwargs):
  165. return await self.fs._get(self._join(rpath), *args, **kwargs)
  166. def get(self, rpath, *args, **kwargs):
  167. return self.fs.get(self._join(rpath), *args, **kwargs)
  168. async def _isfile(self, path):
  169. return await self.fs._isfile(self._join(path))
  170. def isfile(self, path):
  171. return self.fs.isfile(self._join(path))
  172. async def _isdir(self, path):
  173. return await self.fs._isdir(self._join(path))
  174. def isdir(self, path):
  175. return self.fs.isdir(self._join(path))
  176. async def _size(self, path):
  177. return await self.fs._size(self._join(path))
  178. def size(self, path):
  179. return self.fs.size(self._join(path))
  180. async def _exists(self, path):
  181. return await self.fs._exists(self._join(path))
  182. def exists(self, path):
  183. return self.fs.exists(self._join(path))
  184. async def _info(self, path, **kwargs):
  185. info = await self.fs._info(self._join(path), **kwargs)
  186. info = info.copy()
  187. info["name"] = self._relpath(info["name"])
  188. return info
  189. def info(self, path, **kwargs):
  190. info = self.fs.info(self._join(path), **kwargs)
  191. info = info.copy()
  192. info["name"] = self._relpath(info["name"])
  193. return info
  194. async def _ls(self, path, detail=True, **kwargs):
  195. ret = (await self.fs._ls(self._join(path), detail=detail, **kwargs)).copy()
  196. if detail:
  197. out = []
  198. for entry in ret:
  199. entry = entry.copy()
  200. entry["name"] = self._relpath(entry["name"])
  201. out.append(entry)
  202. return out
  203. return self._relpath(ret)
  204. def ls(self, path, detail=True, **kwargs):
  205. ret = self.fs.ls(self._join(path), detail=detail, **kwargs).copy()
  206. if detail:
  207. out = []
  208. for entry in ret:
  209. entry = entry.copy()
  210. entry["name"] = self._relpath(entry["name"])
  211. out.append(entry)
  212. return out
  213. return self._relpath(ret)
  214. async def _walk(self, path, *args, **kwargs):
  215. async for root, dirs, files in self.fs._walk(self._join(path), *args, **kwargs):
  216. yield self._relpath(root), dirs, files
  217. def walk(self, path, *args, **kwargs):
  218. for root, dirs, files in self.fs.walk(self._join(path), *args, **kwargs):
  219. yield self._relpath(root), dirs, files
  220. async def _glob(self, path, **kwargs):
  221. detail = kwargs.get("detail", False)
  222. ret = await self.fs._glob(self._join(path), **kwargs)
  223. if detail:
  224. return {self._relpath(path): info for path, info in ret.items()}
  225. return self._relpath(ret)
  226. def glob(self, path, **kwargs):
  227. detail = kwargs.get("detail", False)
  228. ret = self.fs.glob(self._join(path), **kwargs)
  229. if detail:
  230. return {self._relpath(path): info for path, info in ret.items()}
  231. return self._relpath(ret)
  232. async def _du(self, path, *args, **kwargs):
  233. total = kwargs.get("total", True)
  234. ret = await self.fs._du(self._join(path), *args, **kwargs)
  235. if total:
  236. return ret
  237. return {self._relpath(path): size for path, size in ret.items()}
  238. def du(self, path, *args, **kwargs):
  239. total = kwargs.get("total", True)
  240. ret = self.fs.du(self._join(path), *args, **kwargs)
  241. if total:
  242. return ret
  243. return {self._relpath(path): size for path, size in ret.items()}
  244. async def _find(self, path, *args, **kwargs):
  245. detail = kwargs.get("detail", False)
  246. ret = await self.fs._find(self._join(path), *args, **kwargs)
  247. if detail:
  248. return {self._relpath(path): info for path, info in ret.items()}
  249. return self._relpath(ret)
  250. def find(self, path, *args, **kwargs):
  251. detail = kwargs.get("detail", False)
  252. ret = self.fs.find(self._join(path), *args, **kwargs)
  253. if detail:
  254. return {self._relpath(path): info for path, info in ret.items()}
  255. return self._relpath(ret)
  256. async def _expand_path(self, path, *args, **kwargs):
  257. return self._relpath(
  258. await self.fs._expand_path(self._join(path), *args, **kwargs)
  259. )
  260. def expand_path(self, path, *args, **kwargs):
  261. return self._relpath(self.fs.expand_path(self._join(path), *args, **kwargs))
  262. async def _mkdir(self, path, *args, **kwargs):
  263. return await self.fs._mkdir(self._join(path), *args, **kwargs)
  264. def mkdir(self, path, *args, **kwargs):
  265. return self.fs.mkdir(self._join(path), *args, **kwargs)
  266. async def _makedirs(self, path, *args, **kwargs):
  267. return await self.fs._makedirs(self._join(path), *args, **kwargs)
  268. def makedirs(self, path, *args, **kwargs):
  269. return self.fs.makedirs(self._join(path), *args, **kwargs)
  270. def rmdir(self, path):
  271. return self.fs.rmdir(self._join(path))
  272. def mv(self, path1, path2, **kwargs):
  273. return self.fs.mv(
  274. self._join(path1),
  275. self._join(path2),
  276. **kwargs,
  277. )
  278. def touch(self, path, **kwargs):
  279. return self.fs.touch(self._join(path), **kwargs)
  280. def created(self, path):
  281. return self.fs.created(self._join(path))
  282. def modified(self, path):
  283. return self.fs.modified(self._join(path))
  284. def sign(self, path, *args, **kwargs):
  285. return self.fs.sign(self._join(path), *args, **kwargs)
  286. def __repr__(self):
  287. return f"{self.__class__.__qualname__}(path='{self.path}', fs={self.fs})"
  288. def open(
  289. self,
  290. path,
  291. *args,
  292. **kwargs,
  293. ):
  294. return self.fs.open(
  295. self._join(path),
  296. *args,
  297. **kwargs,
  298. )
  299. async def open_async(
  300. self,
  301. path,
  302. *args,
  303. **kwargs,
  304. ):
  305. return await self.fs.open_async(
  306. self._join(path),
  307. *args,
  308. **kwargs,
  309. )