Docstring cleanups for documentation
This commit is contained in:
parent
2155cc4b7a
commit
386b200e9d
@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
.. :author:: Eric Torres
|
.. :author:: Eric Torres
|
||||||
.. :module:: rbackup.config
|
.. :module:: rbackup.config
|
||||||
.. :synopsis: Functions for handling config files.
|
:synopsis: Functions for handling config files.
|
||||||
"""
|
"""
|
||||||
import configparser
|
import configparser
|
||||||
import logging
|
import logging
|
||||||
@ -45,7 +45,7 @@ def merge_files(files):
|
|||||||
|
|
||||||
Any files included that do not exist send a warning to the log.
|
Any files included that do not exist send a warning to the log.
|
||||||
|
|
||||||
>>> merge_files(get_files_by_suffix('')) # doctest: +ELLIPSIS
|
>>> merge_files(get_files_by_suffix('-include.conf')) # doctest: +ELLIPSIS
|
||||||
PosixPath('/tmp/...')
|
PosixPath('/tmp/...')
|
||||||
|
|
||||||
:param files: files including paths to read from
|
:param files: files including paths to read from
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
.. author:: Eric Torres
|
.. moduleauthor:: Eric Torres
|
||||||
.. module:: rbackup.packagemanager
|
.. module:: rbackup.package_managers.packagemanager
|
||||||
:synopsis: Module for package manager plugins
|
:synopsis: Module for package manager plugins
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
@ -41,8 +41,8 @@ class PackageManager:
|
|||||||
it is to be assumed that no file was created, therefore there
|
it is to be assumed that no file was created, therefore there
|
||||||
is no file to cleanup.
|
is no file to cleanup.
|
||||||
|
|
||||||
Note that this method is internal and is
|
.. note:: This method is internal and is meant to be called from
|
||||||
meant to be called from a subclass in a separate module.
|
a subclass in a separate module.
|
||||||
|
|
||||||
:returns: path to temporary file
|
:returns: path to temporary file
|
||||||
:rtype: path-like object
|
:rtype: path-like object
|
||||||
@ -63,12 +63,12 @@ class PackageManager:
|
|||||||
def gen_db_archive(self, compress=None):
|
def gen_db_archive(self, compress=None):
|
||||||
"""Generate a database archive for this package manager.
|
"""Generate a database archive for this package manager.
|
||||||
|
|
||||||
Note that this method is internal and is
|
|
||||||
meant to be called from a subclass in a separate module.
|
|
||||||
|
|
||||||
All arguments and keyword-only arguments are passed directly
|
All arguments and keyword-only arguments are passed directly
|
||||||
to the PackageManager object.
|
to the PackageManager object.
|
||||||
|
|
||||||
|
.. note:: This method is internal and is meant to be called from
|
||||||
|
a subclass in a separate module.
|
||||||
|
|
||||||
:param compress: compression mode
|
:param compress: compression mode
|
||||||
:type compress: str
|
:type compress: str
|
||||||
:returns: the path to the created file
|
:returns: the path to the created file
|
||||||
@ -95,24 +95,24 @@ class PackageManager:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def cache_directory(self):
|
def cache_directory(self):
|
||||||
"""Return the cache directory of this package manager.
|
"""
|
||||||
|
:returns: the cache directory of this package manager.
|
||||||
:rtype: path-like object
|
:rtype: path-like object
|
||||||
"""
|
"""
|
||||||
return self._cachedir
|
return self._cachedir
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def database_path(self):
|
def database_path(self):
|
||||||
"""Return the database path of this package manager.
|
"""
|
||||||
|
:returns: the database path of this package manager.
|
||||||
:rtype: path-like object
|
:rtype: path-like object
|
||||||
"""
|
"""
|
||||||
return self._db_path
|
return self._db_path
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def pkglist_cmd(self):
|
def pkglist_cmd(self):
|
||||||
"""Return the package listing command of this package manager.
|
"""
|
||||||
|
:returns: the package listing command of this package manager.
|
||||||
:rtype: iterable or str
|
:rtype: iterable or str
|
||||||
"""
|
"""
|
||||||
return self._pkglist_cmd
|
return self._pkglist_cmd
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
.. author:: Eric Torres
|
.. moduleauthor:: Eric Torres
|
||||||
.. module:: rbackup.package_managers.pacman
|
.. module:: rbackup.package_managers.pacman
|
||||||
:synopsis: Implementation class for the Pacman package manager.
|
:synopsis: Implementation class for the Pacman package manager.
|
||||||
"""
|
"""
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
.. author:: Eric Torres
|
.. moduleauthor:: Eric Torres
|
||||||
.. module:: rbackup.rsync
|
.. module:: rbackup.rsync
|
||||||
:synopsis: helper functions for running the rsync backend
|
:synopsis: helper functions for running the rsync backend
|
||||||
"""
|
"""
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
.. author:: Eric Torres
|
.. moduleauthor:: Eric Torres
|
||||||
.. module:: rbackup.struct.hierarchy
|
.. module:: rbackup.struct.hierarchy
|
||||||
:synopsis: Classes for creating the backup hierarchy.
|
:synopsis: Classes for creating the backup hierarchy.
|
||||||
"""
|
"""
|
||||||
@ -22,23 +22,10 @@ class Hierarchy(PathLike):
|
|||||||
"""A class for organizing the backup root hierarchy.
|
"""A class for organizing the backup root hierarchy.
|
||||||
|
|
||||||
Upon creation of a Hierarchy object, it is up to the caller
|
Upon creation of a Hierarchy object, it is up to the caller
|
||||||
to call either shutil.mkdir() or a related method to create
|
to call either :func:`shutil.mkdir` or a related method to create
|
||||||
the directory structure it emulates.
|
the directory structure it emulates.
|
||||||
|
|
||||||
For consistency, Hierarchy objects always store and return absolute paths.
|
For consistency, ``Hierarchy`` objects always store and return absolute paths.
|
||||||
|
|
||||||
Attributes
|
|
||||||
----------
|
|
||||||
* Hierarchy.path
|
|
||||||
* Hierarchy.name
|
|
||||||
* Hierarchy.metadata_path
|
|
||||||
|
|
||||||
Methods
|
|
||||||
-------
|
|
||||||
* gen_metadata - generate the metadata for this Hierarchy
|
|
||||||
* 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):
|
def __init__(self, dest):
|
||||||
@ -60,30 +47,31 @@ class Hierarchy(PathLike):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self):
|
def path(self):
|
||||||
"""Return the base directory of this hierarchy.
|
"""
|
||||||
|
:returns: the base directory of this hierarchy
|
||||||
:rtype: path-like object
|
:rtype: path-like object
|
||||||
"""
|
"""
|
||||||
return self._path
|
return self._path
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of this hierarchy.
|
"""
|
||||||
|
:returns: the name of this hierarchy.
|
||||||
:rtype: str
|
:rtype: str
|
||||||
"""
|
"""
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def metadata_path(self):
|
def metadata_path(self):
|
||||||
"""Return the path of this hierarchy's metadata file.
|
"""
|
||||||
|
:returns: the path of this hierarchy's metadata file.
|
||||||
:rtype: path-like object
|
:rtype: path-like object
|
||||||
"""
|
"""
|
||||||
return self._metadata_path
|
return self._metadata_path
|
||||||
|
|
||||||
def gen_metadata(self):
|
def gen_metadata(self):
|
||||||
"""Generate metadata for this repository.
|
"""Generate metadata for this repository.
|
||||||
|
|
||||||
After this method is called, the data necessary for this hierarchy has been created.
|
After this method is called, the data necessary for this hierarchy has been created.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError("This method must be called in a child class.")
|
raise NotImplementedError("This method must be called in a child class.")
|
||||||
@ -99,11 +87,12 @@ class Hierarchy(PathLike):
|
|||||||
return json.load(mfile)
|
return json.load(mfile)
|
||||||
|
|
||||||
def write_metadata(self, attr):
|
def write_metadata(self, attr):
|
||||||
"""Write this repository's metadata to its file.
|
"""Write this repository's metadata to its metadata file.
|
||||||
Note that this write operation is atomic to the caller.
|
|
||||||
|
|
||||||
:param attr: data to write to file
|
.. note:: This write operation is atomic to the caller.
|
||||||
:type attr: class member to write
|
|
||||||
|
:param attr: class data to write to file
|
||||||
|
:type attr: any type
|
||||||
"""
|
"""
|
||||||
syslog.debug(f"Writing metadata to {self.metadata_path}")
|
syslog.debug(f"Writing metadata to {self.metadata_path}")
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
.. author:: Eric Torres
|
.. moduleauthor:: Eric Torres
|
||||||
.. module:: rbackup.struct.repository
|
.. module:: rbackup.struct.repository
|
||||||
|
:synopsis: Classes for structuring a backup repository.
|
||||||
:synopsis: Module for helpers for structuring a backup repository.
|
|
||||||
"""
|
"""
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
@ -31,56 +30,58 @@ class Repository(Hierarchy):
|
|||||||
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.
|
||||||
|
|
||||||
|
Properties
|
||||||
|
|
||||||
* 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
|
||||||
that are hard-linked together
|
that are hard-linked together
|
||||||
|
|
||||||
Attributes
|
Snapshots can be accessed on a one-by-one basis through iteration.
|
||||||
----------
|
|
||||||
* Repository.path (inherited from Hierarchy)
|
|
||||||
* Repository.name (inherited from Hierarchy)
|
|
||||||
* Repository.metadata_path (inherited from Hierarchy)
|
|
||||||
* Repository.snapshots - a list of snapshots stored in this repository
|
|
||||||
* Repository.snapshot_dir - the snapshot storage location of this repository
|
|
||||||
|
|
||||||
Methods
|
::
|
||||||
-------
|
|
||||||
* cleanup - clean all repository data
|
|
||||||
* create_snapshot - create a new snapshot
|
|
||||||
* gen_metadata (inherited from Hierarchy)
|
|
||||||
* is_valid_snapshot_name - validate a potential name for a snapshot
|
|
||||||
* read_metadata (inherited from Hierarchy)
|
|
||||||
* write_metadata (inherited from Hierarchy)
|
|
||||||
|
|
||||||
Directory Structure
|
>>> for snapshot in Repository('backup'):
|
||||||
-------------------
|
>>> print(snapshot.path)
|
||||||
* "data" directory for storing snapshots
|
first
|
||||||
* Each snapshot is its own directory with its own sub-hierarchy
|
second
|
||||||
* Each snapshot has an "old" directory for storing deleted data
|
...
|
||||||
* rsync hardlinks unchanged files between snapshots
|
|
||||||
* A symlink in the root of the repository symlinking to the
|
|
||||||
most recent snapshot
|
|
||||||
|
|
||||||
Iteration
|
Snapshots on repositories can be retrieved by index using python's
|
||||||
---------
|
list slicing syntax.
|
||||||
To support checking all snapshots for hardlinking, the Repository class
|
|
||||||
can be iterated through.
|
::
|
||||||
|
|
||||||
|
>>> print(Repository('backup')[:])
|
||||||
|
[Snapshot(...), ...]
|
||||||
|
|
||||||
|
Membership of a snapshot in a repository can be checked by name.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
>>> Repository('backup').create_snapshot('test')
|
||||||
|
>>> 'test' in Repository('backup')
|
||||||
|
True
|
||||||
|
|
||||||
|
Number of snapshots in a repository can be checked as well
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
>>> Repository('backup').create_snapshot()
|
||||||
|
>>> len(Repository('backup'))
|
||||||
|
1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
"""Snapshots are serialized as their names relative to the repository
|
"""Snapshots are serialized as their names relative to the repository
|
||||||
data directory, but have their full paths during runtime.
|
data directory, but have their full paths during runtime.
|
||||||
|
|
||||||
Private Attributes
|
Private Attributes
|
||||||
------------------
|
|
||||||
* _snapshots - list of Snapshot objects created and accessed at runtime
|
* _snapshots - list of Snapshot objects created and accessed at runtime
|
||||||
* _snapshot_metadata - list of Snapshot names serialized and deserialized
|
* _snapshot_metadata - list of Snapshot names serialized and deserialized
|
||||||
when this Repository is first created
|
when this Repository is first created
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, dest):
|
def __init__(self, dest):
|
||||||
"""Default constructor for the Repository class.
|
"""Default constructor for the Repository class."""
|
||||||
"""
|
|
||||||
super().__init__(dest)
|
super().__init__(dest)
|
||||||
|
|
||||||
if self.metadata_path.exists():
|
if self.metadata_path.exists():
|
||||||
@ -95,8 +96,9 @@ class Repository(Hierarchy):
|
|||||||
self._snapshot_iterator = iter(self._snapshots)
|
self._snapshot_iterator = iter(self._snapshots)
|
||||||
|
|
||||||
def __contains__(self, name):
|
def __contains__(self, name):
|
||||||
"""Check whether a Snapshot is in this Repository by name.
|
"""Check membership of a Snapshot in this Repository by name.
|
||||||
|
|
||||||
|
:returns: True if name is the name of a Snapshot in this Repository
|
||||||
:type name: str
|
:type name: str
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
@ -126,43 +128,43 @@ class Repository(Hierarchy):
|
|||||||
"""Check if the given name is a valid name.
|
"""Check if the given name is a valid name.
|
||||||
|
|
||||||
Invalid Names:
|
Invalid Names:
|
||||||
--------------
|
|
||||||
* Contain slashes
|
* Contain slashes
|
||||||
* Are empty values
|
* Are empty values
|
||||||
|
|
||||||
Valid names match the regex
|
Valid names:
|
||||||
r'[\\w]+[^/]*'
|
|
||||||
|
* Match the regex r'[\\w]+[^/]*'
|
||||||
|
|
||||||
:param name: name to validate
|
:param name: name to validate
|
||||||
:type name: str
|
:type name: str
|
||||||
:returns: true if this name is deemed valid
|
:returns: true if this name is deemed valid, otherwise False
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
return bool(re.match(VALID_SNAPSHOT_NAME, name))
|
return bool(re.match(VALID_SNAPSHOT_NAME, name))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def snapshot_dir(self):
|
def snapshot_dir(self):
|
||||||
"""Return the directory in this Repository in which snapshots
|
"""
|
||||||
|
:returns: the directory in this Repository in which snapshots
|
||||||
are stored.
|
are stored.
|
||||||
|
|
||||||
:rtype: path-like object
|
:rtype: path-like object
|
||||||
"""
|
"""
|
||||||
return self.path / "data"
|
return self.path / "data"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def snapshots(self):
|
def snapshots(self):
|
||||||
"""Return a list of snapshots stored in this Repository.
|
"""
|
||||||
|
:returns: all snapshots stored in this repository
|
||||||
:returns: the names of all snapshots in this repository sorted by
|
|
||||||
date
|
|
||||||
:rtype: list of Snapshot objects
|
:rtype: list of Snapshot objects
|
||||||
"""
|
"""
|
||||||
return self._snapshots
|
return self._snapshots
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def empty(self):
|
def empty(self):
|
||||||
"""Determine whether or not this Repository is empty.
|
"""
|
||||||
|
:returns: True if there are no Snapshots in this Repository,
|
||||||
|
False otherwise
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
return not self.snapshots
|
return not self.snapshots
|
||||||
@ -179,9 +181,14 @@ class Repository(Hierarchy):
|
|||||||
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 operation 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 not given, then the new snapshot's name is the current
|
||||||
|
UTC date in ISO format.
|
||||||
|
|
||||||
|
If name is given, then it is the name for the new snapshot.
|
||||||
|
|
||||||
If name is given and it is the name of a snapshot already
|
If name is given and it is the name of a snapshot already
|
||||||
on the repository, that snapshot is overwritten instead.
|
on the repository, that snapshot is overwritten instead.
|
||||||
|
|
||||||
@ -221,7 +228,7 @@ class Repository(Hierarchy):
|
|||||||
|
|
||||||
:param remove_snapshots: delete the data directory of this repository
|
:param remove_snapshots: delete the data directory of this repository
|
||||||
:type remove_snapshots: bool
|
:type remove_snapshots: bool
|
||||||
:param remove_repo_dir: remove the top-directory level of this repository
|
:param remove_repo_dir: remove the top-level directory of this repository
|
||||||
:type remove_repo_dir: bool
|
:type remove_repo_dir: bool
|
||||||
"""
|
"""
|
||||||
# We don't want to risk symlink attacks
|
# We don't want to risk symlink attacks
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
.. author:: Eric Torres
|
.. moduleauthor:: Eric Torres
|
||||||
.. module:: rbackup.struct.snapshot
|
.. module:: rbackup.struct.snapshot
|
||||||
:synopsis: Classes for creating the backup hierarchy.
|
:synopsis: Classes for creating the backup hierarchy.
|
||||||
"""
|
"""
|
||||||
@ -14,18 +14,12 @@ syslog = logging.getLogger(__name__)
|
|||||||
# ========== Classes ==========
|
# ========== Classes ==========
|
||||||
class Snapshot(Hierarchy):
|
class Snapshot(Hierarchy):
|
||||||
"""Hierarchy for a single snapshot.
|
"""Hierarchy for a single snapshot.
|
||||||
Attributes
|
|
||||||
----------
|
|
||||||
* Snapshot.path (inherited from Hierarchy)
|
|
||||||
* Snapshot.name (inherited from Hierarchy)
|
|
||||||
* Snapshot.metadata_path (inherited from Hierarchy)
|
|
||||||
* Snapshot.pkg_dir
|
|
||||||
|
|
||||||
Methods
|
Data from each run of a backup script is intended to go here.
|
||||||
-------
|
|
||||||
* gen_metadata (inherited from Hierarchy)
|
Snapshots are unaware of one another, it is up to a third-party caller
|
||||||
* read_metadata (inherited from Hierarchy)
|
to orchestrate operations such as hardlinking between snapshots and
|
||||||
* write_metadata (inherited from Hierarchy)
|
ordering snapshots.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
@ -40,16 +34,13 @@ class Snapshot(Hierarchy):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def pkg_dir(self):
|
def pkg_dir(self):
|
||||||
"""Retrieve the package manager backup directory of this snapshot.
|
"""
|
||||||
|
:returns: the package manager backup directory of this snapshot.
|
||||||
:rtype: path-like object
|
:rtype: path-like object
|
||||||
"""
|
"""
|
||||||
return self._pkg_dir
|
return self._pkg_dir
|
||||||
|
|
||||||
def gen_metadata(self):
|
def gen_metadata(self):
|
||||||
"""Generate metadata for this repository.
|
|
||||||
After this method is called, the data necessary for this snapshot has been created.
|
|
||||||
"""
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
.. author:: Eric Torres
|
.. moduleauthor:: Eric Torres
|
||||||
|
|
||||||
Tests for the rbackup.config module.
|
Tests for the rbackup.config module.
|
||||||
"""
|
"""
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
.. author:: Eric Torres
|
.. moduleauthor:: Eric Torres
|
||||||
|
|
||||||
Tests for the rbackup.struct.hierarchy module.
|
Tests for the rbackup.struct.hierarchy module.
|
||||||
"""
|
"""
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
.. author:: Eric Torres
|
.. moduleauthor:: Eric Torres
|
||||||
:synopsis: Unit tests for the PackageManager module.
|
:synopsis: Unit tests for the PackageManager module.
|
||||||
"""
|
"""
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
.. author:: Eric Torres
|
.. moduleauthor:: Eric Torres
|
||||||
|
|
||||||
Tests for the rbackup.struct.repository module.
|
Tests for the rbackup.struct.repository module.
|
||||||
"""
|
"""
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
.. author:: Eric Torres
|
.. moduleauthor:: Eric Torres
|
||||||
|
|
||||||
Unit tests for the rbackup.struct.snapshot module.
|
Unit tests for the rbackup.struct.snapshot module.
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user