Rename README and hierarchy package to decrease verbosity

This commit is contained in:
Eric Torres 2019-04-09 17:45:38 -07:00
parent 8dcf25920d
commit ea0a629fd9
8 changed files with 71 additions and 35 deletions

View File

View File

@ -1,6 +1,6 @@
""" """
.. author:: Eric Torres .. author:: Eric Torres
.. module:: rbackup.hierarchy.hierarchy .. module:: rbackup.struct.hierarchy
:synopsis: Classes for creating the backup hierarchy. :synopsis: Classes for creating the backup hierarchy.
""" """
import logging import logging

View File

@ -1,13 +1,13 @@
""" """
.. author:: Eric Torres .. author:: Eric Torres
.. module:: rbackup.hierarchy.repository .. module:: rbackup.struct.repository
:synopsis: Class for structuring a backup repository. :synopsis: Class for structuring a backup repository.
""" """
import logging import logging
import datetime import datetime
from rbackup.hierarchy.hierarchy import Hierarchy from rbackup.struct.hierarchy import Hierarchy
from rbackup.hierarchy.snapshot import Snapshot from rbackup.struct.snapshot import Snapshot
# ========== Logging Setup =========== # ========== Logging Setup ===========
@ -26,6 +26,7 @@ class Repository(Hierarchy):
Repository is a mutable, stateful class for representing a Repository is a mutable, stateful class for representing a
directory that contains backup data sequestered into snapshots directory that contains backup data sequestered into snapshots
and a symlink to the most recently created snapshot. and a symlink to the most recently created snapshot.
* Each snapshot in a repository is unaware of one another, * Each snapshot in a repository is unaware of one another,
this is the job of the repository to organize this is the job of the repository to organize
* The only way snapshots are linked together is in files * The only way snapshots are linked together is in files
@ -53,7 +54,6 @@ class Repository(Hierarchy):
Methods 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) * read_metadata (inherited from Hierarchy)
* write_metadata (inherited from Hierarchy) * write_metadata (inherited from Hierarchy)
@ -91,6 +91,41 @@ class Repository(Hierarchy):
self.write_metadata() self.write_metadata()
def _is_duplicate_name(self, name):
"""Check whether or not a snapshot of a given name is already
on this Repository.
If the repository is empty, then this method always returns False.
:param name: the name to check for
:returns: True if this name is already in a snapshot.
:type name: str
:rtype: bool
"""
for s in self._data["snapshots"]:
if name == s.name:
return True
return False
def _is_valid_name(self, name):
"""Check if the given name is a valid name. If it is a duplicate,
log a warning. If it is invalid, raise a ValueError.
Invalid Names:
--------------
* Contain slashes
* Are empty values i.e. '' or []
:param name: name to validate
:type name: str
:returns: true if this name is deemed valid
:rtype: bool
"""
if not str(name) or "/" in name:
return False
else:
return True
def __len__(self): def __len__(self):
"""Return the number of snapshots in this Repository.""" """Return the number of snapshots in this Repository."""
return len(self._data["snapshots"]) return len(self._data["snapshots"])
@ -128,19 +163,6 @@ class Repository(Hierarchy):
""" """
return self.path / "data" return self.path / "data"
def gen_snapshot_path(self, name):
"""Generate a path for a Snapshot by name.
:param name: name of the Snapshot
:type name: str or path-like object
:rtype: path-like object
:raises: ValueError if name contains slashes
"""
if "/" in str(name):
raise ValueError("Names cannot contain slashes")
return self.snapshot_dir / name
@property @property
def snapshots(self): def snapshots(self):
"""Return a list of snapshots stored in this Repository. """Return a list of snapshots stored in this Repository.
@ -167,16 +189,21 @@ class Repository(Hierarchy):
""" """
return self._data["current_snapshot"] return self._data["current_snapshot"]
# TODO search for the name of snapshots
# add ability to use 'in' operator
def create_snapshot(self, name=None): def create_snapshot(self, name=None):
"""Create a new snapshot in this repository. """Create a new snapshot in this repository.
This method is non-intrusive in that it will not This method is non-intrusive in that it will not
make any changes in the filesystem when called. make any changes in the filesystem when called.
If name is given and it is the name of a snapshot already
on the repository, that snapshot is overwritten instead.
:param name: the name of the snapshot :param name: the name of the snapshot
:type name: str :type name: str
:return: a new Snapshot object :return: a new Snapshot object
:raises: FileExistsError if snapshot directory already exists :raises: ValueError if name is an invalid value
""" """
syslog.debug("Creating snapshot") syslog.debug("Creating snapshot")
@ -185,15 +212,20 @@ class Repository(Hierarchy):
if name is not None if name is not None
else datetime.datetime.utcnow().isoformat().replace(":", "_") else datetime.datetime.utcnow().isoformat().replace(":", "_")
) )
self._data["current_snapshot"] = Snapshot(self.gen_snapshot_path(snapshot_name))
self._data["snapshots"].append(self._data["current_snapshot"]) if not self._is_valid_name(snapshot_name):
raise ValueError(f"{name} is an invalid name")
elif self._is_duplicate_name(snapshot_name):
syslog.warning("Snapshot already exists, data will be overwritten.")
else:
self._data["current_snapshot"] = Snapshot(self.snapshot_dir / snapshot_name)
self._data["snapshots"].append(self._data["current_snapshot"])
self.write_metadata() self.write_metadata()
try: self._data["current_snapshot"].path.mkdir(
self._data["current_snapshot"].path.mkdir(mode=DIRMODE, parents=True) mode=DIRMODE, parents=True, exist_ok=True
except FileExistsError as e: )
raise e
syslog.debug("Snapshot created") syslog.debug("Snapshot created")
syslog.debug(f"Snapshot name: {self.current_snapshot.name}") syslog.debug(f"Snapshot name: {self.current_snapshot.name}")

