Access python dicts using path strings (mainly just doing this to l2submodule)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

70 lines
2.2KB

  1. import yaml
  2. class PathError(Exception):
  3. def __init__(self, path):
  4. self.path = path
  5. super().__init__(self.path)
  6. class PathNotFoundError(PathError):
  7. pass
  8. class MissingRequirementError(PathError):
  9. pass
  10. class NotDictError(PathError):
  11. pass
  12. class Config:
  13. def __init__(self, data, delimiter = "/", defaults = {}, requirements = [], **misc_options):
  14. self.data = yaml.safe_load(open(data)) if type(data) != dict else data
  15. self.delimiter = delimiter
  16. self.strict_subscript = misc_options.get("strict_subscript", False)
  17. self.clobber_subscript = misc_options.get("clobber_subscript", False)
  18. for r in requirements:
  19. if not self.get(r): raise MissingRequirementError(r)
  20. for d in defaults:
  21. if not self.get(d): self.set(d, defaults[d])
  22. def split_path(self, path):
  23. return path.split(self.delimiter)
  24. def get(self, path, fallback = None, strict = False):
  25. elementsAll = self.split_path(path)
  26. def g(elems = elementsAll, obj = self.data):
  27. if not elems or not elems[0] or type(obj) != dict: return obj
  28. head, tail = elems[0], elems[1:]
  29. if strict and head not in obj:
  30. raise PathNotFoundError(path)
  31. return g(tail, obj.get(head, fallback))
  32. return g()
  33. def set(self, path, value, clobber = False):
  34. elementsAll = self.split_path(path)
  35. def s(elems = elementsAll, obj = self.data):
  36. head, tail = elems[0], elems[1:]
  37. # YANDEV MODE ACTIVATE!!!
  38. if not tail:
  39. obj[head] = value
  40. else:
  41. if head not in obj or type(obj[head]) != dict:
  42. if clobber:
  43. obj[head] = {}
  44. else:
  45. raise NotDictError(self.delimiter.join(elementsAll[:-len(tail)]))
  46. s(tail, obj[head])
  47. s()
  48. def __getitem__(self, path):
  49. return self.get(path, self.strict_subscript)
  50. def __setitem__(self, path, value):
  51. self.set(path, value, self.clobber_subscript)