42 lines
1.5 KiB
Python
42 lines
1.5 KiB
Python
#
|
|
# Copyright (c) 2022 Airbyte, Inc., all rights reserved.
|
|
#
|
|
|
|
from functools import reduce
|
|
from typing import Any, Iterable, List, Mapping, Optional, Tuple
|
|
|
|
|
|
def all_key_pairs_dot_notation(dict_obj: Mapping) -> Mapping[str, Any]:
|
|
"""
|
|
Recursively iterate through a dictionary and return a dictionary of all key-value pairs in dot notation.
|
|
keys are prefixed with the list of keys passed in as prefix.
|
|
"""
|
|
|
|
def _all_key_pairs_dot_notation(_dict_obj: Mapping, prefix: List[str] = []) -> Iterable[Tuple[str, Any]]:
|
|
for key, value in _dict_obj.items():
|
|
if isinstance(value, dict):
|
|
prefix.append(str(key))
|
|
yield from _all_key_pairs_dot_notation(value, prefix)
|
|
prefix.pop()
|
|
else:
|
|
prefix.append(str(key))
|
|
yield ".".join(prefix), value
|
|
prefix.pop()
|
|
|
|
return {k: v for k, v in _all_key_pairs_dot_notation(dict_obj)}
|
|
|
|
|
|
def get_value_by_dot_notation(dict_obj: Mapping, key: str, default: Optional[Any] = ...) -> Any:
|
|
"""
|
|
Return the value of a key in dot notation in a arbitrarily nested Mapping.
|
|
dict_obj: Mapping
|
|
key: str
|
|
default: Any
|
|
raises: KeyError if default is not provided and the key is not found
|
|
ex.:
|
|
dict_obj = {"nested": {"key": "value"}}
|
|
get_value_by_dot_notation(dict_obj, "nested.key") == "value" -> True
|
|
"""
|
|
|
|
return reduce(lambda d, key_name: d[key_name] if default is ... else d.get(key_name, default), key.split("."), dict_obj)
|