Browse Source

Add tests for pickediff datasource and fixes 'autosql' beahvior for fieldtypes + some others modifications

Yann Weber 9 years ago
parent
commit
537f78e146

+ 10
- 0
DataSource/MySQL/leapidatasource.py View File

@@ -18,6 +18,8 @@ from DataSource.MySQL import utils
18 18
 from EditorialModel.classtypes import EmNature
19 19
 from EditorialModel.fieldtypes.generic import MultiValueFieldType
20 20
 
21
+from EditorialModel.fieldtypes import datetime, rank, pk
22
+
21 23
 from Lodel.settings import Settings
22 24
 from .fieldtypes import fieldtype_cast
23 25
 
@@ -25,6 +27,14 @@ from .fieldtypes import fieldtype_cast
25 27
 class LeapiDataSource(DataSource.dummy.leapidatasource.LeapiDataSource):
26 28
 
27 29
     RELATIONS_POSITIONS_FIELDS = {REL_SUP: 'superior_id', REL_SUB: 'subordinate_id'}
30
+    
31
+    ## @brief List of fieldtypes that should not try to construct their values
32
+    autohandled_fieldtypes = [
33
+        {'ftype': pk.EmFieldType},
34
+        {'ftype': datetime.EmFieldType, 'now_on_update': True},
35
+        {'ftype': datetime.EmFieldType, 'now_on_create': True},
36
+        {'ftype': rank.EmFieldType, 'internal': 'autosql'}
37
+    ]
28 38
 
29 39
     def __init__(self, module = pymysql, **kwargs):
30 40
         super().__init__()

+ 10
- 0
DataSource/dummy/leapidatasource.py View File

@@ -1,5 +1,7 @@
1 1
 #-*- coding: utf-8 -*-
2 2
 
3
+from EditorialModel.fieldtypes import pk, rank, datetime
4
+
3 5
 ## @brief Dummy datasource for LeObject
4 6
 #
5 7
 # This class has to be extended to apply to a real datasource
@@ -8,6 +10,14 @@
8 10
 # @todo Settings fetch/pass generalisation for datasources.
9 11
 class LeapiDataSource(object):
10 12
     
13
+    ## @brief List of fieldtypes that should not try to construct their values
14
+    autohandled_fieldtypes = [
15
+        {'ftype': pk.EmFieldType},
16
+        {'ftype': datetime.EmFieldType, 'now_on_update': True},
17
+        {'ftype': datetime.EmFieldType, 'now_on_create': True},
18
+        {'ftype': rank.EmFieldType, 'internal': 'autosql'}
19
+    ]
20
+
11 21
     ## @todo Settings fetch/pass generalisation for datasources.
12 22
     def __init__(self, module=None, *conn_args, **conn_kargs):
13 23
         self.module = module

+ 0
- 0
DataSource/picklediff/__init__.py View File


+ 11
- 4
DataSource/picklediff/leapidatasource.py View File

@@ -3,10 +3,13 @@
3 3
 import os, os.path
4 4
 import pickle
5 5
 import re
6
+import copy
6 7
 from collections import OrderedDict
7
-from Lodel import logger
8 8
 
9 9
 from Lodel.settings import Settings
10
+from Lodel import logger
11
+
12
+from EditorialModel.fieldtypes import pk
10 13
 
11 14
 ## @brief Datasource designed to stores datas and datas diff in pickle files
12 15
 # 
@@ -22,10 +25,14 @@ from Lodel.settings import Settings
22 25
 #  - modifications_datas : dict with action key and arguements for actions (example : { 'action': 'insert', 'target_class': EmClass, 'datas': dict() }
23 26
 #
24 27
 class LeapiDataSource(object):
25
-    
28
+ 
29
+    autohandled_fieldtypes = [
30
+        {'ftype': pk.EmFieldType}
31
+    ]
32
+
26 33
     def __init__(self, filename = None):
27 34
         if filename is None:
28
-            filename = Settings.datasource['default']['filename']
35
+            filename = Settings.datasource_options['filename']
29 36
         self.__filename = filename
30 37
         self.__content = None
31 38
         self.__load_file()
@@ -64,7 +71,7 @@ class LeapiDataSource(object):
64 71
                         lodel_ids = [ lid for lid in lodel_ids if self.__field_value(lodel_id, field) < value]
65 72
         # Now we got filtered lodel_id list in lodel_ids
66 73
         result = []
