Coverage for stricto/dict.py: 99%
154 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-29 10:26 +0100
« 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
7class Dict(GenericType):
8 """
9 A Dict Type
10 """
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)
23 GenericType.__init__(self, **kwargs)
25 self.set_hierachy_attributs(self, None, "")
27 self._locked = True
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
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
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)
54 def keys(self):
55 """
56 return all keys
57 """
58 return self._keys
60 def __getitem__(self, k):
61 if k in self._keys:
62 return self.__dict__[k]
63 return None
65 def __setattr__(self, name, value):
66 try:
67 locked = self.__dict__["_locked"]
68 except KeyError:
69 locked = False
71 try:
72 keys = self.__dict__["_keys"]
73 except KeyError:
74 keys = None
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
86 self.__dict__[f"{name}"] = value
88 def copy(self):
89 return copy.copy(self)
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
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__()
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
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
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
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
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)
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
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()
178 self.__dict__["currently_doing_autoset"] = False
180 def check(self, value):
181 #self.check_type(value)
182 #self.check_constraints(value)
183 GenericType.check( self, value)
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)
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
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
210 sub_value = value.get(key).get_value()
211 key_object.check(sub_value)
212 return
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
221 if isinstance(value, Dict):
222 return True
224 raise Error(ErrorType.NOTALIST, "Must be a dict", self.path_name())
226 def check_constraints(self, value):
227 GenericType.check_constraints(self, value)
228 return True