Guest User

Untitled

a guest
Jun 22nd, 2018
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.79 KB | None | 0 0
  1. class RecursiveNestedDict(dict):
  2. _PATH_SEP = '.'
  3.  
  4. def __init__(self, *args, **kwargs):
  5. super(RecursiveNestedDict, self).__init__(*args, **kwargs)
  6. for k, v in self.items():
  7. if isinstance(v, dict) and not isinstance(v, RecursiveNestedDict):
  8. self[k] = RecursiveNestedDict(v)
  9.  
  10. def __setitem__(self, key, value):
  11. if isinstance(value, dict) and \
  12. not isinstance(value, RecursiveNestedDict):
  13. value = RecursiveNestedDict(value)
  14.  
  15. super(RecursiveNestedDict, self).__setitem__(key, value)
  16.  
  17. def __repr__(self):
  18. return self.__class__.__name__ + '(' \
  19. + super(RecursiveNestedDict, self).__repr__() + ')'
  20.  
  21. def __str__(self):
  22. return str(self.asdict())
  23.  
  24. def __recursive_find(self, path: str, _previous_path: str = None):
  25. keys = path.split(self._PATH_SEP, maxsplit=1)
  26.  
  27. current_path = keys[0] if not _previous_path \
  28. else self._PATH_SEP.join((_previous_path, keys[0]))
  29.  
  30. if len(keys) == 1:
  31. # final split
  32. try:
  33. return self[keys[0]]
  34. except KeyError as e:
  35. raise KeyError(current_path) from e
  36. else:
  37. try:
  38. next_level = self[keys[0]]
  39. assert isinstance(next_level, RecursiveNestedDict)
  40. return next_level.__recursive_find(keys[1], current_path)
  41. except AssertionError:
  42. raise TypeError(
  43. 'Can\'t traverse dictionary: '
  44. 'element {} is not a {}'.format(
  45. current_path,
  46. self.__class__.__name__
  47. ))
  48.  
  49. def asdict(self) -> Dict:
  50. """
  51. Returns the vanilla python representation of this dictionary.
  52. :return: Dictionary representation of the data contained in this
  53. instance.
  54. """
  55.  
  56. r = dict(self)
  57. for k, v in r.items():
  58. if isinstance(v, RecursiveNestedDict):
  59. r[k] = v.asdict()
  60.  
  61. return r
  62.  
  63. def find(self, path: str):
  64. """
  65. Recursively finds the specified "path" through nested dictionaries,
  66. with origin in the current dictionary.
  67. Paths are specified as a sequence of keys separated by periods.
  68. For instance, in the following dictionary, key "c" in the innermost
  69. nested dictionary has path "a.b.c" from the outermost dictionary:
  70.  
  71. {
  72. "a": {
  73. "b": {
  74. "c": "Hello World!"
  75. }
  76. }
  77. }
  78.  
  79. :param path: String representation of the path to find.
  80. :return: The value at located at the end of the given path.
  81. :raises: KeyError in case the path cannot be followed.
  82. """
  83. return self.__recursive_find(path)
Add Comment
Please, Sign In to add comment