Browse Source

Bugfixes in Backref process refs #131 and in Integer dh

Triggered a bug in wrong Integer DH tests
Yann Weber 8 years ago
parent
commit
66d08738dc

+ 6
- 5
lodel/leapi/datahandlers/datas_base.py View File

46
     #@return value
46
     #@return value
47
     def _check_data_value(self, value, strict = False):
47
     def _check_data_value(self, value, strict = False):
48
         value = super()._check_data_value(value)
48
         value = super()._check_data_value(value)
49
-        if (strict and isinstance(value, int)):
50
-            raise FieldValidationError("The value '%s' is not a python type integer" % value)
51
         try:
49
         try:
52
-            tv = float(value)
53
-            if tv != int(value):
54
-                raise TypeError()
50
+            if strict:
51
+                if float(value) != int(value):
52
+                    raise FieldValidationError("The value '%s' is castable \
53
+into integer. But the DataHandler is strict and there is a floating part")
54
+            else:
55
+                value = int(value)
55
         except(ValueError, TypeError):
56
         except(ValueError, TypeError):
56
             raise FieldValidationError("The value '%s' is not, and will never, be an integer" % value)
57
             raise FieldValidationError("The value '%s' is not, and will never, be an integer" % value)
57
         return int(value)
58
         return int(value)

+ 49
- 21
plugins/mongodb_datasource/datasource.py View File

101
     #@param offset int: used with limit to choose the start record
101
     #@param offset int: used with limit to choose the start record
102
     #@return list
102
     #@return list
103
     #@todo Implement group for abstract LeObject childs
103
     #@todo Implement group for abstract LeObject childs
104
-    def select(self, target, field_list, filters = None,
105
-        relational_filters=None, order=None, group=None, limit=None, offset=0):
104
+    def select(self, target, field_list, filters = None, 
105
+            relational_filters=None, order=None, group=None, limit=None, 
106
+            offset=0):
107
+        logger.debug("Select %s on %s filtered by %s and %s " % (
108
+            field_list, target, filters, relational_filters))
106
         if target.is_abstract():
109
         if target.is_abstract():
107
             #Reccursiv calls for abstract LeObject child
110
             #Reccursiv calls for abstract LeObject child
108
             results =  self.__act_on_abstract(target, filters,
111
             results =  self.__act_on_abstract(target, filters,
208
         res = self.__collection(target).delete_many(mongo_filters)
211
         res = self.__collection(target).delete_many(mongo_filters)
209
         return res.deleted_count
212
         return res.deleted_count
210
 
213
 
211
-    ## @brief updates records according to given filters
214
+    ##@brief updates records according to given filters
212
     #@param target Emclass : class of the object to insert
215
     #@param target Emclass : class of the object to insert
213
     #@param filters list : List of filters
216
     #@param filters list : List of filters
214
     #@param relational_filters list : List of relational filters
217
     #@param relational_filters list : List of relational filters
215
     #@param upd_datas dict : datas to update (new values)
218
     #@param upd_datas dict : datas to update (new values)
216
     #@return int : Number of updated records
219
     #@return int : Number of updated records
217
     def update(self, target, filters, relational_filters, upd_datas):
220
     def update(self, target, filters, relational_filters, upd_datas):
221
+        res = self.__upodate_no_backref(target, filters, relational_filters,
222
+            upd_datas)
223
+        self.__update_backref_filtered(target, filters, relational_filters,
224
+            upd_datas)
225
+        return res
226
+    
227
+    ##@brief Designed to be called by backref update in order to avoid
228
+    #infinite updates between back references
229
+    #@see update()
230
+    def __update_no_backref(self, target, filters, relational_filters,
231
+            upd_datas):
218
         if target.is_abstract():
232
         if target.is_abstract():
219
             #Update using abstract LeObject as target (reccursiv calls)
233
             #Update using abstract LeObject as target (reccursiv calls)
220
             return self.__act_on_abstract(target, filters,
234
             return self.__act_on_abstract(target, filters,
223
         mongo_filters = self.__process_filters(
237
         mongo_filters = self.__process_filters(
224
             target, filters, relational_filters)
238
             target, filters, relational_filters)
225
         res = self.__collection(target).update(mongo_filters, upd_datas)
239
         res = self.__collection(target).update(mongo_filters, upd_datas)
226
-        self.__update_backref_filtered(target, filters, relational_filters,
227
-            upd_datas)
228
         return res['n']
240
         return res['n']
229
 
241
 
242
+        
243
+
230
     ## @brief Inserts a record in a given collection
244
     ## @brief Inserts a record in a given collection
231
     # @param target Emclass : class of the object to insert
245
     # @param target Emclass : class of the object to insert
232
     # @param new_datas dict : datas to insert
246
     # @param new_datas dict : datas to insert
256
     def __update_backref_filtered(self, target, act,
270
     def __update_backref_filtered(self, target, act,
257
             filters, relational_filters, datas = None):
271
             filters, relational_filters, datas = None):
258
         #gathering datas
272
         #gathering datas
259
-        old_datas_l = target.select(target, None, filters, relational_filters)
273
+        old_datas_l = target.get(target, None, filters, relational_filters)
260
         for old_datas in old_datas_l:
274
         for old_datas in old_datas_l:
261
             self.__update_backref(target, old_datas, datas)
275
             self.__update_backref(target, old_datas, datas)
262
 
276
 
334
                     to_add = []
348
                     to_add = []
335
                 elif not oldd and newd:
349
                 elif not oldd and newd:
336
                     to_del = []
350
                     to_del = []
337
-                    to_add = [new_datas[fname]]
351
+                    to_add = new_datas[fname]
338
                 #Calling __back_ref_upd_one_value() with good arguments
352
                 #Calling __back_ref_upd_one_value() with good arguments
339
                 for vtype, vlist in [('old',to_del), ('new', to_add)]:
353
                 for vtype, vlist in [('old',to_del), ('new', to_add)]:
340
                     for value in vlist:
354
                     for value in vlist:
343
                             bref_cls, value, bref_fname)
357
                             bref_cls, value, bref_fname)
344
                         #preparing the upd_dict
358
                         #preparing the upd_dict
345
                         upd_dict = self.__update_backref_upd_dict_prepare(
359
                         upd_dict = self.__update_backref_upd_dict_prepare(
346
-                            upd_dict, bref_infos)
360
+                            upd_dict, bref_infos, bref_fname, value)
347
                         #preparing updated bref_infos
361
                         #preparing updated bref_infos
348
                         bref_cls, bref_leo, bref_dh, bref_value = bref_infos
362
                         bref_cls, bref_leo, bref_dh, bref_value = bref_infos
349
-                        bref_infos = tuple(bref_cls, bref_leo, bref_dh,
350
-                            upd_dict[bref_cls][uid_val][1][bref_fname])
363
+                        bref_infos = (bref_cls, bref_leo, bref_dh,
364
+                            upd_dict[bref_cls][value][1][bref_fname])
351
                         vdict = {vtype: value}
365
                         vdict = {vtype: value}
352
                         #fetch and store updated value
366
                         #fetch and store updated value
353
                         new_bref_val = self.__back_ref_upd_one_value(
367
                         new_bref_val = self.__back_ref_upd_one_value(
354
                             fname, fdh, bref_infos, **vdict)
368
                             fname, fdh, bref_infos, **vdict)
355
-                        upd_dict[bref_cls][uid_val][1][bref_fname] = new_bref_val
369
+                        upd_dict[bref_cls][value][1][bref_fname] = new_bref_val
356
             else:
370
             else:
357
                 #fdh is a single ref so the process is simpler, we do not have
371
                 #fdh is a single ref so the process is simpler, we do not have
358
                 #to loop and we may do an update in only one
372
                 #to loop and we may do an update in only one
371
                     bref_cls, uid_val, bref_fname)
385
                     bref_cls, uid_val, bref_fname)
372
                 #prepare the upd_dict
386
                 #prepare the upd_dict
373
                 upd_dict = self.__update_backref_upd_dict_prepare(
387
                 upd_dict = self.__update_backref_upd_dict_prepare(
374
-                    upd_dict, bref_infos)
388
+                    upd_dict, bref_infos, bref_fname, uid_val)
375
                 #forging update bref_infos
389
                 #forging update bref_infos
376
                 bref_cls, bref_leo, bref_dh, bref_value = bref_infos
390
                 bref_cls, bref_leo, bref_dh, bref_value = bref_infos
377
                 bref_infos = tuple(bref_cls, bref_leo, bref_dh,
391
                 bref_infos = tuple(bref_cls, bref_leo, bref_dh,
384
         #running the updates
398
         #running the updates
385
         for bref_cls, uid_dict in upd_dict.items():
399
         for bref_cls, uid_dict in upd_dict.items():
386
             for uidval, (leo, datas) in uid_dict.items():
400
             for uidval, (leo, datas) in uid_dict.items():
387
-                leo.update(datas)
401
+                #MULTIPLE UID BROKEN 2 LINES BELOW
402
+                self.__update_no_backref(
403
+                    leo.__class__, [(leo.uid_fieldname()[0], '=', uidval)],
404
+                    [], datas)
388
     
405
     
389
     ##@brief Utility function designed to handle the upd_dict of 
406
     ##@brief Utility function designed to handle the upd_dict of 
390
     #__update_backref()
407
     #__update_backref()
391
     #
408
     #
409
+    #Basically checks if a key exists at some level, if not create it with
410
+    #the good default value (in most case dict())
392
     #@param upd_dict dict : in & out args modified by reference
411
     #@param upd_dict dict : in & out args modified by reference
393
     #@param bref_infos tuple : as returned by __bref_get_check()
412
     #@param bref_infos tuple : as returned by __bref_get_check()
413
+    #@param bref_fname str : name of the field in referenced class
414
+    #@param uid_val mixed : the UID of the referenced object
394
     #@return the updated version of upd_dict
415
     #@return the updated version of upd_dict
395
     @staticmethod
416
     @staticmethod
396
-    def __update_backref_upd_dict_prepare(upd_dict,bref_infos):
417
+    def __update_backref_upd_dict_prepare(upd_dict,bref_infos, bref_fname, 
418
+            uid_val):
397
         bref_cls, bref_leo, bref_dh, bref_value = bref_infos
419
         bref_cls, bref_leo, bref_dh, bref_value = bref_infos
398
         if bref_cls not in upd_dict:
420
         if bref_cls not in upd_dict:
399
             upd_dict[bref_cls] = {}
421
             upd_dict[bref_cls] = {}
400
         if uid_val not in upd_dict[bref_cls]:
422
         if uid_val not in upd_dict[bref_cls]:
401
-            upd_dict[bref_cls][uid_val] = tuple(bref_leo, {})
423
+            upd_dict[bref_cls][uid_val] = (bref_leo, {})
402
         if bref_fname not in upd_dict[bref_cls][uid_val]:
424
         if bref_fname not in upd_dict[bref_cls][uid_val]:
403
             upd_dict[bref_cls][uid_val][1][bref_fname] = bref_value
425
             upd_dict[bref_cls][uid_val][1][bref_fname] = bref_value
404
         return upd_dict
426
         return upd_dict
419
             #
441
             #
420
             # We got an old value. It can be an update or a delete
442
             # We got an old value. It can be an update or a delete
421
             #
443
             #
422
-            old_value = old_datas[fname]
444
+            old_value = values['old']
423
             bref_cls, bref_leo, bref_dh, bref_val = self.__bref_get_check(
445
             bref_cls, bref_leo, bref_dh, bref_val = self.__bref_get_check(
424
                 bref_cls, old_value, bref_fname)
446
                 bref_cls, old_value, bref_fname)
425
             if issubclass(bref_dh.__class__, MultipleRef):
447
             if issubclass(bref_dh.__class__, MultipleRef):
442
                         if val == old_value:
464
                         if val == old_value:
443
                             if newd:
465
                             if newd:
444
                                 #Update
466
                                 #Update
445
-                                bref_val[ki] = new_datas[fname]
467
+                                bref_val[ki] = values['new']
446
                             else:
468
                             else:
447
                                 #Deletion
469
                                 #Deletion
448
                                 del(bref_val[ki])
470
                                 del(bref_val[ki])
452
 raised ! We just checked that oldv is in bref_val...")
474
 raised ! We just checked that oldv is in bref_val...")
453
             else:
475
             else:
454
                 #Single ref handling
476
                 #Single ref handling
455
-                if bref_val != old_value:
477
+                if bref_val != values['old']:
456
                     raise MongoDbConsistencyError("The value we wanted to \
478
                     raise MongoDbConsistencyError("The value we wanted to \
457
 update do not match excpected value during aback reference  singleReference \
479
 update do not match excpected value during aback reference  singleReference \
458
 update : expected value was '%s' but found '%s' in field '%s' of leo %s" % (
480
 update : expected value was '%s' but found '%s' in field '%s' of leo %s" % (
460
                 
482
                 
461
                 if newd:
483
                 if newd:
462
                     #update
484
                     #update
463
-                    bref_val = new_datas[fname]
485
+                    bref_val = values['new']
464
                 else:
486
                 else:
465
                     #delete
487
                     #delete
466
                     if not hasattr(bref_dh, "default"): 
488
                     if not hasattr(bref_dh, "default"): 
470
                     bref_val = getattr(bref_dh, "default")
492
                     bref_val = getattr(bref_dh, "default")
471
         elif newd:
493
         elif newd:
472
             #It's an "insert"
494
             #It's an "insert"
473
-            new_value = new_datas[fname]
495
+            new_value = values['new']
474
             if issubclass(bref_dh.__class__, MultipleRef):
496
             if issubclass(bref_dh.__class__, MultipleRef):
497
+                if bref_val is None:
498
+                    bref_val = bref_dh.empty()
475
                 if isinstance(bref_val, set):
499
                 if isinstance(bref_val, set):
476
                     bref_val |= set([new_value])
500
                     bref_val |= set([new_value])
477
                 else:
501
                 else:
498
         if len(bref_leo) == 0:
522
         if len(bref_leo) == 0:
499
             raise MongoDbConsistencyError("Unable to get the object we make \
523
             raise MongoDbConsistencyError("Unable to get the object we make \
500
 reference to : %s with uid = %s" % (bref_cls, repr(uidv)))
524
 reference to : %s with uid = %s" % (bref_cls, repr(uidv)))
525
+        if len(bref_leo) > 1:
526
+            raise MongoDbConsistencyFatalError("Will retrieving data with UID \
527
+as filter we got more than one result !!! Bailout !!!")
528
+        bref_leo = bref_leo[0]
501
         bref_dh = bref_leo.data_handler(bref_fname)
529
         bref_dh = bref_leo.data_handler(bref_fname)
502
-        if not isinstance(bref_leo, Reference):
530
+        if not isinstance(bref_dh, Reference):
503
             raise LodelFatalError("Found a back reference field that \
531
             raise LodelFatalError("Found a back reference field that \
504
 is not a reference : '%s' field '%s'" % (bref_leo, bref_fname))
532
 is not a reference : '%s' field '%s'" % (bref_leo, bref_fname))
505
         bref_val = bref_leo.data(bref_fname)
533
         bref_val = bref_leo.data(bref_fname)

+ 6
- 0
plugins/mongodb_datasource/exceptions.py View File

1
+from lodel.exceptions import *
2
+
1
 ##@ingroup plugin_mongodb_datasource
3
 ##@ingroup plugin_mongodb_datasource
2
 class MongoDbDataSourceError(Exception):
4
 class MongoDbDataSourceError(Exception):
3
     pass
5
     pass
6
 class MongoDbConsistencyError(MongoDbDataSourceError):
8
 class MongoDbConsistencyError(MongoDbDataSourceError):
7
     pass
9
     pass
8
 
10
 
11
+##@ingroup plugin_mongodb_datasource
12
+class MongoDbConsistencyFatalError(LodelFatalError):
13
+    pass
14
+
9
 ##@ingroup plugin_mongodb_datasource
15
 ##@ingroup plugin_mongodb_datasource
10
 class MigrationHandlerChangeError(Exception):
16
 class MigrationHandlerChangeError(Exception):
11
     pass
17
     pass

Loading…
Cancel
Save