Move metadata handling to the Hierarchy class

This commit is contained in:
Eric Torres 2019-03-30 14:13:10 -07:00
parent 874f94c5fc
commit 5cca10a12b
4 changed files with 66 additions and 32 deletions

View File

@ -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__":

View File

@ -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}")

View File

@ -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):

View File

@ -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()