Coverage for src / mafw / tools / generics.py: 100%
12 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-09 09:08 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-09 09:08 +0000
1# Copyright 2025 European Union
2# Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
3# SPDX-License-Identifier: EUPL-1.2
4from copy import deepcopy
5from typing import Any
7"""
8Generic utility functions for data manipulation.
10This module provides helper functions for common data structure operations,
11particularly focused on dictionary manipulation with support for deep updates
12and recursive merging of nested structures.
13"""
16def deep_update(base_dict: dict[Any, Any], update_dict: dict[Any, Any], copy_first: bool = True) -> dict[Any, Any]:
17 """
18 Recursively updates a dictionary.
20 If copy_first is set to False, then the base_dict is actually updated.
22 :param base_dict: The dictionary to update.
23 :type base_dict: dict[Any, Any]
24 :param update_dict: The dictionary containing the updated fields
25 :type update_dict: dict[Any, Any]
26 :param copy_first: Whether the base dictionary should be copied or updated. Defaults to True
27 :type copy_first: bool, Optional
28 :return: The recursively updated dictionary
29 :rtype: dict[Any, Any]
30 """
31 # 1. Handle Copying
32 if copy_first:
33 # Use deepcopy to ensure nested dictionaries are also new objects
34 target_dict = deepcopy(base_dict)
35 else:
36 # Modify the original dictionary in place
37 target_dict = base_dict
39 # 2. Perform Recursive Update
40 for key, value in update_dict.items():
41 if isinstance(value, dict) and key in target_dict and isinstance(target_dict[key], dict):
42 # If both values are dictionaries, recurse on the target_dict's value
43 # Note: We pass copy_first=False here because we are modifying
44 # the already-copied/selected target_dict, we don't need another copy.
45 deep_update(target_dict[key], value, copy_first=False)
46 else:
47 # Otherwise, update or insert the new value
48 target_dict[key] = value
50 return target_dict