Przeglądaj źródła

Changed LeFactory generated code (again) + Bugfix on LeCrud + more tests and tests update

Yann Weber 9 lat temu
rodzic
commit
52cbce9865

+ 16
- 0
EditorialModel/fieldtypes/generic.py Wyświetl plik

@@ -75,6 +75,22 @@ class GenericFieldType(object):
75 75
         if value is None and not self.nullable:
76 76
             return (None, TypeError("'None' value but field is not nullable"))
77 77
         return self._check_data_value(value)
78
+    
79
+    ## @brief Build automatic fields values
80
+    # @param lec LeCrud : A LeCrud child class
81
+    # @param fname str : The field name
82
+    # @param datas dict : dict storing fields values
83
+    # @return constructed datas
84
+    def construct_data(self, lec, fname, datas):
85
+        return datas[fname]
86
+    
87
+    ## @brief Check datas consistency
88
+    # @param leo LeCrud : A LeCrud child class instance
89
+    # @param fname str : The field name
90
+    # @param datas dict : dict storing fields values
91
+    # @return an Exception instance if fails else True
92
+    def check_data_consistency(self, lec, fname, datas):
93
+        return True
78 94
 
79 95
     ## @brief Check if a value is correct
80 96
     # @param value * : The value

+ 3
- 3
leapi/leclass.py Wyświetl plik

@@ -2,11 +2,11 @@
2 2
 
3 3
 import leapi
4 4
 
5
-
5
+from leapi.leobject import _LeObject
6 6
 
7 7
 ## @brief Represent an EmClass data instance
8 8
 # @note Is not a derivated class of LeObject because the concrete class will be a derivated class from LeObject
9
-class _LeClass(object):
9
+class _LeClass(_LeObject):
10 10
 
11 11
     ## @brief Stores fieldtypes by field name
12 12
     _fieldtypes = dict()
@@ -28,7 +28,7 @@ class _LeClass(object):
28 28
     @classmethod
29 29
     def fieldtypes(cls):
30 30
         ret = dict()
31
-        ret.update(super(LeClass,cls).fieldtypes())
31
+        ret.update(super(_LeClass,cls).fieldtypes())
32 32
         ret.update(cls._fieldtypes)
33 33
         return ret
34 34
 

+ 6
- 9
leapi/lecrud.py Wyświetl plik

@@ -8,8 +8,6 @@ import warnings
8 8
 import importlib
9 9
 import re
10 10
 
11
-import leapi.leobject
12
-
13 11
 class LeApiErrors(Exception):
14 12
     ## @brief Instanciate a new exceptions handling multiple exceptions
15 13
     # @param expt_l list : A list of data check Exception
@@ -134,7 +132,6 @@ class _LeCrud(object):
134 132
         provided = set(datas.keys())
135 133
 
136 134
         #searching unknow fields
137
-        print("provided", provided, "correct", correct)
138 135
         unknown = provided - correct
139 136
         for u_f in unknown:
140 137
             #here we can check if the field is unknown or rejected because it is internal
@@ -193,7 +190,7 @@ class _LeCrud(object):
193 190
     # @return A new id if success else False
194 191
     @classmethod
195 192
     def insert(cls, datas):
196
-        insert_datas = self.prepare_datas(datas, complete = True, allow_internal = False)
193
+        insert_datas = cls.prepare_datas(datas, complete = True, allow_internal = False)
197 194
         return cls._datasource.insert(cls, insert_datas)
198 195
     
199 196
     ## @brief Check and prepare datas
@@ -208,9 +205,9 @@ class _LeCrud(object):
208 205
     def prepare_datas(cls, datas, complete = False, allow_internal = True):
209 206
         if not complete:
210 207
             warnings.warn("Actual implementation can make datas construction and consitency checks fails when datas are not complete")
