diff --git a/rbackup/hierarchy/hierarchy.py b/rbackup/hierarchy/hierarchy.py index 7502362..268a485 100644 --- a/rbackup/hierarchy/hierarchy.py +++ b/rbackup/hierarchy/hierarchy.py @@ -4,6 +4,7 @@ :synopsis: Classes for creating the backup hierarchy. """ import logging +import pickle from pathlib import Path @@ -11,6 +12,11 @@ from pathlib import Path syslog = logging.getLogger(__name__) +# ========== Constants ========== +METADATA_READ = "rb" +METADATA_WRITE = "wb" + + # ========== Classes ========== class Hierarchy: """A class for organizing the backup root hierarchy. @@ -24,6 +30,12 @@ class Hierarchy: * path * name * metadata_path + + Methods + ------- + * read_metadata - read this Hierarchy's metadata from a file + and return it + * write_metadata - write this Hierarchy's metadata to a file """ def __init__(self, dest): @@ -77,6 +89,20 @@ class Hierarchy: """ return self.path / ".metadata" + def read_metadata(self): + """Read this repository's metadata from its file and + then return it. + + :rtype: dict + """ + with self.metadata_path.open(mode=METADATA_READ) as mfile: + return pickle.load(mfile) + + def write_metadata(self): + """Write this repository's metadata to its file.""" + with self.metadata_path.open(mode=METADATA_WRITE) as mfile: + pickle.dump(self._data, mfile) + # ========== Functions ========== if __name__ == "__main__": diff --git a/rbackup/hierarchy/repository.py b/rbackup/hierarchy/repository.py index 879cd76..ca931b1 100644 --- a/rbackup/hierarchy/repository.py +++ b/rbackup/hierarchy/repository.py @@ -5,7 +5,6 @@ """ import logging import datetime -import pickle from rbackup.hierarchy.hierarchy import Hierarchy from rbackup.hierarchy.snapshot import Snapshot @@ -16,8 +15,6 @@ syslog = logging.getLogger(__name__) # ========== Constants ========== -METADATA_READ = "rb" -METADATA_WRITE = "wb" DIRMODE = 0o755 FILEMODE = 0o644 @@ -55,7 +52,10 @@ class Repository(Hierarchy): Methods ------- - * create_snapshot() - create a new snapshot, then update current_snapshot + * create_snapshot - create a new snapshot, then update current_snapshot + * gen_snapshot_path - generate a path for a snapshot given by name + * read_metadata (inherited from Hierarchy) + * write_metadata (inherited from Hierarchy) Directory Structure ------------------- @@ -79,25 +79,16 @@ class Repository(Hierarchy): self._snapshot_index = 0 if not self.metadata_path.exists(): + self._data = {"snapshots": [], "current_snapshot": None} self._init_new_repository() else: - self._read_metadata() + self._data = self.read_metadata() def _init_new_repository(self): self.metadata_path.parent.mkdir(mode=DIRMODE, exist_ok=True) self.metadata_path.touch(mode=FILEMODE) - self._data = {"snapshots": [], "current_snapshot": None} - - self._write_metadata() - - def _read_metadata(self): - with self.metadata_path.open(mode=METADATA_READ) as mfile: - self._data = pickle.load(mfile) - - def _write_metadata(self): - with self.metadata_path.open(mode=METADATA_WRITE) as mfile: - pickle.dump(self._data, mfile) + self.write_metadata() def __len__(self): """Return the number of snapshots in this Repository.""" @@ -210,7 +201,12 @@ class Repository(Hierarchy): self._data["current_snapshot"] = Snapshot(path) self._data["snapshots"].append(self._data["current_snapshot"]) - self._write_metadata() + self.write_metadata() + + try: + self._data["current_snapshot"].path.mkdir(mode=DIRMODE, parents=True) + except FileExistsError as e: + raise e syslog.debug("Snapshot created") syslog.debug(f"Snapshot name: {self.current_snapshot.name}") diff --git a/rbackup/hierarchy/snapshot.py b/rbackup/hierarchy/snapshot.py index 7885336..e4449de 100644 --- a/rbackup/hierarchy/snapshot.py +++ b/rbackup/hierarchy/snapshot.py @@ -24,6 +24,11 @@ class Snapshot(Hierarchy): * etc_dir * home_dir * root_home_dir + + Methods + ------- + * read_metadata (inherited from Hierarchy) + * write_metadata (inherited from Hierarchy) """ def __init__(self, path): diff --git a/rbackup/tests/test_repository.py b/rbackup/tests/test_repository.py index 53ae00a..fceb7d2 100644 --- a/rbackup/tests/test_repository.py +++ b/rbackup/tests/test_repository.py @@ -29,18 +29,21 @@ class TestRepositoryPreCreate(unittest.TestCase): self.patched_path = patch.object( Repository, "metadata_path", new_callable=PropertyMock ) + self.patched_r_metadata = patch.object(Repository, "read_metadata") + self.patched_w_metadata = patch.object(Repository, "write_metadata") self.patched_snapshot = patch( f"{TESTING_PACKAGE}.repository.Snapshot", spec_set=Snapshot ) - self.patched_pickle = patch(f"{TESTING_PACKAGE}.repository.pickle") + self.mocked_r_metadata = self.patched_r_metadata.start() + self.mocked_w_metadata = self.patched_w_metadata.start() self.mocked_path = self.patched_path.start() self.mocked_snapshot = self.patched_snapshot.start() self.mocked_pickle = self.patched_pickle.start() @given(lists(builds(Snapshot, text()), unique=True)) def test_empty(self, l): - self.mocked_pickle.load.return_value = { + self.mocked_r_metadata.return_value = { "snapshots": l.copy(), "current_snapshot": l[-1] if l else None, } @@ -53,7 +56,7 @@ class TestRepositoryPreCreate(unittest.TestCase): @given(lists(builds(Snapshot, text()), unique=True)) def test_len(self, l): - self.mocked_pickle.load.return_value = { + self.mocked_r_metadata.return_value = { "snapshots": l.copy(), "current_snapshot": l[-1] if l else None, } @@ -64,15 +67,15 @@ class TestRepositoryPreCreate(unittest.TestCase): @given(lists(builds(Snapshot, text()), unique=True)) def test_current_snapshot(self, l): - self.mocked_pickle.load.return_value = { + self.mocked_r_metadata.return_value = { "snapshots": l.copy(), "current_snapshot": l[-1] if l else None, } if l == []: - self.mocked_pickle.load.return_value["current_snapshot"] = None + self.mocked_r_metadata.return_value["current_snapshot"] = None else: - self.mocked_pickle.load.return_value["current_snapshot"] = l[-1] + self.mocked_r_metadata.return_value["current_snapshot"] = l[-1] repo = Repository("backup") if l == []: @@ -83,8 +86,9 @@ class TestRepositoryPreCreate(unittest.TestCase): def tearDown(self): self.patched_path.stop() + self.patched_r_metadata.stop() + self.patched_w_metadata.stop() self.patched_snapshot.stop() - self.patched_pickle.stop() class TestRepositoryPostCreate(unittest.TestCase): @@ -94,26 +98,28 @@ class TestRepositoryPostCreate(unittest.TestCase): self.patched_path = patch.object( Repository, "metadata_path", new_callable=PropertyMock ) + self.patched_r_metadata = patch.object(Repository, "read_metadata") + self.patched_w_metadata = patch.object(Repository, "write_metadata") self.patched_snapshot = patch( f"{TESTING_PACKAGE}.repository.Snapshot", spec_set=Snapshot ) - self.patched_pickle = patch(f"{TESTING_PACKAGE}.repository.pickle") self.mocked_path = self.patched_path.start() + self.mocked_r_metadata = self.patched_r_metadata.start() + self.mocked_w_metadata = self.patched_w_metadata.start() self.mocked_snapshot = self.patched_snapshot.start() - self.mocked_pickle = self.patched_pickle.start() @given(lists(builds(Snapshot, text()), unique=True)) def test_empty(self, l): - self.mocked_pickle.load.return_value = { + self.mocked_r_metadata.return_value = { "snapshots": l.copy(), "current_snapshot": l[-1] if l else None, } if l == []: - self.mocked_pickle.load.return_value["current_snapshot"] = None + self.mocked_r_metadata.return_value["current_snapshot"] = None else: - self.mocked_pickle.load.return_value["current_snapshot"] = l[-1] + self.mocked_r_metadata.return_value["current_snapshot"] = l[-1] repo = Repository("backup") repo.create_snapshot() @@ -122,7 +128,7 @@ class TestRepositoryPostCreate(unittest.TestCase): @given(lists(builds(Snapshot, text()), unique=True)) def test_len(self, l): - self.mocked_pickle.load.return_value = { + self.mocked_r_metadata.return_value = { "snapshots": l.copy(), "current_snapshot": l[-1] if l else None, } @@ -135,7 +141,7 @@ class TestRepositoryPostCreate(unittest.TestCase): @given(lists(builds(Snapshot, text()), unique=True)) def test_current_snapshot(self, l): - self.mocked_pickle.load.return_value = { + self.mocked_r_metadata.return_value = { "snapshots": l.copy(), "current_snapshot": l[-1] if l else None, } @@ -148,5 +154,6 @@ class TestRepositoryPostCreate(unittest.TestCase): def tearDown(self): self.patched_path.stop() + self.patched_r_metadata.stop() + self.patched_w_metadata.stop() self.patched_snapshot.stop() - self.patched_pickle.stop()