48 lines
1.2 KiB
Python
48 lines
1.2 KiB
Python
|
from typing import Dict
|
||
|
|
||
|
|
||
|
class InvalidKeyError(Exception):
|
||
|
def __init__(self, key):
|
||
|
self.message = "Invalid key: {}".format(key)
|
||
|
|
||
|
super().__init__(key)
|
||
|
|
||
|
|
||
|
class MissingKeyError(Exception):
|
||
|
def __init__(self, key):
|
||
|
self.message = "Missing key: {}".format(key)
|
||
|
|
||
|
super().__init__(key)
|
||
|
|
||
|
|
||
|
def combine(data: Dict, skel: Dict) -> Dict:
|
||
|
"""
|
||
|
Compare a dict with a given skeleton dict, and fill in default values where
|
||
|
needed.
|
||
|
"""
|
||
|
|
||
|
# First, check for illegal keys
|
||
|
for key in data:
|
||
|
if key not in skel:
|
||
|
raise InvalidKeyError(key)
|
||
|
|
||
|
# Then, check the default values
|
||
|
for key, value in skel.items():
|
||
|
if key not in data:
|
||
|
# Raise error if there's not default value
|
||
|
if value is None:
|
||
|
raise MissingKeyError(key)
|
||
|
|
||
|
# Replace with default value
|
||
|
data[key] = value
|
||
|
|
||
|
# Error if value is not same type as default value
|
||
|
elif type(data[key]) != type(value) and value is not None:
|
||
|
raise TypeError("Invalid value type")
|
||
|
|
||
|
# Recurse into dicts
|
||
|
elif type(value) == dict:
|
||
|
data[key] = combine_with_skeleton(data[key], value)
|
||
|
|
||
|
return data
|