PillarTool/pillar_tool/util/pillar_utilities.py

51 lines
2.0 KiB
Python

from copy import deepcopy
def apply_layer(base: dict, layer: dict):
"""
Recursively applies key-value pairs from `layer` onto `base`.
For each key in `layer`:
- If both `base[key]` and `layer[key]` are dictionaries, recursively merge them.
- Otherwise, `base[key]` is overwritten (or newly inserted) with `layer[key]`.
Note: This function mutates the `base` dictionary in-place.
:param base: The target dictionary to be updated. Will be modified directly.
:param layer: The source dictionary whose values will be applied to `base`.
"""
for key, value in layer.items():
# if base and layer value are dicts, apply recursively
if type(value) is dict and key in base and type(base[key]) is dict:
apply_layer(base[key], value)
# else replace the base value with the layer value
# or insert the base value
else:
base[key] = value
def merge(pillar_data, deep_copy=True) -> dict:
"""
Merges multiple pillar data dictionaries into one.
The merging is done left-to-right: keys from later dictionaries override
those in earlier ones. Nested dictionaries are merged recursively using
`apply_layer`.
:param pillar_data: Two or more dictionaries to merge. Must contain at least one item.
:param deep_copy: If True (default), the first dictionary is deep-copied before merging,
preserving the original input data. If False, the first dictionary
is modified in-place.
:return: A new merged dictionary (if `deep_copy=True`) or the mutated first dictionary (if `deep_copy=False`).
Example:
merge({'a': 1}, {'b': 2}) → {'a': 1, 'b': 2}
merge({'a': {'x': 1}}, {'a': {'y': 2}}) → {'a': {'x': 1, 'y': 2}}
"""
assert len(pillar_data) > 0, "At least one pillar data is required"
merged_pillar = deepcopy(pillar_data[0]) if deep_copy else pillar_data[0]
for pillar in pillar_data[1:]:
apply_layer(merged_pillar, pillar)
return merged_pillar