Coverage for stricto/list.py: 100%

197 statements  

« 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 

5 

6 

7class List(GenericType): # pylint: disable=too-many-instance-attributes 

8 """ 

9 A Dict Type 

10 """ 

11 

12 def __init__(self, class_type: None, **kwargs): 

13 """ 

14 initialisation, set class_type and some parameters 

15 """ 

16 self._type = class_type 

17 

18 self._min = kwargs.pop("min", None) 

19 self._max = kwargs.pop("max", None) 

20 self._uniq = kwargs.pop("uniq", None) 

21 

22 GenericType.__init__(self, **kwargs) 

23 

24 

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__() 

32 

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() 

42 

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 

49 

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 

54 

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__() 

62 

63 def __getitem__(self, index): 

64 return self._value[index] 

65 

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 

76 

77 def copy(self): 

78 return copy.copy(self) 

79 

80 # self.__copy__() 

81 

82 def clear(self): 

83 """ 

84 Do List.clear() as list.clear() (with checks) 

85 """ 

86 self.check([]) 

87 self._value.clear() 

88 

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 

97 

98 for v in self._value: 

99 a.append(v.copy()) 

100 return a 

101 

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) 

113 

114 if not isinstance(self._value, list): 

115 self._value = [] 

116 

117 self._value.insert(key, model) 

118 

119 def __setitem__(self, key, value): 

120 """ 

121 Do a list[key] = value 

122 """ 

123 

124 # Duplicate and check 

125 a = self.duplicate_in_list() 

126 

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) 

136 

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) 

145 

146 self._value.__setitem__(key, model) 

147 

148 def __delitem__(self, key): 

149 """ 

150 Do a del (list[key]) 

151 """ 

152 

153 # Duplicate and check 

154 a = self.duplicate_in_list() 

155 a.__delitem__(key) 

156 self.check(a) 

157 

158 self._value.__delitem__(key) 

159 self.set_sub_root() 

160 

161 def sort(self, **kwarg): 

162 """ 

163 Do a sort(List) like sort(list) 

164 """ 

165 

166 # Duplicate and check 

167 a = self.duplicate_in_list() 

168 a.sort(**kwarg) 

169 self.check(a) 

170 

171 if not isinstance(self._value, list): 

172 self._value = [] 

173 

174 return self._value.sort(**kwarg) 

175 

176 def pop(self, key=-1): 

177 """ 

178 Do a List.pop() like list.pop() 

179 """ 

180 

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) 

186 

187 popped = self._value.pop(key) 

188 self.set_sub_root() 

189 return popped 

190 

191 def remove(self, value): 

192 """ 

193 Do a List.remove(value) like list.remove(value) 

194 """ 

195 

196 # Duplicate and check 

197 a = self.duplicate_in_list() 

198 a.remove(value) 

199 self.check(a) 

200 

201 removed = self._value.remove(value) 

202 self.set_sub_root() 

203 return removed 

204 

205 def append(self, value): 

206 """ 

207 Do a List.append(value) like list.append(value) 

208 """ 

209 

210 model = self._type.copy() 

211 model.set_hierachy_attributs(self.root, self, f"[{len(self)}]") 

212 model.set(value) 

213 

214 # Duplicate and check 

215 a = self.duplicate_in_list() 

216 a.append(model) 

217 self.check(a) 

218 

219 if not isinstance(self._value, list): 

220 self._value = [] 

221 

222 self._value.append(model) 

223 

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) 

240 

241 if not isinstance(self._value, list): 

242 self._value = [] 

243 

244 self._value.extend(models) 

245 

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 

253 

254 if not isinstance(self._value, list): 

255 self._value = [] 

256 

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 

265 

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 

274 

275 for key in self._value: 

276 key.auto_set() 

277 

278 def check(self, value): 

279 GenericType.check(self, value) 

280 

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 

288 

289 if isinstance(value, List): 

290 i = 0 

291 for v in value: 

292 self._type.check(v.get_value()) 

293 i = i + 1 

294 

295 def get_value(self): 

296 """ 

297 @overwrite GenericType.get_value() 

298 """ 

299 if self._value is None: 

300 return None 

301 

302 a = [] 

303 for element in self._value: 

304 a.append(element.get_value()) 

305 return a 

306 

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 

313 

314 if isinstance(value, List): 

315 return True 

316 

317 raise Error(ErrorType.NOTALIST, "Must be a list", self.path_name()) 

318 

319 def check_constraints(self, value): 

320 GenericType.check_constraints(self, value) 

321 

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()) 

328 

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 ) 

335 

336 return True