Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/itypes.py: 21%
145 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1# coding: utf-8
2try:
3 from collections.abc import Mapping, Sequence
4except ImportError: # support for python 2.x
5 from collections import Mapping, Sequence
8__version__ = '1.2.0'
11def to_mutable(instance):
12 if isinstance(instance, Dict):
13 return {
14 key: to_mutable(value)
15 for key, value in instance.items()
16 }
17 elif isinstance(instance, List):
18 return [
19 to_mutable(value)
20 for value in instance
21 ]
22 return instance
25def to_immutable(value):
26 if isinstance(value, dict):
27 return Dict(value)
28 elif isinstance(value, list):
29 return List(value)
30 return value
33def _to_hashable(instance):
34 if isinstance(instance, Dict):
35 items = sorted(instance.items(), key=lambda item: item[0])
36 return (
37 (key, _to_hashable(value))
38 for key, value in items
39 )
40 elif isinstance(instance, List):
41 return [
42 _to_hashable(value)
43 for value in instance
44 ]
45 return instance
48def _set_in(node, keys, value):
49 if not keys:
50 return value
51 elif len(keys) == 1:
52 return node.set(keys[0], value)
54 key = keys[0]
55 child = node[key]
56 if not isinstance(child, (Dict, List)):
57 msg = "Expected a container type at key '%s', but got '%s'"
58 raise KeyError(msg % type(child))
59 child = child.set_in(keys[1:], value)
60 return node.set(key, child)
63def _delete_in(node, keys):
64 if not keys:
65 return
66 elif len(keys) == 1:
67 return node.delete(keys[0])
69 key = keys[0]
70 child = node[key]
71 if not isinstance(child, (Dict, List)):
72 msg = "Expected a container type at key '%s', but got '%s'"
73 raise KeyError(msg % type(child))
74 child = child.delete_in(keys[1:])
75 return node.set(key, child)
78def _get_in(node, keys, default=None):
79 if not keys:
80 return default
82 key = keys[0]
83 try:
84 child = node[key]
85 except (KeyError, IndexError):
86 return default
88 if len(keys) == 1:
89 return child
90 return child.get_in(keys[1:], default=default)
93class Object(object):
94 def __setattr__(self, key, value):
95 if key.startswith('_'):
96 return object.__setattr__(self, key, value)
97 msg = "'%s' object doesn't support property assignment."
98 raise TypeError(msg % self.__class__.__name__)
101class Dict(Mapping):
102 def __init__(self, *args, **kwargs):
103 self._data = {
104 key: to_immutable(value)
105 for key, value in dict(*args, **kwargs).items()
106 }
108 def __setattr__(self, key, value):
109 if key.startswith('_'):
110 return object.__setattr__(self, key, value)
111 msg = "'%s' object doesn't support property assignment."
112 raise TypeError(msg % self.__class__.__name__)
114 def __getitem__(self, key):
115 return self._data[key]
117 def __iter__(self):
118 return iter(self._data)
120 def __len__(self):
121 return len(self._data)
123 def __eq__(self, other):
124 if isinstance(other, self.__class__):
125 return self._data == other._data
126 return self._data == other
128 def __hash__(self):
129 return hash(_to_hashable(self))
131 def __repr__(self):
132 return "%s(%s)" % (
133 self.__class__.__name__,
134 to_mutable(self)
135 )
137 def __str__(self):
138 return str(self._data)
140 def set(self, key, value):
141 data = dict(self._data)
142 data[key] = value
143 if hasattr(self, 'clone'):
144 return self.clone(data)
145 return type(self)(data)
147 def delete(self, key):
148 data = dict(self._data)
149 data.pop(key)
150 if hasattr(self, 'clone'):
151 return self.clone(data)
152 return type(self)(data)
154 def get_in(self, keys, default=None):
155 return _get_in(self, keys, default=default)
157 def set_in(self, keys, value):
158 return _set_in(self, keys, value)
160 def delete_in(self, keys):
161 return _delete_in(self, keys)
164class List(Sequence):
165 def __init__(self, *args):
166 self._data = [
167 to_immutable(value)
168 for value in list(*args)
169 ]
171 def __setattr__(self, key, value):
172 if key == '_data':
173 return object.__setattr__(self, key, value)
174 msg = "'%s' object doesn't support property assignment."
175 raise TypeError(msg % self.__class__.__name__)
177 def __getitem__(self, key):
178 return self._data[key]
180 def __iter__(self):
181 return iter(self._data)
183 def __len__(self):
184 return len(self._data)
186 def __eq__(self, other):
187 if isinstance(other, self.__class__):
188 return self._data == other._data
189 return self._data == other
191 def __hash__(self):
192 return hash(_to_hashable(self))
194 def __repr__(self):
195 return "%s(%s)" % (
196 self.__class__.__name__,
197 to_mutable(self)
198 )
200 def __str__(self):
201 return str(self._data)
203 def set(self, key, value):
204 data = list(self._data)
205 data[key] = value
206 if hasattr(self, 'clone'):
207 return self.clone(data)
208 return type(self)(data)
210 def delete(self, key):
211 data = list(self._data)
212 data.pop(key)
213 if hasattr(self, 'clone'):
214 return self.clone(data)
215 return type(self)(data)
217 def get_in(self, keys, default=None):
218 return _get_in(self, keys, default=default)
220 def set_in(self, keys, value):
221 return _set_in(self, keys, value)
223 def delete_in(self, keys):
224 return _delete_in(self, keys)