Coverage for skema/metal/model_linker/skema_model_linker/walkers/json.py: 40%
30 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-30 17:15 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-30 17:15 +0000
1from typing import NamedTuple, Any, Dict, Optional
3from . import ModelWalker
6class JsonNode(NamedTuple):
7 name: str
8 val: Any
9 index: int
12class JsonDictWalker(ModelWalker):
14 def __init__(self, data: Dict[str, Any]):
15 self.__data = data
17 def __iter__(self):
18 return self.walk()
20 def _filter(self, obj_name: Optional[str], obj: Any, index: Optional[int]) -> bool:
21 """ Decides whether traverse the current element.
22 True by default. Override to customize behavior """
23 return True
25 def __step(self, obj_name: Optional[str], obj: Any, index: Optional[int] = None, callback=None, **kwargs):
26 """ Walks over the elements of the json dictionary """
28 ret = list()
30 allowed = self._filter(obj_name, obj, index)
32 # If a callback is provided, call it
33 if allowed and callback:
34 callback(obj_name, obj, index)
36 if isinstance(obj, list):
37 for ix, elem in enumerate(obj):
38 if type(elem) in (list, dict):
39 ret.extend(self.__step(obj_name, elem, ix, callback, **kwargs))
40 elif isinstance(obj, dict):
41 for prop, val in obj.items():
42 ret.extend(self.__step(prop, val, None, callback, **kwargs))
44 if allowed and not isinstance(obj, list):
45 ret.append(JsonNode(obj_name, obj, index))
47 return ret
49 def walk(self, callback=None, *args, **kwargs):
50 """ Start the walk from the root of the json object """
51 return reversed(self.__step(obj_name=None, obj=self.__data, callback=callback, **kwargs))