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
« 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
5MISSING = "---missing---"
8def is_basictype(val):
9 return isinstance(val, (int, str, float, type(None)))
12def is_complextype(val):
13 return isinstance(val, (MutableMapping, MutableSequence))
16def is_mutsequence(val):
17 return isinstance(val, MutableSequence)
20def is_mutmapping(val):
21 return isinstance(val, MutableMapping)
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
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