67
-        for datas in [ self.__content['editorial_model']['components'][lodel_id] for lodel_id in lodel_ids ]:
74
+        for datas in [ copy.copy(self.__content['editorial_model']['components'][lodel_id]) for lodel_id in lodel_ids ]:
68 75
             comp_class = target_cls.name2class(datas['__component_leapi_class__'])
69 76
             del(datas['__component_leapi_class__'])
70 77
 

+ 0
- 0
DataSource/picklediff/test/__init__.py View File


+ 65
- 0
DataSource/picklediff/test/test_datasource.py View File

@@ -0,0 +1,65 @@
1
+#-*- coding:utf-8 -*-
2
+
3
+import unittest
4
+import tempfile
5
+import os, os.path
6
+
7
+import leapi.test.utils
8
+from Lodel.settings import Settings
9
+from DataSource.picklediff.leapidatasource import LeapiDataSource
10
+from leapi.lecrud import _LeCrud
11
+from Lodel import logger
12
+from Lodel.utils.mlstring import MlString
13
+
14
+class PickleDiffDataSourceTestCase(unittest.TestCase):
15
+    
16
+    @classmethod
17
+    def setUpClass(cls):
18
+        """ Set settings for pickle datasource """
19
+        logger.remove_console_handlers()
20
+
21
+        _, filename = tempfile.mkstemp(prefix="picklediff_test_")
22
+        cls.filename = filename
23
+        if os.path.isfile(filename):
24
+            os.unlink(filename)
25
+        cls.ds_package_bck = Settings.ds_package
26
+        cls.ds_opt_bck = Settings.datasource_options
27
+        Settings.ds_package = 'picklediff'
28
+        Settings.datasource_options = { 'filename': filename }
29
+        cls.tmpdir = leapi.test.utils.tmp_load_factory_code()
30
+    
31
+    @classmethod
32
+    def tearDownClass(cls):
33
+        """ Delete temporary file """
34
+        if os.path.isfile(cls.filename):
35
+            os.unlink(cls.filename)
36
+        leapi.test.utils.cleanup(cls.tmpdir)
37
+        Settings.ds_package = cls.ds_package_bck
38
+        Settings.datasource_options = cls.ds_opt_bck
39
+        _LeCrud._datasource = None
40
+
41
+    def test_insert(self):
42
+        from dyncode import Article
43
+        uid = Article.insert({'titre': 'fooBar', 'soustitre': 'Barfoo'})
44
+        res = Article.get([])
45
+
46
+        e_titre = MlString(default_value = 'fooBar')
47
+        e_stitre = MlString(default_value = 'Barfoo')
48
+
49
+        self.assertEqual(len(res), 1)
50
+        self.assertEqual(res[0].uidget(), uid)
51
+        self.assertEqual(res[0].titre, e_titre)
52
+        self.assertEqual(res[0].soustitre, e_stitre)
53
+    
54
+
55
+    def test_load(self):
56
+        from dyncode import Article, LeCrud
57
+        
58
+        uid = Article.insert({'titre': 'wowwo', 'soustitre': 'randomdsfsdfqsofjze'})
59
+        orig = Article.get([('lodel_id','=', uid)])
60
+
61
+        new_ds = LeapiDataSource(self.filename)
62
+        Article._datasource = new_ds
63
+        # Article._datasource = 42 #uncomment this line to verify that this hack works
64
+        new = Article.get([('lodel_id','=', uid)])
65
+        self.assertEqual(orig, new)

+ 1
- 1
EditorialModel/fieldtypes/generic.py View File

@@ -36,7 +36,7 @@ class GenericFieldType(object):
36 36
     
37 37
     ## @return True if a fieldtype is internal
38 38
     def is_internal(self):
39
-        return self.internal != False
39
+        return self.internal is not False
40 40
     
41 41
     ## @brief Take care to call the fieldtype defined _check_data_value() method
42 42
     # @return a tuple (value, error|None)

+ 3
- 0
Lodel/utils/mlstring.py View File

@@ -66,6 +66,9 @@ class MlString(object):
66 66
     # @return A json dump of the MlString::translations dict
67 67
     def __str__(self):
68 68
         return self.get_default()
69
+
70
+    def __repr__(self):
71
+        return "<MlString : %s >" % self.dumps()
69 72
     
70 73
     ## @brief Serialize the MlString in Json
71 74
     def json_dumps(self):

+ 1
- 1
Makefile View File

@@ -2,7 +2,7 @@ all: check doc pip
2 2
 
3 3
 # Running unit tests
4 4
 check:
5
-	python -m unittest -v
5
+	./runtest
6 6
 
7 7
 # Rule to update libs
8 8
 pip: cleanpycache

