Added documentation
continuous-integration/drone the build failed Details

pull/15/head
Jef Roosens 2021-04-25 19:26:12 +02:00
parent d513a03c4a
commit ecfa6fe7b7
Signed by: Jef Roosens
GPG Key ID: B580B976584B5F30
4 changed files with 83 additions and 44 deletions

View File

@ -1,3 +1,4 @@
"""The main entrypoint of the program."""
import argparse
import sys
from parser import read_specs_file
@ -5,55 +6,62 @@ from parser import read_specs_file
# This just displays the error type and message, not the stack trace
def except_hook(ext_type, value, traceback):
"""
Make errors not show the stracktrace to stdout.
Todo:
* Replace this with proper error handling
"""
sys.stderr.write("{}: {}\n".format(ext_type.__name__, value))
# sys.excepthook = except_hook
# Define parser
parser = argparse.ArgumentParser(
description="Backup directories and Docker volumes."
)
parser.add_argument(
"-f",
"--file",
action="append",
dest="file",
required=True,
help="File containing spec definitions.",
)
parser.add_argument(
"-j",
"--json",
action="store_const",
const=True,
default=False,
help="Print out the parsed specs as JSON and exit",
)
parser.add_argument(
"spec", nargs="*", help="The specs to process. Defaults to all."
)
if __name__ == "__main__":
# Define parser
parser = argparse.ArgumentParser(
description="Backup directories and Docker volumes."
)
parser.add_argument(
"-f",
"--file",
action="append",
dest="file",
required=True,
help="File containing spec definitions.",
)
parser.add_argument(
"-j",
"--json",
action="store_const",
const=True,
default=False,
help="Print out the parsed specs as JSON and exit",
)
parser.add_argument(
"spec", nargs="*", help="The specs to process. Defaults to all."
)
# Parse arguments
args = parser.parse_args()
specs = sum([read_specs_file(path) for path in args.file], [])
# Parse arguments
args = parser.parse_args()
specs = sum((read_specs_file(path) for path in args.file), [])
# Filter specs if needed
if args.spec:
specs = list(filter(lambda s: s.name in args.spec, specs))
# Filter specs if needed
if args.spec:
specs = list(filter(lambda s: s.name in args.spec, specs))
# Dump parsed data as json
if args.json:
import json
# Dump parsed data as json
if args.json:
import json
print(json.dumps([spec.to_dict() for spec in specs], indent=4))
# TODO replace this with error handling system
print(json.dumps([spec.to_dict() for spec in specs], indent=4))
else:
# Run the backups
if not specs:
print("No specs, exiting.")
sys.exit(0)
elif not specs:
# TODO replace this with error handling system
print("No specs, exiting.")
sys.exit(0)
for spec in specs:
spec.backup()
for spec in specs:
spec.backup()

View File

@ -1,4 +1,7 @@
"""Parent module for the various spec types."""
from .spec import Spec
from .directory import DirectorySpec
from .volume import VolumeSpec
from .container import ContainerSpec
__all__ = ["Spec", "DirectorySpec", "VolumeSpec", "ContainerSpec"]

View File

@ -1,3 +1,4 @@
"""Module defining a Container-based spec."""
from .spec import Spec
from typing import Union
from pathlib import Path
@ -6,11 +7,10 @@ import subprocess
class ContainerSpec(Spec):
"""
A spec for backing up via a container.
"""
"""Spec for backing up via a container."""
_SKEL = {"container": None, "command": None, "mountpoint": "/from"}
"""The skeleton for the ContainerSpec config."""
def __init__(
self,
@ -23,6 +23,22 @@ class ContainerSpec(Spec):
mountpoint: str,
notify=None,
):
"""
Create a new ContainerSpec object.
Args:
name: name of the spec (used as an identifier)
container: the Docker container to back up
destination: where to store the backups (gets created if
non-existent)
limit: max amount of backups to keep
command: command to run inside the container. This command should
perform a specified backup and output this data to stdout. This
output then gets piped to a backup file.
extension: the extension of the backup files.
mountpoint:
notify: notifier object (may be None)
"""
super().__init__(name, destination, limit, extension, notify)
self.container = container

View File

@ -60,7 +60,19 @@ class Spec:
self.extension = extension
@classmethod
def skeleton(cls):
def skeleton(cls: "Spec") -> Dict:
"""
Return the skeleton for the given class.
It works by inspecting the inheritance tree and merging the skeleton
for each of the parents.
Args:
cls: the class to get the skeleton for
Returns:
a dictionary containing the skeleton
"""
return skeleton.merge(
*[val._SKEL for val in reversed(inspect.getmro(cls)[:-1])]
)