From 2896e6ff774d86379619d9d7e2727cef85fe36f4 Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Fri, 1 Mar 2024 13:47:57 -0800 Subject: [PATCH] flat_dict_to_nested --- src/clippy/backends/expression.py | 13 +++++++++++-- src/clippy/utils.py | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/clippy/utils.py diff --git a/src/clippy/backends/expression.py b/src/clippy/backends/expression.py index 9f4a6b3..f989075 100644 --- a/src/clippy/backends/expression.py +++ b/src/clippy/backends/expression.py @@ -9,6 +9,8 @@ import json from .serialization import ClippySerializable from ..anydict import AnyDict +from ..utils import flat_dict_to_nested + from typing import Any @@ -184,12 +186,19 @@ def _clear_subselectors(self): delattr(self, subsel) self.subselectors = set() - def _import_from_dict(self, d: AnyDict, merge: bool = False): + def _import_from_dict(self, flat_dict: AnyDict, merge: bool = False): '''Imports subselectors from a dictionary. - If `merge = True`, do not clear subselectors first.''' + If `merge = True`, do not clear subselectors first. + + Input dictionary has dot-delimited keys. This function uses + utils.flat_dict_to_nested to create the nested dictionary. + ''' + + d = flat_dict_to_nested(flat_dict) # clear all children if not merge: self._clear_subselectors() + for name, subdict in d.items(): docstr = subdict.get('__doc__', '') self._add_subselector(name, docstr) diff --git a/src/clippy/utils.py b/src/clippy/utils.py new file mode 100644 index 0000000..89524ba --- /dev/null +++ b/src/clippy/utils.py @@ -0,0 +1,26 @@ +""" + Utility functions +""" + +from .anydict import AnyDict +from .error import ClippyInvalidSelectorError + + +def flat_dict_to_nested(input_dict: AnyDict) -> AnyDict: + """input dictionary has dot-delineated keys which are then parsed as subkeys. + That is: {'a.b.c': 5} becomes {'a': {'b': {'c': 5}}} + """ + + output_dict: AnyDict = {} + for k, v in input_dict.items(): + # k is dotted + if '.' not in k: + raise ClippyInvalidSelectorError("cannot set top-level selectors") + + *path, last = k.split('.') + curr_nest = output_dict + for p in path: + curr_nest = output_dict.setdefault(p, {}) + + curr_nest[last] = v + return output_dict