from pathlib import Path import shutil import logging def rm(path: Path): """Delete whatever is specified by `path`""" if path.is_dir(): shutil.rmtree(str(path)) else: path.unlink() class InplaceBackup: """Utility class for moving a file out of the way by appending a '~'""" log = logging.getLogger('%s.inplace-backup' % __name__) def __init__(self, path: Path): self.path = path self.backup() def backup(self): """Move 'path' to 'path~'""" if not self.path.exists(): raise FileNotFoundError("Can't backup path which doesn't exist") self.backup_path = Path(str(self.path) + '~') if self.backup_path.exists(): self.log.warning("Overwriting existing backup '{}'".format(self.backup_path)) rm(self.backup_path) shutil.move(str(self.path), str(self.backup_path)) def restore(self): """Move 'path~' to 'path'""" try: getattr(self, 'backup_path') except AttributeError as err: raise RuntimeError("Can't restore file before backing it up") from err if not self.backup_path.exists(): raise FileNotFoundError("Can't restore backup which doesn't exist") if self.path.exists(): self.log.warning("Overwriting '{0}' with backup file".format(self.path)) rm(self.path) shutil.move(str(self.backup_path), str(self.path)) def remove(self): """Remove 'path~'""" rm(self.backup_path)