View File

@ -1,11 +1,11 @@
""" """
.. author:: Eric Torres .. author:: Eric Torres
.. module:: rbackup.hierarchy.snapshot .. module:: rbackup.struct.snapshot
:synopsis: Classes for creating the backup hierarchy. :synopsis: Classes for creating the backup hierarchy.
""" """
import logging import logging
from rbackup.hierarchy.hierarchy import Hierarchy from rbackup.struct.hierarchy import Hierarchy
# ========== Logging Setup =========== # ========== Logging Setup ===========
@ -32,6 +32,10 @@ class Snapshot(Hierarchy):
"""Default constructor for the Snapshot class.""" """Default constructor for the Snapshot class."""
super().__init__(path) super().__init__(path)
def __repr__(self):
"""Return a string representation of this Snapshot."""
return f"{self.__class__.__name__}('{self.name}')"
@property @property
def pkg_dir(self): def pkg_dir(self):
"""Retrieve the package manager backup directory of this snapshot. """Retrieve the package manager backup directory of this snapshot.

View File

@ -4,10 +4,10 @@ import unittest
from hypothesis import given from hypothesis import given
from hypothesis.strategies import booleans, characters, iterables, one_of, none, text from hypothesis.strategies import booleans, characters, iterables, one_of, none, text
from pathlib import Path from pathlib import Path
from rbackup.hierarchy.hierarchy import Hierarchy from rbackup.struct.hierarchy import Hierarchy
# ========== Constants ========== # ========== Constants ==========
TESTING_MODULE = "rbackup.hierarchy.hierarchy" TESTING_MODULE = "rbackup.struct.struct"
# ========== Functions ========== # ========== Functions ==========

View File

@ -4,12 +4,12 @@ import unittest
from hypothesis import given from hypothesis import given
from hypothesis.strategies import builds, lists, text from hypothesis.strategies import builds, lists, text
from pathlib import Path from pathlib import Path
from rbackup.hierarchy.repository import Repository from rbackup.struct.repository import Repository
from rbackup.hierarchy.snapshot import Snapshot from rbackup.struct.snapshot import Snapshot
from unittest.mock import PropertyMock, patch from unittest.mock import MagicMock, PropertyMock, patch
# ========== Constants ========== # ========== Constants ==========
TESTING_PACKAGE = "rbackup.hierarchy" TESTING_PACKAGE = "rbackup.struct"
REPO_MODULE = f"{TESTING_PACKAGE}.repository" REPO_MODULE = f"{TESTING_PACKAGE}.repository"
SS_MODULE = f"{TESTING_PACKAGE}.snapshot" SS_MODULE = f"{TESTING_PACKAGE}.snapshot"

View File

@ -6,10 +6,10 @@ Unit tests for the Snapshot class.
import doctest import doctest
import unittest import unittest
from rbackup.hierarchy.snapshot import Snapshot from rbackup.struct.snapshot import Snapshot
# ========== Constants ========== # ========== Constants ==========
TESTING_MODULE = "rbackup.hierarchy.snapshot" TESTING_MODULE = "rbackup.struct.snapshot"
# ========== Functions ========== # ========== Functions ==========