Documented skeleton.py
parent
6f8cb2e6f9
commit
3277af2ac5
|
@ -1,21 +1,55 @@
|
|||
"""Handles merging with the skeleton config."""
|
||||
from typing import Dict
|
||||
|
||||
|
||||
class InvalidKeyError(Exception):
|
||||
def __init__(self, key):
|
||||
"""Thrown when a config file contains an invalid key."""
|
||||
|
||||
def __init__(self, key: str):
|
||||
"""
|
||||
Create a new InvalidKeyError object with the given key.
|
||||
|
||||
Args:
|
||||
key: the invalid key
|
||||
"""
|
||||
self.message = "Invalid key: {}".format(key)
|
||||
|
||||
super().__init__(key)
|
||||
|
||||
|
||||
class MissingKeyError(Exception):
|
||||
def __init__(self, key):
|
||||
"""Thrown when a required key is missing from a config."""
|
||||
|
||||
def __init__(self, key: str):
|
||||
"""
|
||||
Create a new MissingKeyError object with the given key.
|
||||
|
||||
Args:
|
||||
key: the invalid key
|
||||
"""
|
||||
self.message = "Missing key: {}".format(key)
|
||||
|
||||
super().__init__(key)
|
||||
|
||||
|
||||
def merge(*dicts: [Dict]) -> Dict:
|
||||
"""
|
||||
Merge multiple dicts into one.
|
||||
|
||||
It reads the dicts from left to right, always preferring the "right"
|
||||
dictionary's values. Therefore, the dictionaries should be sorted from
|
||||
least important to most important (e.g. a default values skeleton should be
|
||||
to the left of a dict of selected values).
|
||||
|
||||
Args:
|
||||
dicts: the dictionaries to merge
|
||||
|
||||
Returns:
|
||||
a new dictionary representing the merged dictionaries
|
||||
|
||||
Todo:
|
||||
* Make sure an infinite loop is not possible
|
||||
"""
|
||||
# Base cases
|
||||
if len(dicts) == 0:
|
||||
return {}
|
||||
|
@ -45,10 +79,20 @@ def merge(*dicts: [Dict]) -> Dict:
|
|||
|
||||
def merge_with_skeleton(data: Dict, skel: Dict) -> Dict:
|
||||
"""
|
||||
Compare a dict with a given skeleton dict, and fill in default values where
|
||||
needed.
|
||||
"""
|
||||
Merge a dictionary with a skeleton containing default values.
|
||||
|
||||
The skeleton not only defines what the default values are, but also
|
||||
enforces a certain shape. This allows us to define a config file using a
|
||||
dictionary and parse it.
|
||||
|
||||
Args:
|
||||
data: dictionary containing the selected config values
|
||||
skel: dictionary containing the skeleton (aka the def)
|
||||
|
||||
Todo:
|
||||
* Check if an infinite loop is possible
|
||||
* Split info less complex functions
|
||||
"""
|
||||
# First, check for illegal keys
|
||||
for key in data:
|
||||
if key not in skel:
|
||||
|
@ -66,6 +110,7 @@ def merge_with_skeleton(data: Dict, skel: Dict) -> Dict:
|
|||
|
||||
# Error if value is not same type as default value
|
||||
elif type(data[key]) != type(value) and value is not None:
|
||||
# TODO make this error message more verbose
|
||||
raise TypeError("Invalid value type")
|
||||
|
||||
# Recurse into dicts
|
||||
|
|
|
@ -6,9 +6,7 @@ from datetime import datetime
|
|||
|
||||
|
||||
class DirectorySpec(Spec):
|
||||
"""
|
||||
A spec for backing up a local directory.
|
||||
"""
|
||||
"""A spec for backing up a local directory."""
|
||||
|
||||
_SKEL = {
|
||||
"source": None,
|
||||
|
|
Loading…
Reference in New Issue