Browse Source

Merge branch 'newlodel' of git.labocleo.org:lodel2 into newlodel

prieto 9 years ago
parent
commit
07344ee5c3

+ 7
- 0
globconf.d/global.ini View File

1
 [lodel2]
1
 [lodel2]
2
 lib_path = /home/yannweb/dev/lodel2/lodel2-git
2
 lib_path = /home/yannweb/dev/lodel2/lodel2-git
3
 plugins_path = /home/yannweb/dev/lodel2/lodel2-git/plugins
3
 plugins_path = /home/yannweb/dev/lodel2/lodel2-git/plugins
4
+
5
+[lodel2.editorialmodel]
6
+emfile = examples/em_test.pickle
7
+emtranslator = picklefile
8
+dyncode = lodel/leapi/dyncode.py
9
+editormode = True
10
+groups = 

+ 1
- 0
lodel/datasource/generic/__init__.py View File

1
+# -*- coding: utf-8 -*-

+ 51
- 0
lodel/datasource/generic/datasource.py View File

1
+# -*- coding: utf-8 -*-
2
+
3
+class GenericDataSource(object):
4
+
5
+    def __init__(self, *conn_args, **conn_kwargs):
6
+        self.conn_args = conn_args
7
+        self.conn_kwargs = conn_kwargs
8
+
9
+    ## @brief returns a selection of documents from the datasource
10
+    # @param target_cls Emclass
11
+    # @param field_list list
12
+    # @param filters list : List of filters
13
+    # @param rel_filters list : List of relational filters
14
+    # @param order list : List of column to order. ex: order = [('title', 'ASC'),]
15
+    # @param group list : List of tupple representing the column to group together. ex: group = [('title', 'ASC'),]
16
+    # @param limit int : Number of records to be returned
17
+    # @param offset int: used with limit to choose the start record
18
+    # @param instanciate bool : If true, the records are returned as instances, else they are returned as dict
19
+    # @return list
20
+    def select(self, target_cls, field_list, filters, rel_filters=None, order=None, group=None, limit=None, offset=0,
21
+               instanciate=True):
22
+        pass
23
+
24
+    ## @brief Deletes one record defined by its uid
25
+    # @param target_cls Emclass : class of the record to delete
26
+    # @param uid dict|list : a dictionary of fields and values composing the unique identifier of the record or a list of several dictionaries
27
+    # @return int : number of deleted records
28
+    def delete(self, target_cls, uid):
29
+        pass
30
+
31
+    ## @brief updates one or a list of records
32
+    # @param target_cls Emclass : class of the object to insert
33
+    # @param uids list : list of uids to update
34
+    # @param datas dict : datas to update (new values)
35
+    # @return int : Number of updated records
36
+    def update(self, target_cls, uids, **datas):
37
+        pass
38
+
39
+    ## @brief Inserts a record in a given collection
40
+    # @param target_cls Emclass : class of the object to insert
41
+    # @param datas dict : datas to insert
42
+    # @return bool
43
+    def insert(self, target_cls, **datas):
44
+        pass
45
+
46
+    ## @brief Inserts a list of records in a given collection
47
+    # @param target_cls Emclass : class of the objects inserted
48
+    # @param datas_list
49
+    # @return list : list of the inserted records' ids
50
+    def insert_multi(self, target_cls, datas_list):
51
+        pass

+ 3
- 1
lodel/datasource/mongodb/datasource.py View File

6
 
6
 
7
 import lodel.datasource.mongodb.utils as utils
7
 import lodel.datasource.mongodb.utils as utils
8
 
8
 
9
+from lodel.datasource.generic.datasource import GenericDataSource
10
+
9
 
11
 
10
 class MongoDbDataSourceError(Exception):
12
 class MongoDbDataSourceError(Exception):
11
     pass
13
     pass
12
 
14
 
13
 
15
 
14
-class MongoDbDataSource(object):
16
+class MongoDbDataSource(GenericDataSource):
15
 
17
 
16
     MANDATORY_CONNECTION_ARGS = ('host', 'port', 'login', 'password', 'dbname')
18
     MANDATORY_CONNECTION_ARGS = ('host', 'port', 'login', 'password', 'dbname')
17
 
19
 

+ 0
- 2
lodel/datasource/mongodb/utils.py View File

16
     '>': {'name': '$gt', 'value_type': None},
16
     '>': {'name': '$gt', 'value_type': None},
17
     'in': {'name': '$in', 'value_type': list},
17
     'in': {'name': '$in', 'value_type': list},
18
     'not in': {'name': '$nin', 'value_type': list},
18
     'not in': {'name': '$nin', 'value_type': list},
19
-    #' like ': {'name': '$text', 'value_type': str},
20
-    #' not like ': {'name': '', 'value_type': str},  # TODO Add the operator
21
     'OR': {'name': '$or', 'value_type': list},
19
     'OR': {'name': '$or', 'value_type': list},
22
     'AND': {'name': '$and', 'value_type': list}
