1010
1111from . import errors
1212from .base import FS
13- from .copy import copy_file
13+ from .copy import copy_file , copy_dir
1414from .info import Info
15- from .move import move_file
15+ from .move import move_file , move_dir
1616from .path import abspath , normpath
1717from .error_tools import unwrap_errors
1818
@@ -180,6 +180,17 @@ def move(self, src_path, dst_path, overwrite=False):
180180 raise errors .DestinationExists (_dst_path )
181181 move_file (src_fs , _src_path , dst_fs , _dst_path )
182182
183+ def copydir (self , src_path , dst_path , create = False ):
184+ # type: (Text, Text, bool) -> None
185+ src_fs , _src_path = self .delegate_path (src_path )
186+ dst_fs , _dst_path = self .delegate_path (dst_path )
187+ with unwrap_errors ({_src_path : src_path , _dst_path : dst_path }):
188+ if not create and not dst_fs .exists (_dst_path ):
189+ raise errors .ResourceNotFound (dst_path )
190+ if not src_fs .getinfo (_src_path ).is_dir :
191+ raise errors .DirectoryExpected (src_path )
192+ move_dir (src_fs , _src_path , dst_fs , _dst_path )
193+
183194 def openbin (self , path , mode = "r" , buffering = - 1 , ** options ):
184195 # type: (Text, Text, int, **Any) -> BinaryIO
185196 self .check ()
@@ -205,6 +216,16 @@ def removedir(self, path):
205216 with unwrap_errors (path ):
206217 _fs .removedir (_path )
207218
219+ def removetree (self , dir_path ):
220+ # type: (Text) -> None
221+ self .check ()
222+ _path = abspath (normpath (dir_path ))
223+ if _path == "/" :
224+ raise errors .RemoveRootError ()
225+ _fs , _path = self .delegate_path (dir_path )
226+ with unwrap_errors (dir_path ):
227+ _fs .removetree (_path )
228+
208229 def scandir (
209230 self ,
210231 path , # type: Text
@@ -247,6 +268,17 @@ def copy(self, src_path, dst_path, overwrite=False):
247268 raise errors .DestinationExists (_dst_path )
248269 copy_file (src_fs , _src_path , dst_fs , _dst_path )
249270
271+ def copydir (self , src_path , dst_path , create = False ):
272+ # type: (Text, Text, bool) -> None
273+ src_fs , _src_path = self .delegate_path (src_path )
274+ dst_fs , _dst_path = self .delegate_path (dst_path )
275+ with unwrap_errors ({_src_path : src_path , _dst_path : dst_path }):
276+ if not create and not dst_fs .exists (_dst_path ):
277+ raise errors .ResourceNotFound (dst_path )
278+ if not src_fs .getinfo (_src_path ).is_dir :
279+ raise errors .DirectoryExpected (src_path )
280+ copy_dir (src_fs , _src_path , dst_fs , _dst_path )
281+
250282 def create (self , path , wipe = False ):
251283 # type: (Text, bool) -> bool
252284 self .check ()
@@ -262,6 +294,13 @@ def desc(self, path):
262294 desc = _fs .desc (_path )
263295 return desc
264296
297+ def download (self , path , file , chunk_size = None , ** options ):
298+ # type: (Text, BinaryIO, Optional[int], **Any) -> None
299+ self .check ()
300+ _fs , _path = self .delegate_path (path )
301+ with unwrap_errors (path ):
302+ _fs .download (_path , file , chunk_size = chunk_size , ** options )
303+
265304 def exists (self , path ):
266305 # type: (Text) -> bool
267306 self .check ()
0 commit comments