211
-        ret_dats = self.check_datas_value(cls, datas, complete, allow_internal)
212
-        ret_datas = self._construct_datas(cls, ret_datas)
213
-        ret_datas = self._check_data_consistency(cls, ret_datas)
208
+        ret_datas = cls.check_datas_value(datas, complete, allow_internal)
209
+        ret_datas = cls._construct_datas(ret_datas)
210
+        cls._check_datas_consistency(ret_datas)
214 211
         return ret_datas
215 212
 
216 213
     #-###################-#
@@ -236,7 +233,7 @@ class _LeCrud(object):
236 233
         res_datas = dict()
237 234
         for fname, ftype in cls.fieldtypes().items():
238 235
             if fname in datas:
239
-                res_datas[fname] = ftype.construct_data(datas)
236
+                res_datas[fname] = ftype.construct_data(cls, fname, datas)
240 237
         return res_datas
241 238
     ## @brief Check datas consistency
242 239
@@ -248,7 +245,7 @@ class _LeCrud(object):
248 245
     def _check_datas_consistency(cls, datas):
249 246
         err_l = []
250 247
         for fname, ftype in cls.fieldtypes().items():
251
-            ret = ftype.check_data_consistency(datas)
248
+            ret = ftype.check_data_consistency(cls, fname, datas)
252 249
             if isinstance(ret, Exception):
253 250
                 err_l.append(ret)
254 251
 

+ 1
- 1
leapi/lefactory.py Wyświetl plik