20
     'AND': {'name': '$and', 'value_type': list}
23
 }
21
 }

+ 3
- 1
lodel/editorial_model/components.py View File

72
         self.__fields = dict() 
72
         self.__fields = dict() 
73
     
73
     
74
     ##@brief Property that represent a dict of all fields (the EmField defined in this class and all its parents)
74
     ##@brief Property that represent a dict of all fields (the EmField defined in this class and all its parents)
75
+    # @todo use Settings.editorialmodel.groups to determine wich fields should be returned
75
     @property
76
     @property
76
     def __all_fields(self):
77
     def __all_fields(self):
77
         res = dict()
78
         res = dict()
97
     # @param uid None | str : If None returns an iterator on EmField instances else return an EmField instance
98
     # @param uid None | str : If None returns an iterator on EmField instances else return an EmField instance
98
     # @param no_parents bool : If True returns only fields defined is this class and not the one defined in parents classes
99
     # @param no_parents bool : If True returns only fields defined is this class and not the one defined in parents classes
99
     # @return A list on EmFields instances (if uid is None) else return an EmField instance
100
     # @return A list on EmFields instances (if uid is None) else return an EmField instance
101
+    # @todo use Settings.editorialmodel.groups to determine wich fields should be returned
100
     def fields(self, uid = None, no_parents = False):
102
     def fields(self, uid = None, no_parents = False):
101
         fields = self.__fields if no_parents else self.__all_fields
103
         fields = self.__fields if no_parents else self.__all_fields
102
         try:
104
         try:
253
                     res[new_app.uid] = new_app
255
                     res[new_app.uid] = new_app
254
         return res
256
         return res
255
     
257
     
256
-	##@brief Returns EmGroup components
258
+    ##@brief Returns EmGroup components
257
     # @returns a copy of the set of components
259
     # @returns a copy of the set of components
258
     def components(self):
260
     def components(self):
259
         return (self.__components).copy()
261
         return (self.__components).copy()

+ 45
- 0
lodel/leapi/datahandlers/base_classes.py View File

256
             if self.max_item < len(value):
256
             if self.max_item < len(value):
257
                 return None, FieldValidationError("To many items")
257
                 return None, FieldValidationError("To many items")
258
 
258
 
259
+## @brief Class designed to handle datas access will fieldtypes are constructing datas
260
+#
261
+# This class is designed to allow automatic scheduling of construct_data calls. 
262
+#
263
+# In theory it's able to detect circular dependencies
264
+# @todo test circular deps detection
265
+# @todo test circulat deps false positiv
266
+class DatasConstructor(object):
267
+    
268
+    ## @brief Init a DatasConstructor
269
+    # @param lec LeCrud : @ref LeObject child class 
270
+    # @param datas dict : dict with field name as key and field values as value
271
+    # @param fields_handler dict : dict with field name as key and data handler instance as value
272
+    def __init__(self, leobject, datas, fields_handler):
273
+        ## Stores concerned class
274
+        self._leobject = leobject
275
+        ## Stores datas and constructed datas
276
+        self._datas = copy.copy(datas)
277
+        ## Stores fieldtypes
278
+        self._fields_handler = fields_handler
279
+        ## Stores list of fieldname for constructed datas
280
+        self._constructed = []
281
+        ## Stores construct calls list
282
+        self._construct_calls = []
283
+    
284
+    ## @brief Implements the dict.keys() method on instance
285
+    def keys(self):
286
+        return self._datas.keys()
287
+    
288
+    ## @brief Allows to access the instance like a dict
289
+    def __getitem__(self, fname):
290
+        if fname not in self._constructed:
291
+            if fname in self._construct_calls:
292
+                raise RuntimeError('Probably circular dependencies in fieldtypes')
293
+            cur_value = self._datas[fname] if fname in self._datas else None
294
+            self._datas[fname] = self._fields_handler[fname].construct_data(self._leobject, fname, self, cur_value)
295
+            self._constructed.append(fname)
296
+        return self._datas[fname]
297
+    
298
+    ## @brief Allows to set instance values like a dict
299
+    # @warning Should not append in theory
300
+    def __setitem__(self, fname, value):
301
+        self._datas[fname] = value
302
+        warnings.warn("Setting value of an DatasConstructor instance")
303
+ 

+ 2
- 0
lodel/settings/settings.py View File

59
 #
59
 #
60
 # @todo handles default sections for variable sections (sections ending with 
60
 # @todo handles default sections for variable sections (sections ending with 
61
 # '.*')
61
 # '.*')
62
+# @todo delete the first stage, the lib path HAVE TO BE HARDCODED. In fact
63
+#when we will run lodel in production the lodel2 lib will be in the python path
62
 class Settings(object):
64
 class Settings(object):
63
     
65
     
64
     ##@brief global conf specsification (default_value + validator)
66
     ##@brief global conf specsification (default_value + validator)

+ 14
- 0
lodel/settings/validator.py View File