+ 19
- 5
leapi/lecrud.py View File

@@ -518,14 +518,28 @@ class _LeCrud(object, metaclass = _MetaLeCrud):
518 518
     # @param cls
519 519
     # @param datas dict : Datas that have been returned by LeCrud.check_datas_value() methods
520 520
     # @return A new dict of datas
521
+    # @todo change the internal value 'autosql' to 'auto_datasource'
521 522
     @classmethod
522 523
     def _construct_datas(cls, datas):
523 524
         constructor = DatasConstructor(cls, datas, cls.fieldtypes())
524
-        ret = {
525
-                fname:constructor[fname]
526
-                for fname, ftype in cls.fieldtypes().items()
527
-                if not ftype.is_internal() or ftype.internal != 'autosql'
528
-        }
525
+        ret = dict()
526
+
527
+        for fname, ftype in cls.fieldtypes().items():
528
+            construct = True
529
+            for autods_ftype in cls._datasource.autohandled_fieldtypes:
530
+                if isinstance(ftype, autods_ftype['ftype']):
531
+                    test_false = False
532
+                    for optname, optval in autods_ftype.items():
533
+                        if optname != 'ftype':
534
+                            if not hasattr(ftype, optname) or getattr(ftype, optname) != optval:
535
+                                test_false = True
536
+                                break
537
+                    if not test_false:
538
+                        construct = False
539
+                        break
540
+
541
+            if construct:
542
+                ret[fname] = constructor[fname]
529 543
         return ret
530 544
 
531 545
     ## @brief Check datas consistency

+ 9
- 2
leapi/leobject.py View File

@@ -47,9 +47,16 @@ class _LeObject(_LeCrud):
47 47
     # @todo check class
48 48
     def __eq__(self, other):
49 49
         uid_fname = self.uidname()
50
-        if not hasattr(other, uid_fname):
50
+        if not hasattr(other, uid_fname) \
51
+            or self.uidget() != other.uidget() \
52
+            or self.__class__ != other.__class__:
51 53
             return False
52
-        return getattr(self, uid_fname) == getattr(other, uid_fname)
54
+        if self.is_complete() and other.is_complete():
55
+            for fname in self.fieldlist():
56
+                if not hasattr(other, fname) or getattr(other, fname) != getattr(self, fname):
57
+                    print(fname, 'differ', getattr(other, fname), getattr(self, fname))
58
+                    return False
59
+        return True
53 60
         
54 61
         
55 62
     ## @brief Quick str cast method implementation

+ 10
- 47
runtest View File

@@ -1,49 +1,12 @@
1 1
 #!/bin/bash
2
-#
3
-# Usage : ./runtest [OPTIONS] [test_module[.test_class][ test_module2[.test_class2]...]
4
-#########
5
-#
6
-# Options list :
7
-################
8
-#
9
-# -b, --buffer
10
-#
11
-#    The standard output and standard error streams are buffered during the test run. Output during a passing test is discarded. Output is echoed normally on test fail or error and is added to the failure messages.
12
-#
13
-# -c, --catch
14
-#
15
-#    Control-C during the test run waits for the current test to end and then reports all the results so far. A second control-C raises the normal KeyboardInterrupt exception.
16
-#
17
-#
18
-# -f, --failfast
19
-#
20
-#    Stop the test run on the first error or failure.
21
-#
22
-# -h, --help
23
-#
24
-#    Get some help
25
-#
26
-# -v, --verbose
27
-#
28
-#   higher verbosity
29
-#
30
-# Examples :
31
-############
32
-#
33
-# Running all discoverables tests :
34
-# ./runtest
35
-#
36
-# Running only Em test about component object (only tests about the __init__ and modify_rank methods) with higher verbosity and failfast :
37
-# ./runtest -fv EditorialModel.test.test_component.TestInit EditorialModel.test.test_component.TestModifyRank
38
-#
39
-#
40
-# Running only Em tests
41
-# ./runtest discover EditorialModel
42
-#
43
-# More details :
44
-################
45
-#
46
-# https://docs.python.org/3.4/library/unittest.html
47
-#
48 2
 
49
-python -W ignore -m unittest $@
3
+# Old runtest is broken because of DataSource.picklediff tests
4
+# we have to run each test package in differents python instances
5
+
6
+test_package_name='test'
7
+
8
+for d in $(find . -type d -name "$test_package_name")
9
+do
10
+	echo -e "\tTesting\t$(dirname $d)\n"
11
+	python -W ignore -m unittest discover -qf -s "$d" || break
12
+done

Loading…
Cancel
Save