Coverage for stricto/list.py: 100%
197 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-08 22:32 +0100
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-08 22:32 +0100
1"""Module providing the List() Class"""
2import copy
3from .generic import GenericType
4from .error import Error, ErrorType
7class List(GenericType): # pylint: disable=too-many-instance-attributes
8 """
9 A Dict Type
10 """
12 def __init__(self, class_type: None, **kwargs):
13 """
14 initialisation, set class_type and some parameters
15 """
16 self._type = class_type
18 self._min = kwargs.pop("min", None)
19 self._max = kwargs.pop("max", None)
20 self._uniq = kwargs.pop("uniq", None)
22 GenericType.__init__(self, **kwargs)
25 def __len__(self):
26 """
27 calld by len()
28 """
29 if not isinstance(self._value, list):
30 return 0
31 return self._value.__len__()
33 def set_hierachy_attributs(self, root, parent, name):
34 """
35 set the root, parent and attribute_name
36 used to build the hierachy of the object and the name of che current key (name)
37 """
38 self.root = root
39 self.parent = parent
40 self.attribute_name = name
41 self.set_sub_root()
43 def set_sub_root(self):
44 """
45 Do like set_hierachy_attributs, but for sub objects
46 """
47 if not isinstance(self._value, list):
48 return
50 i = 0
51 for item in self._value:
52 item.set_hierachy_attributs(self.root, self, f"{self.attribute_name}[{i}]")
53 i = i + 1
55 def __repr__(self):
56 if self._value is None:
57 return repr(None)
58 a = []
59 for i in self._value:
60 a.append(i)
61 return a.__repr__()
63 def __getitem__(self, index):
64 return self._value[index]
66 def __copy__(self):
67 cls = self.__class__
68 result = cls.__new__(cls)
69 result.__dict__.update(self.__dict__)
70 result._value = None
71 if isinstance(self._value, list):
72 result._value = []
73 for i in self._value:
74 result._value.append(i.copy())
75 return result
77 def copy(self):
78 return copy.copy(self)
80 # self.__copy__()
82 def clear(self):
83 """
84 Do List.clear() as list.clear() (with checks)
85 """
86 self.check([])
87 self._value.clear()
89 def duplicate_in_list(self):
90 """
91 Copy the list self._value to another list
92 used to check() on this list before modification
93 """
94 a = []
95 if not isinstance(self._value, list):
96 return a
98 for v in self._value:
99 a.append(v.copy())
100 return a
102 def insert(self, key, value):
103 """
104 Do a list.insert()
105 """
106 # Duplicate and check
107 a = self.duplicate_in_list()
108 model = self._type.copy()
109 model.set_hierachy_attributs(self.root, self, f"{self.attribute_name}[{key}]")
110 model.set(value)
111 a.insert(key, model)
112 self.check(a)
114 if not isinstance(self._value, list):
115 self._value = []
117 self._value.insert(key, model)
119 def __setitem__(self, key, value):
120 """
121 Do a list[key] = value
122 """
124 # Duplicate and check
125 a = self.duplicate_in_list()
127 if isinstance(key, slice):
128 models = []
129 for v in value:
130 model = self._type.copy()
131 model.set_hierachy_attributs(self.root, self, "[slice]")
132 model.set(v)
133 models.append(model)
134 a.__setitem__(key, models)
135 self.check(a)
137 self._value.__setitem__(key, models)
138 self.set_sub_root()
139 else:
140 model = self._type.copy()
141 model.set_hierachy_attributs(self.root, self, f"[{key}]")
142 model.set(value)
143 a[key].set(value)
144 self.check(a)
146 self._value.__setitem__(key, model)
148 def __delitem__(self, key):
149 """
150 Do a del (list[key])
151 """
153 # Duplicate and check
154 a = self.duplicate_in_list()
155 a.__delitem__(key)
156 self.check(a)
158 self._value.__delitem__(key)
159 self.set_sub_root()
161 def sort(self, **kwarg):
162 """
163 Do a sort(List) like sort(list)
164 """
166 # Duplicate and check
167 a = self.duplicate_in_list()
168 a.sort(**kwarg)
169 self.check(a)
171 if not isinstance(self._value, list):
172 self._value = []
174 return self._value.sort(**kwarg)
176 def pop(self, key=-1):
177 """
178 Do a List.pop() like list.pop()
179 """
181 # Build a list to modify and check if ok before
182 # doing the pop
183 a = self.duplicate_in_list()
184 a.pop(key)
185 self.check(a)
187 popped = self._value.pop(key)
188 self.set_sub_root()
189 return popped
191 def remove(self, value):
192 """
193 Do a List.remove(value) like list.remove(value)
194 """
196 # Duplicate and check
197 a = self.duplicate_in_list()
198 a.remove(value)
199 self.check(a)
201 removed = self._value.remove(value)
202 self.set_sub_root()
203 return removed
205 def append(self, value):
206 """
207 Do a List.append(value) like list.append(value)
208 """
210 model = self._type.copy()
211 model.set_hierachy_attributs(self.root, self, f"[{len(self)}]")
212 model.set(value)
214 # Duplicate and check
215 a = self.duplicate_in_list()
216 a.append(model)
217 self.check(a)
219 if not isinstance(self._value, list):
220 self._value = []
222 self._value.append(model)
224 def extend(self, second_list):
225 """
226 Do a List.extend(second_list) like list.extend(second_list)
227 """
228 # Duplicate and check
229 a = self.duplicate_in_list()
230 models = []
231 i = len(self)
232 for value in second_list:
233 model = self._type.copy()
234 model.set_hierachy_attributs(self.root, self, f"[{i}]")
235 model.set(value)
236 a.append(model)
237 models.append(model)
238 i = i + 1
239 self.check(a)
241 if not isinstance(self._value, list):
242 self._value = []
244 self._value.extend(models)
246 def set_value_without_checks(self, value):
247 """
248 @overwrite GenericType.setWithoutcheck
249 """
250 if value is None:
251 self._value = None
252 return
254 if not isinstance(self._value, list):
255 self._value = []
257 self._value.clear()
258 i = 0
259 for v in value:
260 model = self._type.copy()
261 model.set_hierachy_attributs(self.root, self, f"[{i}]")
262 model.set_value_without_checks(v)
263 self._value.append(model)
264 i = i + 1
266 def auto_set(self):
267 """
268 compute automatically a value because another value as changed somewhere.
269 (related to set=flag) and call to all subs
270 """
271 GenericType.auto_set(self)
272 if not isinstance(self._value, list):
273 return
275 for key in self._value:
276 key.auto_set()
278 def check(self, value):
279 GenericType.check(self, value)
281 # check all values
282 if isinstance(value, list):
283 i = 0
284 for v in value:
285 self._type.check(v)
286 i = i + 1
287 return
289 if isinstance(value, List):
290 i = 0
291 for v in value:
292 self._type.check(v.get_value())
293 i = i + 1
295 def get_value(self):
296 """
297 @overwrite GenericType.get_value()
298 """
299 if self._value is None:
300 return None
302 a = []
303 for element in self._value:
304 a.append(element.get_value())
305 return a
307 def check_type(self, value):
308 """
309 check if conplain to model or return a error string
310 """
311 if isinstance(value, list):
312 return True
314 if isinstance(value, List):
315 return True
317 raise Error(ErrorType.NOTALIST, "Must be a list", self.path_name())
319 def check_constraints(self, value):
320 GenericType.check_constraints(self, value)
322 if self._min is not None:
323 if len(value) < self._min:
324 raise Error(ErrorType.LENGTH, "Must be above Minimal", self.path_name())
325 if self._max is not None:
326 if len(value) > self._max:
327 raise Error(ErrorType.LENGTH, "Must be below Maximal", self.path_name())
329 if self._uniq is True:
330 for x in value:
331 if value.count(x) > 1:
332 raise Error(
333 ErrorType.DUP, "duplicate value in list", self.path_name()
334 )
336 return True