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

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 

6 

7""" 

8Generic utility functions for data manipulation. 

9 

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""" 

14 

15 

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. 

19 

20 If copy_first is set to False, then the base_dict is actually updated. 

21 

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 

38 

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 

49 

50 return target_dict