Docstring cleanups for documentation
This commit is contained in:
parent
2155cc4b7a
commit
386b200e9d
@ -1,7 +1,7 @@
|
||||
"""
|
||||
.. :author:: Eric Torres
|
||||
.. :module:: rbackup.config
|
||||
.. :synopsis: Functions for handling config files.
|
||||
:synopsis: Functions for handling config files.
|
||||
"""
|
||||
import configparser
|
||||
import logging
|
||||
@ -45,7 +45,7 @@ def merge_files(files):
|
||||
|
||||
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/...')
|
||||
|
||||
:param files: files including paths to read from
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
.. author:: Eric Torres
|
||||
.. module:: rbackup.packagemanager
|
||||
:synopsis: Module for package manager plugins
|
||||
.. moduleauthor:: Eric Torres
|
||||
.. module:: rbackup.package_managers.packagemanager
|
||||
:synopsis: Module for package manager plugins
|
||||
"""
|
||||
import logging
|
||||
import subprocess
|
||||
@ -41,8 +41,8 @@ class PackageManager:
|
||||
it is to be assumed that no file was created, therefore there
|
||||
is no file to cleanup.
|
||||
|
||||
Note that this method is internal and is
|
||||
meant to be called from a subclass in a separate module.
|
||||
.. note:: This method is internal and is meant to be called from
|
||||
a subclass in a separate module.
|
||||
|
||||
:returns: path to temporary file
|
||||
:rtype: path-like object
|
||||
@ -63,12 +63,12 @@ class PackageManager:
|
||||
def gen_db_archive(self, compress=None):
|
||||
"""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
|
||||
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
|
||||
:type compress: str
|
||||
:returns: the path to the created file
|
||||
@ -95,24 +95,24 @@ class PackageManager:
|
||||
|
||||
@property
|
||||
def cache_directory(self):
|
||||
"""Return the cache directory of this package manager.
|
||||
|
||||
"""
|
||||
:returns: the cache directory of this package manager.
|
||||
:rtype: path-like object
|
||||
"""
|
||||
return self._cachedir
|
||||
|
||||
@property
|
||||
def database_path(self):
|
||||
"""Return the database path of this package manager.
|
||||
|
||||
"""
|
||||
:returns: the database path of this package manager.
|
||||
:rtype: path-like object
|
||||
"""
|
||||
return self._db_path
|
||||
|
||||
@property
|
||||
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
|
||||
"""
|
||||
return self._pkglist_cmd
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
.. author:: Eric Torres
|
||||
.. moduleauthor:: Eric Torres
|
||||
.. module:: rbackup.package_managers.pacman
|
||||
:synopsis: Implementation class for the Pacman package manager.
|
||||
:synopsis: Implementation class for the Pacman package manager.
|
||||
"""
|
||||
from rbackup.package_managers.packagemanager import PackageManager
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
.. author:: Eric Torres
|
||||
.. moduleauthor:: Eric Torres
|
||||
.. module:: rbackup.rsync
|
||||
:synopsis: helper functions for running the rsync backend
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
.. author:: Eric Torres
|
||||
.. moduleauthor:: Eric Torres
|
||||
.. module:: rbackup.struct.hierarchy
|
||||
:synopsis: Classes for creating the backup hierarchy.
|
||||
:synopsis: Classes for creating the backup hierarchy.
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
@ -22,23 +22,10 @@ class Hierarchy(PathLike):
|
||||
"""A class for organizing the backup root hierarchy.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
For consistency, ``Hierarchy`` objects always store and return absolute paths.
|
||||
"""
|
||||
|
||||
def __init__(self, dest):
|
||||
@ -60,30 +47,31 @@ class Hierarchy(PathLike):
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
"""Return the base directory of this hierarchy.
|
||||
|
||||
"""
|
||||
:returns: the base directory of this hierarchy
|
||||
:rtype: path-like object
|
||||
"""
|
||||
return self._path
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of this hierarchy.
|
||||
|
||||
"""
|
||||
:returns: the name of this hierarchy.
|
||||
:rtype: str
|
||||
"""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
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
|
||||
"""
|
||||
return self._metadata_path
|
||||
|
||||
def gen_metadata(self):
|
||||
"""Generate metadata for this repository.
|
||||
|
||||
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.")
|
||||
@ -99,11 +87,12 @@ class Hierarchy(PathLike):
|
||||
return json.load(mfile)
|
||||
|
||||
def write_metadata(self, attr):
|
||||
"""Write this repository's metadata to its file.
|
||||
Note that this write operation is atomic to the caller.
|
||||
"""Write this repository's metadata to its metadata file.
|
||||
|
||||
:param attr: data to write to file
|
||||
:type attr: class member to write
|
||||
.. note:: This write operation is atomic to the caller.
|
||||
|
||||
:param attr: class data to write to file
|
||||
:type attr: any type
|
||||
"""
|
||||
syslog.debug(f"Writing metadata to {self.metadata_path}")
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
"""
|
||||
.. author:: Eric Torres
|
||||
.. moduleauthor:: Eric Torres
|
||||
.. module:: rbackup.struct.repository
|
||||
|
||||
:synopsis: Module for helpers for structuring a backup repository.
|
||||
:synopsis: Classes for structuring a backup repository.
|
||||
"""
|
||||
import datetime
|
||||
import logging
|
||||
@ -27,60 +26,62 @@ VALID_SNAPSHOT_NAME = r"[\w._+-]+[^/]*"
|
||||
class Repository(Hierarchy):
|
||||
"""A class for interacting with a backup repository.
|
||||
|
||||
Repository is a mutable, stateful class for representing a
|
||||
directory that contains backup data sequestered into snapshots
|
||||
and a symlink to the most recently created snapshot.
|
||||
Repository is a mutable, stateful class for representing a
|
||||
directory that contains backup data sequestered into snapshots
|
||||
and a symlink to the most recently created snapshot.
|
||||
|
||||
Properties
|
||||
|
||||
* Each snapshot in a repository is unaware of one another,
|
||||
this is the job of the repository to organize
|
||||
* The only way snapshots are linked together is in files
|
||||
that are hard-linked together
|
||||
|
||||
Attributes
|
||||
----------
|
||||
* 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
|
||||
Snapshots can be accessed on a one-by-one basis through iteration.
|
||||
|
||||
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
|
||||
-------------------
|
||||
* "data" directory for storing snapshots
|
||||
* Each snapshot is its own directory with its own sub-hierarchy
|
||||
* 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
|
||||
>>> for snapshot in Repository('backup'):
|
||||
>>> print(snapshot.path)
|
||||
first
|
||||
second
|
||||
...
|
||||
|
||||
Iteration
|
||||
---------
|
||||
To support checking all snapshots for hardlinking, the Repository class
|
||||
can be iterated through.
|
||||
Snapshots on repositories can be retrieved by index using python's
|
||||
list slicing syntax.
|
||||
|
||||
::
|
||||
|
||||
>>> 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
|
||||
data directory, but have their full paths during runtime.
|
||||
|
||||
Private Attributes
|
||||
------------------
|
||||
* _snapshots - list of Snapshot objects created and accessed at runtime
|
||||
* _snapshot_metadata - list of Snapshot names serialized and deserialized
|
||||
when this Repository is first created
|
||||
"""
|
||||
|
||||
def __init__(self, dest):
|
||||
"""Default constructor for the Repository class.
|
||||
"""
|
||||
"""Default constructor for the Repository class."""
|
||||
super().__init__(dest)
|
||||
|
||||
if self.metadata_path.exists():
|
||||
@ -95,8 +96,9 @@ class Repository(Hierarchy):
|
||||
self._snapshot_iterator = iter(self._snapshots)
|
||||
|
||||
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
|
||||
:rtype: bool
|
||||
"""
|
||||
@ -126,43 +128,43 @@ class Repository(Hierarchy):
|
||||
"""Check if the given name is a valid name.
|
||||
|
||||
Invalid Names:
|
||||
--------------
|
||||
|
||||
* Contain slashes
|
||||
* Are empty values
|
||||
|
||||
Valid names match the regex
|
||||
r'[\\w]+[^/]*'
|
||||
Valid names:
|
||||
|
||||
* Match the regex r'[\\w]+[^/]*'
|
||||
|
||||
:param name: name to validate
|
||||
:type name: str
|
||||
:returns: true if this name is deemed valid
|
||||
:returns: true if this name is deemed valid, otherwise False
|
||||
:rtype: bool
|
||||
"""
|
||||
return bool(re.match(VALID_SNAPSHOT_NAME, name))
|
||||
|
||||
@property
|
||||
def snapshot_dir(self):
|
||||
"""Return the directory in this Repository in which snapshots
|
||||
are stored.
|
||||
|
||||
"""
|
||||
:returns: the directory in this Repository in which snapshots
|
||||
are stored.
|
||||
:rtype: path-like object
|
||||
"""
|
||||
return self.path / "data"
|
||||
|
||||
@property
|
||||
def snapshots(self):
|
||||
"""Return a list of snapshots stored in this Repository.
|
||||
|
||||
:returns: the names of all snapshots in this repository sorted by
|
||||
date
|
||||
"""
|
||||
:returns: all snapshots stored in this repository
|
||||
:rtype: list of Snapshot objects
|
||||
"""
|
||||
return self._snapshots
|
||||
|
||||
@property
|
||||
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
|
||||
"""
|
||||
return not self.snapshots
|
||||
@ -179,9 +181,14 @@ class Repository(Hierarchy):
|
||||
def create_snapshot(self, name=None):
|
||||
"""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.
|
||||
|
||||
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
|
||||
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
|
||||
: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
|
||||
"""
|
||||
# We don't want to risk symlink attacks
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
.. author:: Eric Torres
|
||||
.. moduleauthor:: Eric Torres
|
||||
.. module:: rbackup.struct.snapshot
|
||||
:synopsis: Classes for creating the backup hierarchy.
|
||||
"""
|
||||
@ -14,18 +14,12 @@ syslog = logging.getLogger(__name__)
|
||||
# ========== Classes ==========
|
||||
class Snapshot(Hierarchy):
|
||||
"""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
|
||||
-------
|
||||
* gen_metadata (inherited from Hierarchy)
|
||||
* read_metadata (inherited from Hierarchy)
|
||||
* write_metadata (inherited from Hierarchy)
|
||||
Data from each run of a backup script is intended to go here.
|
||||
|
||||
Snapshots are unaware of one another, it is up to a third-party caller
|
||||
to orchestrate operations such as hardlinking between snapshots and
|
||||
ordering snapshots.
|
||||
"""
|
||||
|
||||
def __init__(self, path):
|
||||
@ -40,16 +34,13 @@ class Snapshot(Hierarchy):
|
||||
|
||||
@property
|
||||
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
|
||||
"""
|
||||
return self._pkg_dir
|
||||
|
||||
def gen_metadata(self):
|
||||
"""Generate metadata for this repository.
|
||||
After this method is called, the data necessary for this snapshot has been created.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
.. author:: Eric Torres
|
||||
.. moduleauthor:: Eric Torres
|
||||
|
||||
Tests for the rbackup.config module.
|
||||
"""
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
.. author:: Eric Torres
|
||||
.. moduleauthor:: Eric Torres
|
||||
|
||||
Tests for the rbackup.struct.hierarchy module.
|
||||
"""
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
.. author:: Eric Torres
|
||||
.. moduleauthor:: Eric Torres
|
||||
:synopsis: Unit tests for the PackageManager module.
|
||||
"""
|
||||
import subprocess
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
.. author:: Eric Torres
|
||||
.. moduleauthor:: Eric Torres
|
||||
|
||||
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.
|
||||
"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user