Преглед на файлове

Bugfixes in Backref process refs #131 and in Integer dh

Triggered a bug in wrong Integer DH tests
Yann Weber преди 8 години
родител
ревизия
66d08738dc
променени са 3 файла, в които са добавени 61 реда и са изтрити 26 реда
  1. 6
    5
      lodel/leapi/datahandlers/datas_base.py
  2. 49
    21
      plugins/mongodb_datasource/datasource.py
  3. 6
    0
      plugins/mongodb_datasource/exceptions.py

+ 6
- 5
lodel/leapi/datahandlers/datas_base.py Целия файл

@@ -46,12 +46,13 @@ class Integer(DataField):
46 46
     #@return value
47 47
     def _check_data_value(self, value, strict = False):
48 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 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 56
         except(ValueError, TypeError):
56 57
             raise FieldValidationError("The value '%s' is not, and will never, be an integer" % value)
57 58
         return int(value)

+ 49
- 21
plugins/mongodb_datasource/datasource.py Целия файл

@@ -101,8 +101,11 @@ class MongoDbDatasource(object):
101 101
     #@param offset int: used with limit to choose the start record
102 102
     #@return list
103 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 109
         if target.is_abstract():
107 110
             #Reccursiv calls for abstract LeObject child
108 111
             results =  self.__act_on_abstract(target, filters,
@@ -208,13 +211,24 @@ class MongoDbDatasource(object):
208 211
         res = self.__collection(target).delete_many(mongo_filters)
209 212
         return res.deleted_count
210 213
 
211
-    ## @brief updates records according to given filters
214
+    ##@brief updates records according to given filters
212 215
     #@param target Emclass : class of the object to insert
213 216
     #@param filters list : List of filters
214 217
     #@param relational_filters list : List of relational filters
215 218
     #@param upd_datas dict : datas to update (new values)
216 219
     #@return int : Number of updated records
217 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 232
         if target.is_abstract():
219 233
             #Update using abstract LeObject as target (reccursiv calls)
220 234
             return self.__act_on_abstract(target, filters,
@@ -223,10 +237,10 @@ class MongoDbDatasource(object):
223 237
         mongo_filters = self.__process_filters(
224 238
             target, filters, relational_filters)
225 239
         res = self.__collection(target).update(mongo_filters, upd_datas)
226
-        self.__update_backref_filtered(target, filters, relational_filters,
227
-            upd_datas)
228 240
         return res['n']
229 241
 
242
+        
243
+
230 244
     ## @brief Inserts a record in a given collection
231 245
     # @param target Emclass : class of the object to insert
232 246
     # @param new_datas dict : datas to insert
@@ -256,7 +270,7 @@ class MongoDbDatasource(object):
256 270
     def __update_backref_filtered(self, target, act,
257 271
             filters, relational_filters, datas = None):
258 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 274
         for old_datas in old_datas_l:
261 275
             self.__update_backref(target, old_datas, datas)
262 276
 
@@ -334,7 +348,7 @@ class MongoDbDatasource(object):
334 348
                     to_add = []
335 349
                 elif not oldd and newd:
336 350
                     to_del = []
337
-                    to_add = [new_datas[fname]]
351
+                    to_add = new_datas[fname]
338 352
                 #Calling __back_ref_upd_one_value() with good arguments
339 353
                 for vtype, vlist in [('old',to_del), ('new', to_add)]:
340 354
                     for value in vlist:
@@ -343,16 +357,16 @@ class MongoDbDatasource(object):
343 357
                             bref_cls, value, bref_fname)
344 358
                         #preparing the upd_dict
345 359
                         upd_dict = self.__update_backref_upd_dict_prepare(
346
-                            upd_dict, bref_infos)
360
+                            upd_dict, bref_infos, bref_fname, value)
347 361
                         #preparing updated bref_infos
348 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 365
                         vdict = {vtype: value}
352 366
                         #fetch and store updated value
353 367
                         new_bref_val = self.__back_ref_upd_one_value(
354 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 370
             else:
357 371
                 #fdh is a single ref so the process is simpler, we do not have
358 372
                 #to loop and we may do an update in only one
@@ -371,7 +385,7 @@ class MongoDbDatasource(object):
371 385
                     bref_cls, uid_val, bref_fname)
