Coverage for stricto/dict.py: 99%

154 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-02-29 10:26 +0100

1"""Module providing the Dict() Class""" 

2import copy 

3from .generic import GenericType 

4from .error import Error, ErrorType 

5 

6 

7class Dict(GenericType): 

8 """ 

9 A Dict Type 

10 """ 

11 

12 def __init__(self, schema: dict, **kwargs): 

13 """ """ 

14 self._keys = [] 

15 for key in schema.keys(): 

16 m = schema.get(key) 

17 if isinstance(m, GenericType) is False: 

18 raise Error(ErrorType.NOTATYPE, "Not a schema") 

19 mm = copy.copy(m) 

20 setattr(self, key, mm) 

21 self._keys.append(key) 

22 

23 GenericType.__init__(self, **kwargs) 

24 

25 self.set_hierachy_attributs(self, None, "") 

26 

27 self._locked = True 

28 

29 def add_to_model(self, key, model): 

30 """ 

31 add new element to the model 

32 """ 

33 mm = copy.copy(model) 

34 self.__dict__["_locked"] = False 

35 setattr(self, key, mm) 

36 self._keys.append(key) 

37 self.__dict__[key].set_hierachy_attributs(self.root, self, key) 

38 self.__dict__["_locked"] = True 

39 

40 def remove_model(self, key): 

41 """ 

42 remove a key Model to the model 

43 """ 

44 self.__dict__["_locked"] = False 

45 delattr(self, key) 

46 self._keys.remove(key) 

47 self.__dict__["_locked"] = True 

48 

49 def set_hierachy_attributs(self, root, parent, name): 

50 GenericType.set_hierachy_attributs(self, root, parent, name) 

51 for key in self._keys: 

52 self.__dict__[key].set_hierachy_attributs(root, self, key) 

53 

54 def keys(self): 

55 """ 

56 return all keys 

57 """ 

58 return self._keys 

59 

60 def __getitem__(self, k): 

61 if k in self._keys: 

62 return self.__dict__[k] 

63 return None 

64 

65 def __setattr__(self, name, value): 

66 try: 

67 locked = self.__dict__["_locked"] 

68 except KeyError: 

69 locked = False 

70 

71 try: 

72 keys = self.__dict__["_keys"] 

73 except KeyError: 

74 keys = None 

75 

76 if locked: 

77 if name not in keys: 

78 raise Error(ErrorType.NOTALIST, "locked", f"{name}") 

79 if isinstance(value, GenericType): 

80 self.__dict__[f"{name}"].check(value) 

81 self.__dict__[f"{name}"] = value 

82 else: 

83 self.__dict__[f"{name}"].set(value) 

84 return 

85 

86 self.__dict__[f"{name}"] = value 

87 

88 def copy(self): 

89 return copy.copy(self) 

90 

91 def __copy__(self): 

92 cls = self.__class__ 

93 result = cls.__new__(cls) 

94 result._keys = self._keys.copy() 

95 for key in self._keys: 

96 result.__dict__[key] = self.__dict__[key].__copy__() 

97 result.__dict__["_constraints"] = self.__dict__["_constraints"].copy() 

98 result.__dict__["_transform"] = self.__dict__["_transform"] 

99 result.__dict__["_union"] = self.__dict__["_union"] 

100 result.__dict__["root"] = self.__dict__["root"] 

101 result.__dict__["parent"] = self.__dict__["parent"] 

102 result.__dict__["attribute_name"] = self.__dict__["attribute_name"] 

103 result.__dict__["_on_change"] = self.__dict__["_on_change"] 

104 result.__dict__["_exists"] = self.__dict__["_exists"] 

105 result._locked = True 

106 return result 

107 

108 def __repr__(self): 

109 a = {} 

110 for key in self._keys: 

111 v = getattr(self, key) 

112 if v.exists() is False: 

113 continue 

114 a[key] = getattr(self, key) 

115 return a.__repr__() 

116 

117 def __eq__(self, other): 

118 """ 

119 equality test two objects 

120 """ 

121 for key in self._keys: 

122 if getattr(self, key) != getattr(other, key): 

123 return False 

124 return True 

125 

126 def __ne__(self, other): 

127 """ 

128 equality test two objects 

129 """ 

130 for key in self._keys: 

131 if getattr(self, key) != getattr(other, key): 

132 return True 

133 return False 

134 

135 def get_value(self): 

136 a = {} 

137 for key in self._keys: 

138 key_object = getattr(self, key) 

139 if key_object.exists() is False: 

140 continue 

141 a[key] = getattr(self, key).get_value() 

142 return a 

143 

144 def get(self, key: str, default=None): 

145 """ 

146 return the value of a key 

147 """ 

148 if key not in self._keys: 

149 return default 

150 v = self.__dict__[key] 

151 if v.exists() is False: 

152 return default 

153 return v 

154 

155 def set_value_without_checks(self, value): 

156 for key in self._keys: 

157 if key in value: 

158 v = value.get(key) 

159 self.__dict__[key].set_value_without_checks(v) 

160 

161 def auto_set(self): 

162 """ 

163 compute automatically a value because another value as changed somewhere. 

164 (related to set=flag) and call to all subs 

165 """ 

166 if self.am_i_root() is True: 

167 if self.__dict__["currently_doing_autoset"] is True: 

168 return 

169 self.__dict__["currently_doing_autoset"] = True 

170 

171 GenericType.auto_set(self) 

172 for key in self._keys: 

173 key_object = getattr(self, key) 

174 if key_object.exists() is False: 

175 continue 

176 key_object.auto_set() 

177 

178 self.__dict__["currently_doing_autoset"] = False 

179 

180 def check(self, value): 

181 #self.check_type(value) 

182 #self.check_constraints(value) 

183 GenericType.check( self, value) 

184 

185 # check reccursively subtypes 

186 if isinstance(value, dict): 

187 for key in self._keys: 

188 key_object = self.__dict__[key] 

189 if key_object.exists() is False: 

190 continue 

191 sub_value = value.get(key) 

192 key_object.check(sub_value) 

193 

194 # check if a non-described value 

195 for key in value: 

196 if key not in self._keys: 

197 raise Error( 

198 ErrorType.UNKNOWNCONTENT, 

199 "Unknown content", 

200 self.path_name() + f".{key}", 

201 ) 

202 return 

203 

204 if isinstance(value, Dict): 

205 for key in self._keys: 

206 key_object = self.__dict__[key] 

207 if key_object.exists() is False: 

208 continue 

209 

210 sub_value = value.get(key).get_value() 

211 key_object.check(sub_value) 

212 return 

213 

214 def check_type(self, value): 

215 """ 

216 check if conplain to model or raise an 

217 """ 

218 if isinstance(value, dict): 

219 return True 

220 

221 if isinstance(value, Dict): 

222 return True 

223 

224 raise Error(ErrorType.NOTALIST, "Must be a dict", self.path_name()) 

225 

226 def check_constraints(self, value): 

227 GenericType.check_constraints(self, value) 

228 return True