|
@@ -19,7 +19,7 @@ LodelContext.expose_modules(globals(), {
|
19
|
19
|
'DataNoneValid',
|
20
|
20
|
'FieldValidationError'
|
21
|
21
|
],
|
22
|
|
- 'lodel.mlnamedobject.mlnamedobject':['MlNamedObject'],
|
|
22
|
+ 'lodel.mlnamedobject.mlnamedobject': ['MlNamedObject'],
|
23
|
23
|
'lodel.leapi.datahandlers.exceptions': [
|
24
|
24
|
'LodelDataHandlerConsistencyException',
|
25
|
25
|
'LodelDataHandlerException'
|
|
@@ -30,14 +30,14 @@ LodelContext.expose_modules(globals(), {
|
30
|
30
|
'lodel.logger': 'logger'})
|
31
|
31
|
|
32
|
32
|
|
33
|
|
-##@brief Base class for all data handlers
|
34
|
|
-#@ingroup lodel2_datahandlers
|
|
33
|
+## @brief Base class for all data handlers
|
|
34
|
+# @ingroup lodel2_datahandlers
|
35
|
35
|
class DataHandler(MlNamedObject):
|
36
|
36
|
base_type = "type"
|
37
|
37
|
_HANDLERS_MODULES = ('datas_base', 'datas', 'references')
|
38
|
|
- ##@brief Stores the DataHandler childs classes indexed by name
|
|
38
|
+ ## @brief Stores the DataHandler childs classes indexed by name
|
39
|
39
|
_base_handlers = None
|
40
|
|
- ##@brief Stores custom datahandlers classes indexed by name
|
|
40
|
+ ## @brief Stores custom datahandlers classes indexed by name
|
41
|
41
|
# @todo do it ! (like plugins, register handlers... blablabla)
|
42
|
42
|
__custom_handlers = dict()
|
43
|
43
|
|
|
@@ -46,15 +46,16 @@ class DataHandler(MlNamedObject):
|
46
|
46
|
options_spec = dict()
|
47
|
47
|
options_values = dict()
|
48
|
48
|
|
49
|
|
- ##@brief List fields that will be exposed to the construct_data_method
|
|
49
|
+ ## @brief List fields that will be exposed to the construct_data_method
|
50
|
50
|
_construct_datas_deps = []
|
51
|
51
|
|
52
|
52
|
directly_editable = True
|
53
|
|
- ##@brief constructor
|
|
53
|
+
|
|
54
|
+ ## @brief constructor
|
|
55
|
+ #
|
54
|
56
|
# @param internal False | str : define whether or not a field is internal
|
55
|
|
- # @param immutable bool : indicates if the fieldtype has to be defined in child classes of LeObject or if it is
|
56
|
|
- # designed globally and immutable
|
57
|
|
- # @param **args
|
|
57
|
+ # @param immutable bool : indicates if the fieldtype has to be defined in child classes of
|
|
58
|
+ # LeObject or if it is designed globally and immutable
|
58
|
59
|
# @throw NotImplementedError if it is instanciated directly
|
59
|
60
|
def __init__(self, **kwargs):
|
60
|
61
|
if self.__class__ == DataHandler:
|
|
@@ -69,22 +70,24 @@ class DataHandler(MlNamedObject):
|
69
|
70
|
self.default, error = self.check_data_value(kwargs['default'])
|
70
|
71
|
if error:
|
71
|
72
|
raise error
|
72
|
|
- del(kwargs['default'])
|
|
73
|
+ del kwargs['default']
|
73
|
74
|
for argname, argval in kwargs.items():
|
74
|
75
|
setattr(self, argname, argval)
|
75
|
76
|
self.check_options()
|
76
|
77
|
super().__init__(self.display_name, self.help_text)
|
77
|
78
|
|
78
|
79
|
## @brief Sets properly casted and checked options for the datahandler
|
79
|
|
- # @raises LodelDataHandlerNotAllowedOptionException when a passed option is not in the option specifications of the datahandler
|
|
80
|
+ # @raises LodelDataHandlerNotAllowedOptionException when a passed option is not in the option
|
|
81
|
+ # specifications of the datahandler
|
80
|
82
|
def check_options(self):
|
81
|
83
|
for option_name, option_datas in self.options_spec.items():
|
82
|
84
|
if option_name in self.options_values:
|
83
|
85
|
# There is a configured option, we check its value
|
84
|
86
|
try:
|
85
|
|
- self.options_values[option_name] = option_datas[1].check_value(self.options_values[option_name])
|
|
87
|
+ self.options_values[option_name] = option_datas[1].check_value(
|
|
88
|
+ self.options_values[option_name])
|
86
|
89
|
except ValueError:
|
87
|
|
- pass # TODO Deal with the case where the value used for an option has not been validated
|
|
90
|
+ pass # TODO Deal with the case where the value used for an option is invalid
|
88
|
91
|
else:
|
89
|
92
|
# This option was not configured, we get the default value from the specs
|
90
|
93
|
self.options_values[option_name] = option_datas[0]
|
|
@@ -105,15 +108,15 @@ class DataHandler(MlNamedObject):
|
105
|
108
|
def is_primary_key(self):
|
106
|
109
|
return self.primary_key
|
107
|
110
|
|
108
|
|
- ##@brief checks if a fieldtype is internal
|
|
111
|
+ ## @brief checks if a fieldtype is internal
|
109
|
112
|
# @return bool
|
110
|
113
|
def is_internal(self):
|
111
|
114
|
return self.internal is not False
|
112
|
115
|
|
113
|
|
- ##brief check if a value can be nullable
|
114
|
|
- #@param value *
|
115
|
|
- #@throw DataNoneValid if value is None and nullable. LodelExceptions if not nullable
|
116
|
|
- #@return value (if not None)
|
|
116
|
+ ## @brief check if a value can be nullable
|
|
117
|
+ # @param value *
|
|
118
|
+ # @throw DataNoneValid if value is None and nullable. LodelExceptions if not nullable
|
|
119
|
+ # @return value (if not None)
|
117
|
120
|
# @return value
|
118
|
121
|
def _check_data_value(self, value):
|
119
|
122
|
if value is None:
|
|
@@ -122,9 +125,9 @@ class DataHandler(MlNamedObject):
|
122
|
125
|
raise DataNoneValid("None with a nullable. This exeption is allowed")
|
123
|
126
|
return value
|
124
|
127
|
|
125
|
|
- ##@brief calls the data_field (defined in derived class) _check_data_value() method
|
126
|
|
- #@param value *
|
127
|
|
- #@return tuple (value|None, None|error) value can be cast if NoneError
|
|
128
|
+ ## @brief calls the data_field (defined in derived class) _check_data_value() method
|
|
129
|
+ # @param value *
|
|
130
|
+ # @return tuple (value|None, None|error) value can be cast if NoneError
|
128
|
131
|
def check_data_value(self, value):
|
129
|
132
|
try:
|
130
|
133
|
value = self._check_data_value(value)
|
|
@@ -134,7 +137,7 @@ class DataHandler(MlNamedObject):
|
134
|
137
|
return None, expt
|
135
|
138
|
return value, None
|
136
|
139
|
|
137
|
|
- ##@brief checks if this class can override the given data handler
|
|
140
|
+ ## @brief checks if this class can override the given data handler
|
138
|
141
|
# @param data_handler DataHandler
|
139
|
142
|
# @return bool
|
140
|
143
|
def can_override(self, data_handler):
|
|
@@ -142,17 +145,17 @@ class DataHandler(MlNamedObject):
|
142
|
145
|
return False
|
143
|
146
|
return True
|
144
|
147
|
|
145
|
|
- ##@brief Build field value
|
146
|
|
- #@ingroup lodel2_dh_checks
|
147
|
|
- #@warning DO NOT REIMPLEMENT THIS METHOD IN A CUSTOM DATAHANDLER (see
|
148
|
|
- #@ref _construct_data() and @ref lodel2_dh_check_impl )
|
149
|
|
- #@param emcomponent EmComponent : An EmComponent child class instance
|
150
|
|
- #@param fname str : The field name
|
151
|
|
- #@param datas dict : dict storing fields values (from the component)
|
152
|
|
- #@param cur_value : the value from the current field (identified by fieldname)
|
153
|
|
- #@return the value
|
154
|
|
- #@throw RunTimeError if data construction fails
|
155
|
|
- #@todo raise something else
|
|
148
|
+ ## @brief Build field value
|
|
149
|
+ # @ingroup lodel2_dh_checks
|
|
150
|
+ # @warning DO NOT REIMPLEMENT THIS METHOD IN A CUSTOM DATAHANDLER (see
|
|
151
|
+ # @ref _construct_data() and @ref lodel2_dh_check_impl )
|
|
152
|
+ # @param emcomponent EmComponent : An EmComponent child class instance
|
|
153
|
+ # @param fname str : The field name
|
|
154
|
+ # @param datas dict : dict storing fields values (from the component)
|
|
155
|
+ # @param cur_value : the value from the current field (identified by fieldname)
|
|
156
|
+ # @return the value
|
|
157
|
+ # @throw RunTimeError if data construction fails
|
|
158
|
+ # @todo raise something else
|
156
|
159
|
def construct_data(self, emcomponent, fname, datas, cur_value):
|
157
|
160
|
emcomponent_fields = emcomponent.fields()
|
158
|
161
|
data_handler = None
|
|
@@ -167,41 +170,41 @@ class DataHandler(MlNamedObject):
|
167
|
170
|
new_val = None
|
168
|
171
|
return self._construct_data(emcomponent, fname, datas, new_val)
|
169
|
172
|
|
170
|
|
- ##@brief Designed to be reimplemented by child classes
|
171
|
|
- #@param emcomponent EmComponent : An EmComponent child class instance
|
172
|
|
- #@param fname str : The field name
|
173
|
|
- #@param datas dict : dict storing fields values (from the component)
|
174
|
|
- #@param cur_value : the value from the current field (identified by fieldname)
|
175
|
|
- #@return the value
|
176
|
|
- #@see construct_data() lodel2_dh_check_impl
|
|
173
|
+ ## @brief Designed to be reimplemented by child classes
|
|
174
|
+ # @param emcomponent EmComponent : An EmComponent child class instance
|
|
175
|
+ # @param fname str : The field name
|
|
176
|
+ # @param datas dict : dict storing fields values (from the component)
|
|
177
|
+ # @param cur_value : the value from the current field (identified by fieldname)
|
|
178
|
+ # @return the value
|
|
179
|
+ # @see construct_data() lodel2_dh_check_impl
|
177
|
180
|
def _construct_data(self, empcomponent, fname, datas, cur_value):
|
178
|
181
|
return cur_value
|
179
|
182
|
|
180
|
|
- ##@brief Check datas consistency
|
181
|
|
- #@ingroup lodel2_dh_checks
|
182
|
|
- #@warning DO NOT REIMPLEMENT THIS METHOD IN A CUSTOM DATAHANDLER (see
|
183
|
|
- #@ref _construct_data() and @ref lodel2_dh_check_impl )
|
184
|
|
- #@warning the datas argument looks like a dict but is not a dict
|
185
|
|
- #see @ref base_classes.DatasConstructor "DatasConstructor" and
|
186
|
|
- #@ref lodel2_dh_datas_construction "Datas construction section"
|
187
|
|
- #@param emcomponent EmComponent : An EmComponent child class instance
|
188
|
|
- #@param fname : the field name
|
189
|
|
- #@param datas dict : dict storing fields values
|
190
|
|
- #@return an Exception instance if fails else True
|
191
|
|
- #@todo A implémenter
|
|
183
|
+ ## @brief Check datas consistency
|
|
184
|
+ # @ingroup lodel2_dh_checks
|
|
185
|
+ # @warning DO NOT REIMPLEMENT THIS METHOD IN A CUSTOM DATAHANDLER (see
|
|
186
|
+ # @ref _construct_data() and @ref lodel2_dh_check_impl )
|
|
187
|
+ # @warning the datas argument looks like a dict but is not a dict
|
|
188
|
+ # see @ref base_classes.DatasConstructor "DatasConstructor" and
|
|
189
|
+ # @ref lodel2_dh_datas_construction "Datas construction section"
|
|
190
|
+ # @param emcomponent EmComponent : An EmComponent child class instance
|
|
191
|
+ # @param fname : the field name
|
|
192
|
+ # @param datas dict : dict storing fields values
|
|
193
|
+ # @return an Exception instance if fails else True
|
|
194
|
+ # @todo A implémenter
|
192
|
195
|
def check_data_consistency(self, emcomponent, fname, datas):
|
193
|
196
|
return self._check_data_consistency(emcomponent, fname, datas)
|
194
|
197
|
|
195
|
|
- ##@brief Designed to be reimplemented by child classes
|
196
|
|
- #@param emcomponent EmComponent : An EmComponent child class instance
|
197
|
|
- #@param fname : the field name
|
198
|
|
- #@param datas dict : dict storing fields values
|
199
|
|
- #@return an Exception instance if fails else True
|
200
|
|
- #@see check_data_consistency() lodel2_dh_check_impl
|
|
198
|
+ ## @brief Designed to be reimplemented by child classes
|
|
199
|
+ # @param emcomponent EmComponent : An EmComponent child class instance
|
|
200
|
+ # @param fname : the field name
|
|
201
|
+ # @param datas dict : dict storing fields values
|
|
202
|
+ # @return an Exception instance if fails else True
|
|
203
|
+ # @see check_data_consistency() lodel2_dh_check_impl
|
201
|
204
|
def _check_data_consistency(self, emcomponent, fname, datas):
|
202
|
205
|
return True
|
203
|
206
|
|
204
|
|
- ##@brief make consistency after a query
|
|
207
|
+ ## @brief make consistency after a query
|
205
|
208
|
# @param emcomponent EmComponent : An EmComponent child class instance
|
206
|
209
|
# @param fname : the field name
|
207
|
210
|
# @param datas dict : dict storing fields values
|
|
@@ -210,7 +213,7 @@ class DataHandler(MlNamedObject):
|
210
|
213
|
def make_consistency(self, emcomponent, fname, datas):
|
211
|
214
|
pass
|
212
|
215
|
|
213
|
|
- ##@brief This method is use by plugins to register new data handlers
|
|
216
|
+ ## @brief This method is use by plugins to register new data handlers
|
214
|
217
|
@classmethod
|
215
|
218
|
def register_new_handler(cls, name, data_handler):
|
216
|
219
|
if not inspect.isclass(data_handler):
|
|
@@ -219,7 +222,7 @@ class DataHandler(MlNamedObject):
|
219
|
222
|
raise ValueError("A data handler HAS TO be a child class of DataHandler")
|
220
|
223
|
cls.__custom_handlers[name] = data_handler
|
221
|
224
|
|
222
|
|
- ##@brief Load all datahandlers
|
|
225
|
+ ## @brief Load all datahandlers
|
223
|
226
|
@classmethod
|
224
|
227
|
def load_base_handlers(cls):
|
225
|
228
|
if cls._base_handlers is None:
|
|
@@ -232,10 +235,11 @@ class DataHandler(MlNamedObject):
|
232
|
235
|
cls._base_handlers[name.lower()] = obj
|
233
|
236
|
return copy.copy(cls._base_handlers)
|
234
|
237
|
|
235
|
|
- ##@brief given a field type name, returns the associated python class
|
|
238
|
+ ## @brief given a field type name, returns the associated python class
|
236
|
239
|
# @param fieldtype_name str : A field type name (not case sensitive)
|
237
|
240
|
# @return DataField child class
|
238
|
|
- # @note To access custom data handlers it can be cool to prefix the handler name by plugin name for example ? (to ensure name unicity)
|
|
241
|
+ # @note To access custom data handlers it can be cool to prefix the handler name by plugin
|
|
242
|
+ # name for example ? (to ensure name unicity)
|
239
|
243
|
@classmethod
|
240
|
244
|
def from_name(cls, name):
|
241
|
245
|
cls.load_base_handlers()
|
|
@@ -245,7 +249,7 @@ class DataHandler(MlNamedObject):
|
245
|
249
|
raise NameError("No data handlers named '%s'" % (name,))
|
246
|
250
|
return all_handlers[name]
|
247
|
251
|
|
248
|
|
- ##@brief Return the module name to import in order to use the datahandler
|
|
252
|
+ ## @brief Return the module name to import in order to use the datahandler
|
249
|
253
|
# @param data_handler_name str : Data handler name
|
250
|
254
|
# @return a str
|
251
|
255
|
@classmethod
|
|
@@ -253,62 +257,64 @@ class DataHandler(MlNamedObject):
|
253
|
257
|
name = name.lower()
|
254
|
258
|
handler_class = cls.from_name(name)
|
255
|
259
|
return '{module_name}.{class_name}'.format(
|
256
|
|
- module_name=handler_class.__module__,
|
257
|
|
- class_name=handler_class.__name__
|
|
260
|
+ module_name=handler_class.__module__,
|
|
261
|
+ class_name=handler_class.__name__
|
258
|
262
|
)
|
259
|
263
|
|
260
|
|
- ##@brief __hash__ implementation for fieldtypes
|
|
264
|
+ ## @brief __hash__ implementation for fieldtypes
|
261
|
265
|
def __hash__(self):
|
262
|
266
|
hash_dats = [self.__class__.__module__]
|
263
|
267
|
for kdic in sorted([k for k in self.__dict__.keys() if not k.startswith('_')]):
|
264
|
268
|
hash_dats.append((kdic, getattr(self, kdic)))
|
265
|
269
|
return hash(tuple(hash_dats))
|
266
|
270
|
|
267
|
|
-##@brief Base class for datas data handler (by opposition with references)
|
268
|
|
-#@ingroup lodel2_datahandlers
|
|
271
|
+## @brief Base class for datas data handler (by opposition with references)
|
|
272
|
+# @ingroup lodel2_datahandlers
|
269
|
273
|
class DataField(DataHandler):
|
270
|
274
|
pass
|
271
|
275
|
|
272
|
|
-##@brief Abstract class for all references
|
273
|
|
-#@ingroup lodel2_datahandlers
|
|
276
|
+
|
|
277
|
+## @brief Abstract class for all references
|
|
278
|
+# @ingroup lodel2_datahandlers
|
274
|
279
|
#
|
275
|
280
|
# References are fields that stores a reference to another
|
276
|
281
|
# editorial object
|
277
|
|
-#@todo Construct data implementation : transform the data into a LeObject
|
278
|
|
-#instance
|
279
|
|
-
|
|
282
|
+# @todo Construct data implementation : transform the data into a LeObject instance
|
280
|
283
|
class Reference(DataHandler):
|
281
|
284
|
base_type = "ref"
|
282
|
285
|
|
283
|
|
- ##@brief Instanciation
|
|
286
|
+ ## @brief Instanciation
|
284
|
287
|
# @param allowed_classes list | None : list of allowed em classes if None no restriction
|
285
|
288
|
# @param back_reference tuple | None : tuple containing (LeObject child class, fieldname)
|
286
|
289
|
# @param internal bool : if False, the field is not internal
|
287
|
290
|
# @param **kwargs : other arguments
|
288
|
291
|
def __init__(self, allowed_classes=None, back_reference=None, internal=False, **kwargs):
|
289
|
292
|
self.__allowed_classes = set() if allowed_classes is None else set(allowed_classes)
|
290
|
|
- self.allowed_classes = list() if allowed_classes is None else allowed_classes # For now usefull to jinja 2
|
|
293
|
+ # For now usefull to jinja 2
|
|
294
|
+ self.allowed_classes = list() if allowed_classes is None else allowed_classes
|
291
|
295
|
if back_reference is not None:
|
292
|
296
|
if len(back_reference) != 2:
|
293
|
297
|
raise ValueError("A tuple (classname, fieldname) expected but got '%s'" % back_reference)
|
294
|
|
- #if not issubclass(lodel.leapi.leobject.LeObject, back_reference[0]) or not isinstance(back_reference[1], str):
|
295
|
|
- # raise TypeError("Back reference was expected to be a tuple(<class LeObject>, str) but got : (%s, %s)" % (back_reference[0], back_reference[1]))
|
|
298
|
+ # if not issubclass(lodel.leapi.leobject.LeObject, back_reference[0])
|
|
299
|
+ # or not isinstance(back_reference[1], str):
|
|
300
|
+ # raise TypeError("Back reference was expected to be a tuple(<class LeObject>, str)
|
|
301
|
+ # but got : (%s, %s)" % (back_reference[0], back_reference[1]))
|
296
|
302
|
self.__back_reference = back_reference
|
297
|
303
|
super().__init__(internal=internal, **kwargs)
|
298
|
304
|
|
299
|
|
- ##@brief Method designed to return an empty value for this kind of
|
300
|
|
- #multipleref
|
|
305
|
+ ## @brief Method designed to return an empty value for this kind of
|
|
306
|
+ # multipleref
|
301
|
307
|
@classmethod
|
302
|
308
|
def empty(cls):
|
303
|
309
|
return None
|
304
|
310
|
|
305
|
|
- ##@brief Property that takes value of a copy of the back_reference tuple
|
|
311
|
+ ## @brief Property that takes value of a copy of the back_reference tuple
|
306
|
312
|
@property
|
307
|
313
|
def back_reference(self):
|
308
|
314
|
return copy.copy(self.__back_reference)
|
309
|
315
|
|
310
|
|
- ##@brief Property that takes value of datahandler of the backreference or
|
311
|
|
- #None
|
|
316
|
+ ## @brief Property that takes value of datahandler of the backreference or
|
|
317
|
+ # None
|
312
|
318
|
@property
|
313
|
319
|
def back_ref_datahandler(self):
|
314
|
320
|
if self.__back_reference is None:
|
|
@@ -319,15 +325,15 @@ class Reference(DataHandler):
|
319
|
325
|
def linked_classes(self):
|
320
|
326
|
return copy.copy(self.__allowed_classes)
|
321
|
327
|
|
322
|
|
- ##@brief Set the back reference for this field.
|
|
328
|
+ ## @brief Set the back reference for this field.
|
323
|
329
|
def _set_back_reference(self, back_reference):
|
324
|
330
|
self.__back_reference = back_reference
|
325
|
331
|
|
326
|
|
- ##@brief Check and cast value in appropriate type
|
327
|
|
- #@param value *
|
328
|
|
- #@throw FieldValidationError if value is an appropriate type
|
329
|
|
- #@return value
|
330
|
|
- #@todo implement the check when we have LeObject uid check value
|
|
332
|
+ ## @brief Check and cast value in appropriate type
|
|
333
|
+ # @param value *
|
|
334
|
+ # @throw FieldValidationError if value is an appropriate type
|
|
335
|
+ # @return value
|
|
336
|
+ # @todo implement the check when we have LeObject uid check value
|
331
|
337
|
def _check_data_value(self, value):
|
332
|
338
|
from lodel.leapi.leobject import LeObject
|
333
|
339
|
value = super()._check_data_value(value)
|
|
@@ -342,13 +348,13 @@ class Reference(DataHandler):
|
342
|
348
|
raise FieldValidationError("Reference datahandler can not check this value %s if any allowed_class is allowed." % value)
|
343
|
349
|
return value
|
344
|
350
|
|
345
|
|
- ##@brief Check datas consistency
|
346
|
|
- #@param emcomponent EmComponent : An EmComponent child class instance
|
347
|
|
- #@param fname : the field name
|
348
|
|
- #@param datas dict : dict storing fields values
|
349
|
|
- #@return an Exception instance if fails else True
|
350
|
|
- #@todo check for performance issue and check logics
|
351
|
|
- #@warning composed uid capabilities broken here
|
|
351
|
+ ## @brief Check datas consistency
|
|
352
|
+ # @param emcomponent EmComponent : An EmComponent child class instance
|
|
353
|
+ # @param fname : the field name
|
|
354
|
+ # @param datas dict : dict storing fields values
|
|
355
|
+ # @return an Exception instance if fails else True
|
|
356
|
+ # @todo check for performance issue and check logics
|
|
357
|
+ # @warning composed uid capabilities broken here
|
352
|
358
|
def check_data_consistency(self, emcomponent, fname, datas):
|
353
|
359
|
rep = super().check_data_consistency(emcomponent, fname, datas)
|
354
|
360
|
if isinstance(rep, Exception):
|
|
@@ -364,21 +370,21 @@ class Reference(DataHandler):
|
364
|
370
|
if not target_class.is_exist(value):
|
365
|
371
|
logger.warning('Object referenced does not exist')
|
366
|
372
|
return False
|
367
|
|
- #target_uidfield = target_class.uid_fieldname()[0] #multi uid broken here
|
368
|
|
- #obj = target_class.get([(target_uidfield, '=', value)])
|
369
|
|
- #if len(obj) == 0:
|
|
373
|
+ # target_uidfield = target_class.uid_fieldname()[0] #multi uid broken here
|
|
374
|
+ # obj = target_class.get([(target_uidfield, '=', value)])
|
|
375
|
+ # if len(obj) == 0:
|
370
|
376
|
# logger.warning('Object referenced does not exist')
|
371
|
377
|
# return False
|
372
|
378
|
return True
|
373
|
379
|
|
374
|
|
- ##@brief Utility method designed to fetch referenced objects
|
375
|
|
- #@param value mixed : the field value
|
376
|
|
- #@throw NotImplementedError
|
|
380
|
+ ## @brief Utility method designed to fetch referenced objects
|
|
381
|
+ # @param value mixed : the field value
|
|
382
|
+ # @throw NotImplementedError
|
377
|
383
|
def get_referenced(self, value):
|
378
|
384
|
raise NotImplementedError
|
379
|
385
|
|
380
|
386
|
|
381
|
|
-##@brief This class represent a data_handler for single reference to another object
|
|
387
|
+## @brief This class represent a data_handler for single reference to another object
|
382
|
388
|
#
|
383
|
389
|
# The fields using this data handlers are like "foreign key" on another object
|
384
|
390
|
class SingleRef(Reference):
|
|
@@ -387,18 +393,18 @@ class SingleRef(Reference):
|
387
|
393
|
super().__init__(allowed_classes=allowed_classes, **kwargs)
|
388
|
394
|
|
389
|
395
|
|
390
|
|
- ##@brief Check and cast value in appropriate type
|
391
|
|
- #@param value: *
|
392
|
|
- #@throw FieldValidationError if value is unappropriate or can not be cast
|
393
|
|
- #@return value
|
|
396
|
+ ## @brief Check and cast value in appropriate type
|
|
397
|
+ # @param value: *
|
|
398
|
+ # @throw FieldValidationError if value is unappropriate or can not be cast
|
|
399
|
+ # @return value
|
394
|
400
|
def _check_data_value(self, value):
|
395
|
401
|
value = super()._check_data_value(value)
|
396
|
402
|
return value
|
397
|
403
|
|
398
|
|
- ##@brief Utility method designed to fetch referenced objects
|
399
|
|
- #@param value mixed : the field value
|
400
|
|
- #@return A LeObject child class instance
|
401
|
|
- #@throw LodelDataHandlerConsistencyException if no referenced object found
|
|
404
|
+ ## @brief Utility method designed to fetch referenced objects
|
|
405
|
+ # @param value mixed : the field value
|
|
406
|
+ # @return A LeObject child class instance
|
|
407
|
+ # @throw LodelDataHandlerConsistencyException if no referenced object found
|
402
|
408
|
def get_referenced(self, value):
|
403
|
409
|
for leo_cls in self.linked_classes:
|
404
|
410
|
res = leo_cls.get_from_uid(value)
|
|
@@ -408,30 +414,30 @@ class SingleRef(Reference):
|
408
|
414
|
referenced object with uid %s" % value)
|
409
|
415
|
|
410
|
416
|
|
411
|
|
-##@brief This class represent a data_handler for multiple references to another object
|
412
|
|
-#@ingroup lodel2_datahandlers
|
|
417
|
+## @brief This class represent a data_handler for multiple references to another object
|
|
418
|
+# @ingroup lodel2_datahandlers
|
413
|
419
|
#
|
414
|
420
|
# The fields using this data handlers are like SingleRef but can store multiple references in one field
|
415
|
421
|
# @note for the moment split on ',' chars
|
416
|
422
|
class MultipleRef(Reference):
|
417
|
423
|
|
418
|
|
- ##
|
|
424
|
+ ## @brief Constructor
|
419
|
425
|
# @param max_item int | None : indicate the maximum number of item referenced by this field, None mean no limit
|
420
|
426
|
def __init__(self, max_item=None, **kwargs):
|
421
|
427
|
self.max_item = max_item
|
422
|
428
|
super().__init__(**kwargs)
|
423
|
429
|
|
424
|
|
- ##@brief Method designed to return an empty value for this kind of
|
425
|
|
- #multipleref
|
|
430
|
+ ## @brief Method designed to return an empty value for this kind of
|
|
431
|
+ # multipleref
|
426
|
432
|
@classmethod
|
427
|
433
|
def empty(cls):
|
428
|
434
|
return []
|
429
|
435
|
|
430
|
|
- ##@brief Check and cast value in appropriate type
|
431
|
|
- #@param value *
|
432
|
|
- #@throw FieldValidationError if value is unappropriate or can not be cast
|
433
|
|
- #@return value
|
434
|
|
- #@TODO Writing test error for errors when stored multiple references in one field
|
|
436
|
+ ## @brief Check and cast value in appropriate type
|
|
437
|
+ # @param value *
|
|
438
|
+ # @throw FieldValidationError if value is unappropriate or can not be cast
|
|
439
|
+ # @return value
|
|
440
|
+ # @TODO Writing test error for errors when stored multiple references in one field
|
435
|
441
|
def _check_data_value(self, value):
|
436
|
442
|
value = DataHandler._check_data_value(self, value)
|
437
|
443
|
if not hasattr(value, '__iter__'):
|
|
@@ -451,11 +457,11 @@ class MultipleRef(Reference):
|
451
|
457
|
raise FieldValidationError("MultipleRef have for invalid values [%s] :" % (",".join(error_list)))
|
452
|
458
|
return new_val
|
453
|
459
|
|
454
|
|
- ##@brief Utility method designed to fetch referenced objects
|
455
|
|
- #@param values mixed : the field values
|
456
|
|
- #@return A list of LeObject child class instance
|
457
|
|
- #@throw LodelDataHandlerConsistencyException if some referenced objects
|
458
|
|
- #were not found
|
|
460
|
+ ## @brief Utility method designed to fetch referenced objects
|
|
461
|
+ # @param values mixed : the field values
|
|
462
|
+ # @return A list of LeObject child class instance
|
|
463
|
+ # @throw LodelDataHandlerConsistencyException if some referenced objects
|
|
464
|
+ # were not found
|
459
|
465
|
def get_referenced(self, values):
|
460
|
466
|
if values is None or len(values) == 0:
|
461
|
467
|
return list()
|
|
@@ -463,18 +469,19 @@ class MultipleRef(Reference):
|
463
|
469
|
values = set(values)
|
464
|
470
|
res = list()
|
465
|
471
|
for leo_cls in self.linked_classes:
|
466
|
|
- uidname = leo_cls.uid_fieldname()[0] #MULTIPLE UID BROKEN HERE
|
|
472
|
+ uidname = leo_cls.uid_fieldname()[0] # MULTIPLE UID BROKEN HERE
|
467
|
473
|
tmp_res = leo_cls.get(('%s in (%s)' % (uidname, ','.join(
|
468
|
474
|
[str(l) for l in left]))))
|
469
|
|
- left ^= set(( leo.uid() for leo in tmp_res))
|
|
475
|
+ left ^= set((leo.uid() for leo in tmp_res))
|
470
|
476
|
res += tmp_res
|
471
|
477
|
if len(left) == 0:
|
472
|
478
|
return res
|
473
|
479
|
raise LodelDataHandlerConsistencyException("Unable to find \
|
474
|
480
|
some referenced objects. Following uids were not found : %s" % ','.join(left))
|
475
|
481
|
|
|
482
|
+
|
476
|
483
|
## @brief Class designed to handle datas access will fieldtypes are constructing datas
|
477
|
|
-#@ingroup lodel2_datahandlers
|
|
484
|
+# @ingroup lodel2_datahandlers
|
478
|
485
|
#
|
479
|
486
|
# This class is designed to allow automatic scheduling of construct_data calls.
|
480
|
487
|
#
|
|
@@ -488,15 +495,15 @@ class DatasConstructor(object):
|
488
|
495
|
# @param datas dict : dict with field name as key and field values as value
|
489
|
496
|
# @param fields_handler dict : dict with field name as key and data handler instance as value
|
490
|
497
|
def __init__(self, leobject, datas, fields_handler):
|
491
|
|
- ## Stores concerned class
|
|
498
|
+ # Stores concerned class
|
492
|
499
|
self._leobject = leobject
|
493
|
|
- ## Stores datas and constructed datas
|
|
500
|
+ # Stores datas and constructed datas
|
494
|
501
|
self._datas = copy.copy(datas)
|
495
|
|
- ## Stores fieldtypes
|
|
502
|
+ # Stores fieldtypes
|
496
|
503
|
self._fields_handler = fields_handler
|
497
|
|
- ## Stores list of fieldname for constructed datas
|
|
504
|
+ # Stores list of fieldname for constructed datas
|
498
|
505
|
self._constructed = []
|
499
|
|
- ## Stores construct calls list
|
|
506
|
+ # Stores construct calls list
|
500
|
507
|
self._construct_calls = []
|
501
|
508
|
|
502
|
509
|
## @brief Implements the dict.keys() method on instance
|