From 3277af2ac5df2f7a85d8978ed99d2c08f824bb3b Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 25 Apr 2021 18:10:37 +0200 Subject: [PATCH] Documented skeleton.py --- app/skeleton.py | 55 ++++++++++++++++++++++++++++++++++++++---- app/specs/directory.py | 4 +-- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/app/skeleton.py b/app/skeleton.py index 07c6afb..9fe48a6 100644 --- a/app/skeleton.py +++ b/app/skeleton.py @@ -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 diff --git a/app/specs/directory.py b/app/specs/directory.py index 9747b5b..4fa0ffe 100644 --- a/app/specs/directory.py +++ b/app/specs/directory.py @@ -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,