|
- class PathError(Exception):
- def __init__(self, path):
- self.path = path
- super().__init__(self.path)
-
- class PathNotFoundError(PathError):
- pass
-
- class MissingRequirementError(PathError):
- pass
-
- class NotDictError(PathError):
- pass
-
- class Config:
- def __init__(self, data, delimiter = "/", defaults = {}, requirements = [], **misc_options):
- self.data = data
- self.delimiter = delimiter
- self.strict_subscript = misc_options.get("strict_subscript", False)
- self.clobber_subscript = misc_options.get("clobber_subscript", False)
-
- for r in requirements:
- if not self.get(r): raise MissingRequirementError(r)
- for d in defaults:
- try:
- self.get(d, strict = True)
- except PathNotFoundError:
- self.set(d, defaults[d])
-
- def split_path(self, path):
- return path.split(self.delimiter)
-
- def get(self, path, fallback = None, strict = False):
- elementsAll = self.split_path(path)
-
- def g(elems = elementsAll, obj = self.data):
- if not elems or not elems[0] or type(obj) != dict: return obj
- head, tail = elems[0], elems[1:]
- if strict and head not in obj:
- raise PathNotFoundError(path)
- return g(tail, obj.get(head, fallback))
-
- return g()
-
- def set(self, path, value, clobber = False):
- elementsAll = self.split_path(path)
-
- def s(elems = elementsAll, obj = self.data):
- head, tail = elems[0], elems[1:]
-
- # YANDEV MODE ACTIVATE!!!
- if not tail:
- obj[head] = value
- else:
- if head not in obj or type(obj[head]) != dict:
- if clobber:
- obj[head] = {}
- else:
- raise NotDictError(self.delimiter.join(elementsAll[:-len(tail)]))
-
- s(tail, obj[head])
-
- s()
-
- def __getitem__(self, path):
- return self.get(path, self.strict_subscript)
-
- def __setitem__(self, path, value):
- self.set(path, value, self.clobber_subscript)
|