Coverage for /opt/conda/envs/apienv/lib/python3.10/site-packages/daiquiri/core/utils/dictutils.py: 77%

56 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-11-14 02:13 +0000

1from itertools import zip_longest 

2from collections.abc import MutableMapping 

3from collections.abc import MutableSequence 

4 

5MISSING = "---missing---" 

6 

7 

8def is_basictype(val): 

9 return isinstance(val, (int, str, float, type(None))) 

10 

11 

12def is_complextype(val): 

13 return isinstance(val, (MutableMapping, MutableSequence)) 

14 

15 

16def is_mutsequence(val): 

17 return isinstance(val, MutableSequence) 

18 

19 

20def is_mutmapping(val): 

21 return isinstance(val, MutableMapping) 

22 

23 

24def is_sametype(val1, val2): 

25 if is_basictype(val1) and is_basictype(val2) and (type(val1) is type(val2)): 

26 return True 

27 elif is_mutmapping(val1) and is_mutmapping(val2): 

28 return True 

29 elif is_mutsequence(val1) and is_mutsequence(val2): 

30 return True 

31 

32 

33def prudent_update(d, u, ignore_unknown=False): 

34 """Updates a MutableMapping or MutableSequence 'd' 

35 from another one 'u'. 

36 The update is done trying to minimize changes: the 

37 update is done only on leaves of the tree if possible. 

38 This is to preserve the original object as much as possible. 

39 """ 

40 if is_basictype(d) and is_basictype(u): 

41 if d != u: 

42 if d == MISSING: 

43 return u 

44 elif u == MISSING: 

45 return d 

46 return u 

47 else: 

48 return d # prefer not to update 

49 elif is_complextype(d) and is_complextype(u): 

50 if is_sametype(d, u): 

51 # same type 

52 if is_mutmapping(d): 

53 for k, v in u.items(): 

54 if k in d: 

55 d[k] = prudent_update(d[k], v, ignore_unknown=ignore_unknown) 

56 else: 

57 d[k] = v 

58 elif is_mutsequence(d): 

59 if len(u) < len(d): 

60 # issue 2348: if updated element is smaller than existing one, updated replaces existing 

61 d = u 

62 else: 

63 for num, (el1, el2) in enumerate( 

64 zip_longest(d, u, fillvalue=MISSING) 

65 ): 

66 if el2 == MISSING: 

67 # Nothing to do 

68 pass 

69 else: 

70 # missing el1 is managed by prudent_update 

71 # when el1==MISSING el2!=MISSING -> el2 returned 

72 value = prudent_update( 

73 el1, el2, ignore_unknown=ignore_unknown 

74 ) 

75 try: 

76 d[num] = value 

77 except IndexError: 

78 d.append(value) 

79 else: 

80 raise NotImplementedError 

81 return d 

82 else: 

83 # not same type so the destination will be replaced 

84 return u 

85 elif is_basictype(d) and is_complextype(u): 

86 return u 

87 elif is_complextype(d) and is_basictype(u): 

88 return u 

89 else: 

90 if ignore_unknown: 

91 return d 

92 else: 

93 raise NotImplementedError