210
                     SettingValidator('bool')),
210
                     SettingValidator('bool')),
211
         'plugins': (    "",
211
         'plugins': (    "",
212
                         SettingValidator('list')),
212
                         SettingValidator('list')),
213
+        'sitename': (   'noname',
214
+                        SettingValidator('strip')),
213
     },
215
     },
214
     'lodel2.logging.*' : {
216
     'lodel2.logging.*' : {
215
         'level': (  'ERROR',
217
         'level': (  'ERROR',
222
                             SettingValidator('int', none_is_valid = True)),
224
                             SettingValidator('int', none_is_valid = True)),
223
         'maxbytes': (   None,
225
         'maxbytes': (   None,
224
                         SettingValidator('int', none_is_valid = True)),
226
                         SettingValidator('int', none_is_valid = True)),
227
+    },
228
+    'lodel2.editorialmodel': {
229
+        'emfile': ( 'em.pickle',
230
+                    SettingValidator('strip')),
231
+        'emtranslator': (   'picklefile',
232
+                            SettingValidator('strip')),
233
+        'dyncode': (    'leapi_dyncode.py',
234
+                        SettingValidator('strip')),
235
+        'groups': ( '',
236
+                    SettingValidator('list')),
237
+        'editormode': ( False,
238
+                        SettingValidator('bool')),
225
     }
239
     }
226
 }
240
 }

+ 8
- 0
tests/settings/settings_examples/complex.conf.d/file1.ini View File

1
+[lodel2.editorialmodel]
2
+lib_path=/tmp
3
+foo_bar=42
4
+foo.bar=1337
5
+[lodel2.bar.foo]
6
+barfoo=42
7
+[lodel2.bar.bar]
8
+toto=tata

+ 9
- 0
tests/settings/settings_examples/complex.conf.d/file2.ini View File

1
+[lodel2.editorialmodel]
2
+example=foobar
3
+
4
+[lodel2.conf1]
5
+conf_key=woot
6
+conf_value=42
7
+
8
+[lodel2.conf2]
9
+conf_foo=bar

+ 6
- 0
tests/settings/settings_examples/complex.conf.d/file3.ini View File

1
+[lodel2.foo.bar]
2
+barfoo=42
3
+[lodel2.foo.foo]
4
+foobar=barfoo
5
+[lodel2.bar.foo]
6
+foobar=barfoo

+ 1
- 0
tests/settings/test_settings.py View File

8
 
8
 
9
 class SettingsTestCase(unittest.TestCase):
9
 class SettingsTestCase(unittest.TestCase):
10
     
10
     
11
+    @unittest.skip('todo : write it')
11
     def test_init(self):
12
     def test_init(self):
12
         settings = Settings('tests/settings/settings_tests.ini', 'tests/settings/settings_tests_conf.d')
13
         settings = Settings('tests/settings/settings_tests.ini', 'tests/settings/settings_tests_conf.d')
13
         pass
14
         pass

+ 39
- 0
tests/settings/test_settings_loader.py View File

59
         value = loader.getoption('lodel2.foo.bar', 'foobar', dummy_validator)
59
         value = loader.getoption('lodel2.foo.bar', 'foobar', dummy_validator)
60
         self.assertEqual(value, "hello world")
60
         self.assertEqual(value, "hello world")
61
 
61
 
62
+    def test_getoption_complex(self):
63
+        """ Testing behavior of getoption with less simple files & confs """
64
+
65
+        expected = {
66
+            'lodel2.editorialmodel': {
67
+                'lib_path': '/tmp',
68
+                'foo_bar': '42',
69
+                'foo.bar': '1337',
70
+                'example': 'foobar',
71
+            },
72
+            'lodel2.conf1': {
73
+                'conf_key': 'woot',
74
+                'conf_value': '42',
75
+            },
76
+            'lodel2.conf2': {
77
+                'conf_foo': 'bar',
78
+            },
79
+            'lodel2.foo.foo': {
80
+                'foobar': 'barfoo',
81
+            },
82
+            'lodel2.bar.foo': {
83
+                'foobar': 'barfoo',
84
+                'barfoo': '42',
85
+            },
86
+            'lodel2.bar.bar': {
87
+                'toto': 'tata',
88
+            }
89
+        }
90
+
91
+        loader = SettingsLoader('tests/settings/settings_examples/complex.conf.d')
92
+        for section in expected:
93
+            for key, expected_value in expected[section].items():
94
+                value = loader.getoption(   section,
95
+                                            key,
96
+                                            dummy_validator)
97
+                self.assertEqual(value, expected_value)
98
+
99
+                
100
+
62
     def test_variable_sections(self):
101
     def test_variable_sections(self):
63
         """ Testing variable section recognition """
102
         """ Testing variable section recognition """
64
         loader = SettingsLoader('tests/settings/settings_examples/var_sections.conf.d')
103
         loader = SettingsLoader('tests/settings/settings_examples/var_sections.conf.d')

Loading…
Cancel
Save