@@ -225,7 +225,7 @@ class {name}(LeClass, LeObject):
225 225
             result += """
226 226
 ## @brief EmType {name} LeType child class
227 227
 # @see leobject::letype::LeType
228
-class {name}({leclass}, LeType):
228
+class {name}(LeType, {leclass}):
229 229
     _type_id = {uid}
230 230
 
231 231
 """.format(

+ 3
- 22
leapi/leobject.py Wyświetl plik

@@ -14,15 +14,16 @@ import re
14 14
 import warnings
15 15
 
16 16
 import leapi
17
-import EditorialModel
17
+from leapi.lecrud import _LeCrud
18 18
 from leapi.lefactory import LeFactory
19
+import EditorialModel
19 20
 from EditorialModel.types import EmType
20 21
 
21 22
 REL_SUP = 0
22 23
 REL_SUB = 1
23 24
 
24 25
 ## @brief Main class to handle objects defined by the types of an Editorial Model
25
-class _LeObject(object):
26
+class _LeObject(_LeCrud):
26 27
     
27 28
     ## @brief maps em uid with LeType or LeClass keys are uid values are LeObject childs classes
28 29
     # @todo check if this attribute shouldn't be in _LeCrud
@@ -55,26 +56,6 @@ class _LeObject(object):
55 56
             cls._fieldtypes_all.update(cls._leo_fieldtypes)
56 57
         return cls._fieldtypes_all
57 58
 
58
-    ## @brief Creates new entries in the datasource
59
-    # @param datas list : A list a dict with fieldname as key
60
-    # @param cls
61
-    # @return a list of inserted lodel_id
62
-    # @see leapi.datasources.dummy.DummyDatasource.insert(), leapi.letype.LeType.insert()
63
-    @classmethod
64
-    def insert(cls, letype, datas):
65
-        if isinstance(datas, dict):
66
-            datas = [datas]
67
-
68
-        if cls == _LeObject:
69
-            raise NotImplementedError("Abstract method")
70
-        letype,leclass = cls._prepare_targets(letype)
71
-        if letype is None:
72
-            raise ValueError("letype argument cannot be None")
73
-
74
-        for data in datas:
75
-            letype.prepare_data(data, complete = True)
76
-        return cls._datasource.insert(letype, leclass, datas)
77
-    
78 59
     ## @brief Check if a LeType is a hierarchy root
79 60
     @staticmethod
80 61
     def is_root(leo):

+ 2
- 1
leapi/letype.py Wyświetl plik

@@ -11,11 +11,12 @@
11 11
 # @note LeObject will be generated by leapi.lefactory.LeFactory
12 12
 
13 13
 import leapi
14
+from leapi.leclass import _LeClass
14 15
 from leapi.leobject import LeObjectError
15 16
 
16 17
 ## @brief Represent an EmType data instance
17 18
 # @note Is not a derivated class of LeClass because the concrete class will be a derivated class from LeClass
18
-class _LeType(object):
19
+class _LeType(_LeClass):
19 20
     
20 21
     ## @brief Stores selected fields with key = name
21 22
     _fields = list()

+ 41
- 0
leapi/test/test_lecrud.py Wyświetl plik

@@ -11,6 +11,8 @@ import leapi
11 11
 import leapi.test.utils
12 12
 from leapi.lecrud import _LeCrud
13 13
 
14
+## @brief Test LeCrud methods
15
+# @note those tests need the full dynamically generated code
14 16
 class LeCrudTestCase(TestCase):
15 17
     @classmethod
16 18
     def setUpClass(cls):
@@ -139,4 +141,43 @@ class LeCrudTestCase(TestCase):
139 141
         filters = ['hello world !']
140 142
         with self.assertRaises(ValueError):
141 143
             Personnes._prepare_filters(filters)
144
+    
145
+
146
+    # 
147
+    #   Tests mocking the datasource
148
+    # 
149
+
150
+    @patch('leapi.datasources.dummy.DummyDatasource.insert')
151
+    def test_insert(self, dsmock):
152
+        from dyncode import Publication, Numero, LeObject, Personne, Article
153
+        ndatas = [
154
+            (Numero, {'titre' : 'FooBar'}),
155
+            (Numero, {'titre':'hello'}),
156
+            (Personne, {'nom':'world', 'prenom':'hello'}),
157
+            (Article, {'titre': 'Ar Boof', 'soustitre': 'Wow!'}),
158
+        ]
159
+        for lecclass, ndats in ndatas:
160
+            lecclass.insert(ndats)
161
+            dsmock.assert_called_once_with(lecclass, ndats)
162
+            dsmock.reset_mock()
163
+
164
+            lecclass.insert(ndats)
165
+            dsmock.assert_called_once_with(lecclass, ndats)
166
+            dsmock.reset_mock()
167
+    
168
+    ## @todo try failing on inserting from LeClass child or LeObject
169
+    @patch('leapi.datasources.dummy.DummyDatasource.insert')
170
+    def test_insert_fails(self, dsmock):
171
+        from dyncode import Publication, Numero, LeObject, Personne, Article
172
+        ndatas = [
173
+            (Numero, dict()),
174
+            (Numero, {'titre':'hello', 'lodel_id':42}),
175
+            (Numero, {'tititre': 'hehello'}),
176
+            (Personne, {'titre':'hello'}),
177
+            (Article, {'titre': 'hello'}),
178
+        ]
179
+        for lecclass, ndats in ndatas:
180
+            with self.assertRaises(leapi.lecrud.LeApiDataCheckError, msg="But trying to insert %s as %s"%(ndats, lecclass.__name__)):
181
+                lecclass.insert(ndats)
182
+        pass
142 183
 

+ 10
- 6
leapi/test/test_lefactory.py Wyświetl plik

@@ -35,14 +35,16 @@ class TestLeFactory(TestCase):
35 35
     def test_leobject(self):
36 36
         """ Testing the generated LeObject class """
37 37
         import dyncode
38
+        from dyncode import LeType, LeClass
39
+
38 40
         self.assertTrue(hasattr(dyncode, 'LeObject'))
39 41
 
40 42
         for uid, cls in dyncode.LeObject._me_uid.items():
41
-            if leapi.letype.LeType in cls.__bases__:
42
-                self.assertNotEqual(cls, leapi.letype.LeType)
43
+            if LeType in cls.__bases__:
44
+                self.assertNotEqual(cls, LeType)
43 45
                 self.assertEqual(cls._type_id, uid)
44
-            elif leapi.leclass.LeClass in cls.__bases__:
45
-                self.assertNotEqual(cls, leapi.leclass.LeClass)
46
+            elif LeClass in cls.__bases__:
47
+                self.assertNotEqual(cls, LeClass)
46 48
                 self.assertEqual(cls._class_id, uid)
47 49
             else:
48 50
                 self.fail("Bad instance type for _me_uid values : %s"%type(cls))
@@ -51,6 +53,7 @@ class TestLeFactory(TestCase):
51 53
     def test_leclass(self):
52 54
         """ Testing generated LeClass childs classes """
53 55
         import dyncode
56
+        from dyncode import LeType, LeClass
54 57
 
55 58
         for emclass in self.model.components(EditorialModel.classes.EmClass):
56 59
             leclass_name = LeFactory.name2classname(emclass.name)
@@ -60,7 +63,7 @@ class TestLeFactory(TestCase):
60 63
             self.assertEqual(leclass._class_id, emclass.uid)
61 64
             
62 65
             #Testing inheritance
63
-            self.assertEqual(set(leclass.__bases__), set([dyncode.LeObject, leapi.leclass.LeClass]))
66
+            self.assertEqual(set(leclass.__bases__), set([dyncode.LeObject, dyncode.LeClass]))
64 67
             
65 68
             #Testing _linked_types attr
66 69
             self.assertEqual(
@@ -83,6 +86,7 @@ class TestLeFactory(TestCase):
83 86
     def test_letype(self):
84 87
         """ Testing generated LeType childs classes """
85 88
         import dyncode
89
+        from dyncode import LeType, LeClass
86 90
 
87 91
         for emtype in self.model.components(EditorialModel.types.EmType):
88 92
             letype_name = LeFactory.name2classname(emtype.name)
@@ -95,7 +99,7 @@ class TestLeFactory(TestCase):
95 99
             #Testing inheritance
96 100
             self.assertEqual(
97 101
                 set(letype.__bases__),
98
-                set([leapi.letype.LeType, letype._leclass])
102
+                set([LeType, letype._leclass])
99 103
             )
100 104
 
101 105
             #Testing _fields

+ 3
- 2
leapi/test/test_leobject.py Wyświetl plik

@@ -26,11 +26,12 @@ class LeObjectTestCase(TestCase):
26 26
     def test_uid2leobj(self):
27 27
         """ Testing _Leobject.uid2leobj() """
28 28
         import dyncode
29
+        from dyncode import LeType, LeClass
29 30
         for i in dyncode.LeObject._me_uid.keys():
30 31
             cls = dyncode.LeObject.uid2leobj(i)
31
-            if leapi.letype.LeType in cls.__bases__:
32
+            if LeType in cls.__bases__:
32 33
                 self.assertEqual(i, cls._type_id)
33
-            elif leapi.leclass.LeClass in cls.__bases__:
34
+            elif LeClass in cls.__bases__:
34 35
                 self.assertEqual(i, cls._class_id)
35 36
             else:
36 37
                 self.fail("Bad value returned : '%s'"%cls)

+ 3
- 3
leapi/test/test_letype.py Wyświetl plik

@@ -24,10 +24,10 @@ class LeTypeTestCase(TestCase):
24 24
     @unittest.skip("Waiting for EmFieldType full implementation")
25 25
     def test_init(self):
26 26
         """ testing the constructor """
27
-        from dyncode import Publication, Numero, LeObject
27
+        from dyncode import Publication, Numero, LeObject, LeType
28 28
         
29 29
         with self.assertRaises(NotImplementedError):
30
-            leapi.letype.LeType(42)
30
+            LeType(42)
31 31
 
32 32
         badargs = [
33 33
             {'class_id':Numero._class_id + 1},
@@ -45,7 +45,7 @@ class LeTypeTestCase(TestCase):
45 45
             with self.assertRaises(expect_e, msg="Invalid argument given %s"%badarg):
46 46
                 Numero(**badarg)
47 47
     
48
-    @patch('leapi.letype.LeType.populate')
48
+    @patch('leapi.letype._LeType.populate')
49 49
     def test_datas(self, dsmock):
50 50
         """ Testing the datas @property method """
51 51
         from dyncode import Publication, Numero, LeObject

Loading…
Anuluj
Zapisz