372 386
                 #prepare the upd_dict
373 387
                 upd_dict = self.__update_backref_upd_dict_prepare(
374
-                    upd_dict, bref_infos)
388
+                    upd_dict, bref_infos, bref_fname, uid_val)
375 389
                 #forging update bref_infos
376 390
                 bref_cls, bref_leo, bref_dh, bref_value = bref_infos
377 391
                 bref_infos = tuple(bref_cls, bref_leo, bref_dh,
@@ -384,21 +398,29 @@ class MongoDbDatasource(object):
384 398
         #running the updates
385 399
         for bref_cls, uid_dict in upd_dict.items():
386 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 406
     ##@brief Utility function designed to handle the upd_dict of 
390 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 411
     #@param upd_dict dict : in & out args modified by reference
393 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 415
     #@return the updated version of upd_dict
395 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 419
         bref_cls, bref_leo, bref_dh, bref_value = bref_infos
398 420
         if bref_cls not in upd_dict:
399 421
             upd_dict[bref_cls] = {}
400 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 424
         if bref_fname not in upd_dict[bref_cls][uid_val]:
403 425
             upd_dict[bref_cls][uid_val][1][bref_fname] = bref_value
404 426
         return upd_dict
@@ -419,7 +441,7 @@ class MongoDbDatasource(object):
419 441
             #
420 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 445
             bref_cls, bref_leo, bref_dh, bref_val = self.__bref_get_check(
424 446
                 bref_cls, old_value, bref_fname)
425 447
             if issubclass(bref_dh.__class__, MultipleRef):
@@ -442,7 +464,7 @@ object : %s field %s" % (bref_leo, ref_fname))
442 464
                         if val == old_value:
443 465
                             if newd:
444 466
                                 #Update
445
-                                bref_val[ki] = new_datas[fname]
467
+                                bref_val[ki] = values['new']
446 468
                             else:
447 469
                                 #Deletion
448 470
                                 del(bref_val[ki])
@@ -452,7 +474,7 @@ object : %s field %s" % (bref_leo, ref_fname))
452 474
 raised ! We just checked that oldv is in bref_val...")
453 475
             else:
454 476
                 #Single ref handling
455
-                if bref_val != old_value:
477
+                if bref_val != values['old']:
456 478
                     raise MongoDbConsistencyError("The value we wanted to \
457 479
 update do not match excpected value during aback reference  singleReference \
458 480
 update : expected value was '%s' but found '%s' in field '%s' of leo %s" % (
@@ -460,7 +482,7 @@ update : expected value was '%s' but found '%s' in field '%s' of leo %s" % (
460 482
                 
461 483
                 if newd:
462 484
                     #update
463
-                    bref_val = new_datas[fname]
485
+                    bref_val = values['new']
464 486
                 else:
465 487
                     #delete
466 488
                     if not hasattr(bref_dh, "default"): 
@@ -470,8 +492,10 @@ value : in %s field %s" % (bref_leo, ref_fname))
470 492
                     bref_val = getattr(bref_dh, "default")
471 493
         elif newd:
472 494
             #It's an "insert"
473
-            new_value = new_datas[fname]
495
+            new_value = values['new']
474 496
             if issubclass(bref_dh.__class__, MultipleRef):
497
+                if bref_val is None:
498
+                    bref_val = bref_dh.empty()
475 499
                 if isinstance(bref_val, set):
476 500
                     bref_val |= set([new_value])
477 501
                 else:
@@ -498,8 +522,12 @@ value : in %s field %s" % (bref_leo, ref_fname))
498 522
         if len(bref_leo) == 0:
499 523
             raise MongoDbConsistencyError("Unable to get the object we make \
500 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 529
         bref_dh = bref_leo.data_handler(bref_fname)
502
-        if not isinstance(bref_leo, Reference):
530
+        if not isinstance(bref_dh, Reference):
503 531
             raise LodelFatalError("Found a back reference field that \
504 532
 is not a reference : '%s' field '%s'" % (bref_leo, bref_fname))
505 533
         bref_val = bref_leo.data(bref_fname)

+ 6
- 0
plugins/mongodb_datasource/exceptions.py Целия файл

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

Loading…
Отказ
Запис