import traceback
from typing import (
Any,
cast,
Dict,
Tuple,
)
from norfs.fs.base import (
BaseFileSystem,
FSObjectPath,
FSObjectType,
Path,
)
[docs]class CopyError(Exception):
pass
[docs]class CopyFileSystemObject:
_fs: BaseFileSystem
_path: Path
def __init__(self, fs: BaseFileSystem, path: Path) -> None:
self._fs = fs
self._path = path
@property
def fs(self) -> BaseFileSystem:
return self._fs
@property
def path(self) -> Path:
return self._path
[docs] def copy(self, dst: 'CopyFileSystemObject', copy_strategy: 'CopyStrategy') -> None:
raise TypeError("Cannot copy from filesystem object that is not file or directory")
[docs] def copy_from_file(self, src: 'CopyFile', copy_strategy: 'CopyStrategy') -> None:
raise TypeError("Cannot copy to filesystem object that is not file or directory")
[docs] def copy_from_dir(self, src: 'CopyDirectory', copy_strategy: 'CopyStrategy') -> None:
raise TypeError("Cannot copy to filesystem object that is not file or directory")
def __eq__(self, other: Any) -> bool:
if isinstance(other, self.__class__):
other_casted: 'CopyFileSystemObject' = cast(CopyFileSystemObject, other)
return self._fs == other_casted._fs and self._path == other_casted._path
return False
def __repr__(self) -> str:
return f"{self.__class__.__name__}(fs={self._fs}, path={self._path})"
[docs]class CopyFile(CopyFileSystemObject):
[docs] def copy(self, dst: 'CopyFileSystemObject', copy_strategy: 'CopyStrategy') -> None:
dst.copy_from_file(self, copy_strategy)
[docs] def copy_from_file(self, src: 'CopyFile', copy_strategy: 'CopyStrategy') -> None:
copy_strategy.copy_file_to_file(src, self)
[docs] def copy_from_dir(self, src: 'CopyDirectory', copy_strategy: 'CopyStrategy') -> None:
raise TypeError("Cannot copy Directory into a File.")
[docs]class CopyDirectory(CopyFileSystemObject):
[docs] def file(self, suffix: str) -> 'CopyFile':
return CopyFile(self._fs, self._path.child(suffix))
[docs] def subdir(self, suffix: str) -> 'CopyDirectory':
return CopyDirectory(self._fs, self._path.child(suffix))
[docs] def copy(self, dst: 'CopyFileSystemObject', copy_strategy: 'CopyStrategy') -> None:
dst.copy_from_dir(self, copy_strategy)
[docs] def copy_from_file(self, src: 'CopyFile', copy_strategy: 'CopyStrategy') -> None:
copy_strategy.copy_file_to_file(src, self.file(src.path.basename))
[docs] def copy_from_dir(self, src: 'CopyDirectory', copy_strategy: 'CopyStrategy') -> None:
copy_strategy.copy_dir_to_dir(src, self)
[docs]class CopyStrategy:
[docs] def copy_dir_to_dir(self, src: CopyDirectory, dst: CopyDirectory) -> None:
raise NotImplementedError()
[docs] def copy_file_to_file(self, src: CopyFile, dst: CopyFile) -> None:
raise NotImplementedError()
[docs]class GenericCopyStrategy(CopyStrategy):
[docs] def copy_dir_to_dir(self, src: CopyDirectory, dst: CopyDirectory) -> None:
fs_path: FSObjectPath
for fs_path in src.fs.dir_list(src.path):
if fs_path.type == FSObjectType.FILE:
src_child_file: CopyFile = src.file(fs_path.path.basename)
dst_child_file: CopyFile = dst.file(fs_path.path.basename)
self.copy_file_to_file(src_child_file, dst_child_file)
elif fs_path.type == FSObjectType.DIR:
src_child_dir: CopyDirectory = src.subdir(fs_path.path.basename)
dst_child_dir: CopyDirectory = dst.subdir(fs_path.path.basename)
self.copy_dir_to_dir(src_child_dir, dst_child_dir)
[docs] def copy_file_to_file(self, src: CopyFile, dst: CopyFile) -> None:
dst.fs.file_write(dst.path, src.fs.file_read(src.path))
[docs]class Copier:
_copy_strategies: Dict[Tuple[BaseFileSystem, BaseFileSystem], CopyStrategy]
_default: CopyStrategy
def __init__(self, default_copy_strategy: CopyStrategy) -> None:
self._copy_strategies = {}
self._default = default_copy_strategy
[docs] def set_copy_policy(self, src_fs: BaseFileSystem, dst_fs: BaseFileSystem, copy_strategy: CopyStrategy) -> None:
self._copy_strategies[(src_fs, dst_fs)] = copy_strategy
[docs] def copy(self, src: CopyFileSystemObject, dst: CopyFileSystemObject) -> None:
copy_strategy: CopyStrategy = self._copy_strategies.get((src.fs, dst.fs), self._default)
try:
src.copy(dst, copy_strategy)
except Exception:
raise CopyError(traceback.format_exc())