Move metadata handling to the Hierarchy class
This commit is contained in:
parent
874f94c5fc
commit
5cca10a12b
@ -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__":
|
||||
|
@ -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}")
|
||||
|
@ -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):
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user