Преглед изворни кода

Only indentation and stuff like that

prieto пре 7 година
родитељ
комит
3b4494cb7a

+ 133
- 121
lodel/editorial_model/components.py Прегледај датотеку

@@ -1,6 +1,6 @@
1 1
 #-*- coding: utf-8 -*-
2 2
 
3
-##@package lodel.editorial_model.components
3
+# @package lodel.editorial_model.components
4 4
 #@brief Defines all @ref lodel2_em "EM" components
5 5
 #@ingroup lodel2_em
6 6
 
@@ -17,23 +17,25 @@ LodelContext.expose_modules(globals(), {
17 17
     'lodel.editorial_model.exceptions': ['EditorialModelError', 'assert_edit'],
18 18
     'lodel.leapi.leobject': ['CLASS_ID_FIELDNAME']})
19 19
 
20
-##@brief Abstract class to represent editorial model components
20
+# @brief Abstract class to represent editorial model components
21 21
 # @see EmClass EmField
22 22
 # @todo forbid '.' in uid
23 23
 #@ingroup lodel2_em
24
+
25
+
24 26
 class EmComponent(MlNamedObject):
25
-    
26
-    ##@brief Instanciate an EmComponent
27
+
28
+    # @brief Instanciate an EmComponent
27 29
     # @param uid str : uniq identifier
28 30
     # @param display_name MlString|str|dict : component display_name
29 31
     # @param help_text MlString|str|dict : help_text
30
-    def __init__(self, uid, display_name = None, help_text = None, group = None):
32
+    def __init__(self, uid, display_name=None, help_text=None, group=None):
31 33
         if self.__class__ == EmComponent:
32 34
             raise NotImplementedError('EmComponent is an abstract class')
33 35
         self.uid = uid
34 36
         self.group = group
35 37
         super().__init__(display_name, help_text)
36
-    
38
+
37 39
     def __str__(self):
38 40
         if self.display_name is None:
39 41
             return str(self.uid)
@@ -42,34 +44,34 @@ class EmComponent(MlNamedObject):
42 44
     def d_hash(self):
43 45
         m = hashlib.md5()
44 46
         for data in (
45
-                        self.uid,
46
-                        'NODISPNAME' if self.display_name is None else str(self.display_name.d_hash()),
47
-                        'NOHELP' if self.help_text is None else str(self.help_text.d_hash()),
48
-                        'NOGROUP' if self.group is None else str(self.group.d_hash()),
47
+            self.uid,
48
+            'NODISPNAME' if self.display_name is None else str(self.display_name.d_hash()),
49
+            'NOHELP' if self.help_text is None else str(self.help_text.d_hash()),
50
+            'NOGROUP' if self.group is None else str(self.group.d_hash()),
49 51
         ):
50 52
             m.update(bytes(data, 'utf-8'))
51 53
         return int.from_bytes(m.digest(), byteorder='big')
52 54
 
53 55
 
54
-##@brief Handles editorial model objects classes
56
+# @brief Handles editorial model objects classes
55 57
 #@ingroup lodel2_em
56 58
 class EmClass(EmComponent):
57
-    
58
-    ##@brief Instanciate a new EmClass
59
+
60
+    # @brief Instanciate a new EmClass
59 61
     #@param uid str : uniq identifier
60 62
     #@param display_name MlString|str|dict : component display_name
61 63
     #@param abstract bool : set the class as asbtract if True
62 64
     #@param pure_abstract bool : if True the EmClass will not be represented in
63
-    #leapi dyncode
65
+    # leapi dyncode
64 66
     #@param parents list: parent EmClass list or uid list
65 67
     #@param help_text MlString|str|dict : help_text
66
-    #@param datasources str|tuple|list : The datasource name ( see 
68
+    #@param datasources str|tuple|list : The datasource name ( see
67 69
     #@ref lodel2_datasources ) or two names (first is read_only datasource the
68
-    #second is read write)
70
+    # second is read write)
69 71
     def __init__(
70
-        self, uid, display_name = None, help_text = None, abstract = False,
71
-        parents = None, group = None, pure_abstract = False,
72
-        datasources = 'default'):
72
+            self, uid, display_name=None, help_text=None, abstract=False,
73
+            parents=None, group=None, pure_abstract=False,
74
+            datasources='default'):
73 75
 
74 76
         super().__init__(uid, display_name, help_text, group)
75 77
         self.abstract = bool(abstract)
@@ -85,49 +87,50 @@ class EmClass(EmComponent):
85 87
                 parents = [parents]
86 88
             for parent in parents:
87 89
                 if not isinstance(parent, EmClass):
88
-                    raise ValueError("<class EmClass> expected in parents list, but %s found" % type(parent))
90
+                    raise ValueError(
91
+                        "<class EmClass> expected in parents list, but %s found" % type(parent))
89 92
         else:
90 93
             parents = list()
91 94
         self.parents = parents
92
-        ##@brief Stores EmFields instances indexed by field uid
93
-        self.__fields = dict() 
94
-        
95
+        # @brief Stores EmFields instances indexed by field uid
96
+        self.__fields = dict()
97
+
95 98
         self.group = group
96 99
         if group is None:
97 100
             warnings.warn("NO GROUP FOR EMCLASS %s" % uid)
98 101
         else:
99 102
             group.add_components([self])
100
-    
101
-        #Adding common field
103
+
104
+        # Adding common field
102 105
         if not self.abstract:
103 106
             self.new_field(
104 107
                 CLASS_ID_FIELDNAME,
105
-                display_name = {
108
+                display_name={
106 109
                     'eng': "LeObject subclass identifier",
107 110
                     'fre': "Identifiant de la class fille de LeObject"},
108
-                help_text = {
111
+                help_text={
109 112
                     'eng': "Allow to create instance of the good class when\
110 113
  fetching arbitrary datas from DB"},
111
-                data_handler = 'LeobjectSubclassIdentifier',
112
-                internal = True,
113
-                group = group)
114
+                data_handler='LeobjectSubclassIdentifier',
115
+                internal=True,
116
+                group=group)
114 117
 
115
-    ##@brief Property that represent a dict of all fields (the EmField defined in this class and all its parents)
118
+    # @brief Property that represent a dict of all fields (the EmField defined in this class and all its parents)
116 119
     # @todo use Settings.editorialmodel.groups to determine wich fields should be returned
117 120
     @property
118 121
     def __all_fields(self):
119 122
         res = dict()
120
-        for pfields in [ p.__all_fields for p in self.parents]:
123
+        for pfields in [p.__all_fields for p in self.parents]:
121 124
             res.update(pfields)
122 125
         res.update(self.__fields)
123 126
         return res
124
-    
125
-    ##@brief RO access to datasource attribute
127
+
128
+    # @brief RO access to datasource attribute
126 129
     @property
127 130
     def datasource(self):
128 131
         return self.__datasource
129 132
 
130
-    ##@brief Return the list of all dependencies
133
+    # @brief Return the list of all dependencies
131 134
     #
132 135
     # Reccursive parents listing
133 136
     @property
@@ -140,29 +143,29 @@ class EmClass(EmComponent):
140 143
             res |= parent.parents_recc
141 144
         return res
142 145
 
143
-    ##@brief EmField getter
146
+    # @brief EmField getter
144 147
     # @param uid None | str : If None returns an iterator on EmField instances else return an EmField instance
145 148
     # @param no_parents bool : If True returns only fields defined is this class and not the one defined in parents classes
146 149
     # @return A list on EmFields instances (if uid is None) else return an EmField instance
147 150
     # @todo use Settings.editorialmodel.groups to determine wich fields should be returned
148
-    def fields(self, uid = None, no_parents = False):
151
+    def fields(self, uid=None, no_parents=False):
149 152
         fields = self.__fields if no_parents else self.__all_fields
150 153
         try:
151 154
             return list(fields.values()) if uid is None else fields[uid]
152 155
         except KeyError:
153 156
             raise EditorialModelError("No such EmField '%s'" % uid)
154
-    
155
-    ##@brief Keep in __fields only fields contained in active groups
157
+
158
+    # @brief Keep in __fields only fields contained in active groups
156 159
     def _set_active_fields(self, active_groups):
157 160
         if not Settings.editorialmodel.editormode:
158 161
             active_fields = []
159 162
             for grp_name, agrp in active_groups.items():
160
-                active_fields += [ emc for emc in agrp.components()
161
-                    if isinstance(emc, EmField)]
162
-            self.__fields = { fname:fdh for fname, fdh in self.__fields.items()
163
-                if fdh in active_fields }
163
+                active_fields += [emc for emc in agrp.components()
164
+                                  if isinstance(emc, EmField)]
165
+            self.__fields = {fname: fdh for fname, fdh in self.__fields.items()
166
+                             if fdh in active_fields}
164 167
 
165
-    ##@brief Add a field to the EmClass
168
+    # @brief Add a field to the EmClass
166 169
     # @param emfield EmField : an EmField instance
167 170
     # @warning do not add an EmField allready in another class !
168 171
     # @throw EditorialModelException if an EmField with same uid allready in this EmClass (overwritting allowed from parents)
@@ -170,38 +173,40 @@ class EmClass(EmComponent):
170 173
     def add_field(self, emfield):
171 174
         assert_edit()
172 175
         if emfield.uid in self.__fields:
173
-            raise EditorialModelError("Duplicated uid '%s' for EmField in this class ( %s )" % (emfield.uid, self))
176
+            raise EditorialModelError(
177
+                "Duplicated uid '%s' for EmField in this class ( %s )" % (emfield.uid, self))
174 178
         # Incomplete field override check
175 179
         if emfield.uid in self.__all_fields:
176 180
             parent_field = self.__all_fields[emfield.uid]
177 181
             if not emfield.data_handler_instance.can_override(parent_field.data_handler_instance):
178
-                raise AttributeError("'%s' field override a parent field, but data_handles are not compatible" % emfield.uid)
182
+                raise AttributeError(
183
+                    "'%s' field override a parent field, but data_handles are not compatible" % emfield.uid)
179 184
         self.__fields[emfield.uid] = emfield
180 185
         return emfield
181
-    
182
-    ##@brief Create a new EmField and add it to the EmClass
186
+
187
+    # @brief Create a new EmField and add it to the EmClass
183 188
     # @param data_handler str : A DataHandler name
184 189
     # @param uid str : the EmField uniq id
185
-    # @param **field_kwargs :  EmField constructor parameters ( see @ref EmField.__init__() ) 
190
+    # @param **field_kwargs :  EmField constructor parameters ( see @ref EmField.__init__() )
186 191
     def new_field(self, uid, data_handler, **field_kwargs):
187 192
         assert_edit()
188 193
         return self.add_field(EmField(uid, data_handler, self, **field_kwargs))
189 194
 
190 195
     def d_hash(self):
191 196
         m = hashlib.md5()
192
-        payload = str(super().d_hash())  + ("1" if self.abstract else "0") 
197
+        payload = str(super().d_hash()) + ("1" if self.abstract else "0")
193 198
 
194 199
         for p in sorted(self.parents):
195 200
             payload += str(p.d_hash())
196 201
         for fuid in sorted(self.__fields.keys()):
197 202
             payload += str(self.__fields[fuid].d_hash())
198
-            
203
+
199 204
         m.update(bytes(payload, 'utf-8'))
200 205
         return int.from_bytes(m.digest(), byteorder='big')
201 206
 
202 207
     def __str__(self):
203 208
         return "<class EmClass %s>" % self.uid
204
-    
209
+
205 210
     def __repr__(self):
206 211
         if not self.abstract:
207 212
             abstract = ''
@@ -209,80 +214,82 @@ class EmClass(EmComponent):
209 214
             abstract = 'PureAbstract'
210 215
         else:
211 216
             abstract = 'Abstract'
212
-        return "<class %s EmClass uid=%s>" % (abstract, repr(self.uid) )
217
+        return "<class %s EmClass uid=%s>" % (abstract, repr(self.uid))
213 218
 
214 219
 
215
-##@brief Handles editorial model classes fields
220
+# @brief Handles editorial model classes fields
216 221
 #@ingroup lodel2_em
217 222
 class EmField(EmComponent):
218 223
 
219
-    ##@brief Instanciate a new EmField
224
+    # @brief Instanciate a new EmField
220 225
     # @param uid str : uniq identifier
221 226
     # @param display_name MlString|str|dict : field display_name
222 227
     # @param data_handler str : A DataHandler name
223 228
     # @param help_text MlString|str|dict : help text
224 229
     # @param group EmGroup :
225 230
     # @param **handler_kwargs : data handler arguments
226
-    def __init__(self, uid, data_handler, em_class = None, display_name = None, help_text = None, group = None, **handler_kwargs):
231
+    def __init__(self, uid, data_handler, em_class=None, display_name=None, help_text=None, group=None, **handler_kwargs):
227 232
         from lodel.leapi.datahandlers.base_classes import DataHandler
228 233
         super().__init__(uid, display_name, help_text, group)
229
-        ##@brief The data handler name
234
+        # @brief The data handler name
230 235
         self.data_handler_name = data_handler
231
-        ##@brief The data handler class
236
+        # @brief The data handler class
232 237
         self.data_handler_cls = DataHandler.from_name(data_handler)
233
-        ##@brief The data handler instance associated with this EmField
238
+        # @brief The data handler instance associated with this EmField
234 239
         self.data_handler_instance = self.data_handler_cls(**handler_kwargs)
235
-        ##@brief Stores data handler instanciation options
240
+        # @brief Stores data handler instanciation options
236 241
         self.data_handler_options = handler_kwargs
237
-        ##@brief Stores the emclass that contains this field (set by EmClass.add_field() method)
242
+        # @brief Stores the emclass that contains this field (set by EmClass.add_field() method)
238 243
         self._emclass = em_class
239 244
         if self._emclass is None:
240
-            warnings.warn("No EmClass for field %s" %uid)
245
+            warnings.warn("No EmClass for field %s" % uid)
241 246
         if group is None:
242 247
             warnings.warn("No EmGroup for field  %s" % uid)
243 248
         else:
244 249
             group.add_components([self])
245 250
 
246
-    ##@brief Returns data_handler_name attribute
251
+    # @brief Returns data_handler_name attribute
247 252
     def get_data_handler_name(self):
248 253
         return copy.copy(self.data_handler_name)
249
-        
250
-    ##@brief Returns data_handler_cls attribute
254
+
255
+    # @brief Returns data_handler_cls attribute
251 256
     def get_data_handler_cls(self):
252 257
         return copy.copy(self.data_handler_cls)
253
-    
258
+
254 259
     ##@brief Returne the uid of the emclass which contains this field
255 260
     def get_emclass_uid(self):
256 261
         return self._emclass.uid
257
-    
262
+
258 263
     # @warning Not complete !
259 264
     # @todo Complete the hash when data handlers becomes available
260 265
     def d_hash(self):
261 266
         return int.from_bytes(hashlib.md5(
262
-                        bytes(
263
-                                "%s%s%s" % (  super().d_hash(),
264
-                                            self.data_handler_name,
265
-                                            self.data_handler_options), 
266
-                                'utf-8')
267
+            bytes(
268
+                "%s%s%s" % (super().d_hash(),
269
+                            self.data_handler_name,
270
+                            self.data_handler_options),
271
+                'utf-8')
267 272
         ).digest(), byteorder='big')
268 273
 
269
-##@brief Handles functionnal group of EmComponents
274
+# @brief Handles functionnal group of EmComponents
270 275
 #@ingroup lodel2_em
276
+
277
+
271 278
 class EmGroup(MlNamedObject):
272
-        
273
-    ##@brief Create a new EmGroup
279
+
280
+    # @brief Create a new EmGroup
274 281
     # @note you should NEVER call the constructor yourself. Use Model.add_group instead
275 282
     # @param uid str : Uniq identifier
276 283
     # @param depends list : A list of EmGroup dependencies
277
-    # @param display_name MlString|str : 
278
-    # @param help_text MlString|str : 
279
-    def __init__(self, uid, depends = None, display_name = None, help_text = None):
284
+    # @param display_name MlString|str :
285
+    # @param help_text MlString|str :
286
+    def __init__(self, uid, depends=None, display_name=None, help_text=None):
280 287
         self.uid = uid
281
-        ##@brief Stores the list of groups that depends on this EmGroup indexed by uid
288
+        # @brief Stores the list of groups that depends on this EmGroup indexed by uid
282 289
         self.required_by = dict()
283
-        ##@brief Stores the list of dependencies (EmGroup) indexed by uid
290
+        # @brief Stores the list of dependencies (EmGroup) indexed by uid
284 291
         self.require = dict()
285
-        ##@brief Stores the list of EmComponent instances contained in this group
292
+        # @brief Stores the list of EmComponent instances contained in this group
286 293
         self.__components = set()
287 294
         super().__init__(display_name, help_text)
288 295
 
@@ -291,11 +298,11 @@ class EmGroup(MlNamedObject):
291 298
                 if not isinstance(grp, EmGroup):
292 299
                     raise ValueError("EmGroup expected in depends argument but %s found" % grp)
293 300
                 self.add_dependencie(grp)
294
-    
295
-    ##@brief Returns EmGroup dependencie
301
+
302
+    # @brief Returns EmGroup dependencie
296 303
     # @param recursive bool : if True return all dependencies and their dependencies
297 304
     # @return a dict of EmGroup identified by uid
298
-    def dependencies(self, recursive = False):
305
+    def dependencies(self, recursive=False):
299 306
         res = copy.copy(self.require)
300 307
         if not recursive:
301 308
             return res
@@ -307,11 +314,11 @@ class EmGroup(MlNamedObject):
307 314
                     to_scan.append(new_dep)
308 315
                     res[new_dep.uid] = new_dep
309 316
         return res
310
-    
311
-    ##@brief Returns EmGroup applicants
317
+
318
+    # @brief Returns EmGroup applicants
312 319
     # @param recursive bool : if True return all dependencies and their dependencies
313 320
     # @returns a dict of EmGroup identified by uid
314
-    def applicants(self, recursive = False):
321
+    def applicants(self, recursive=False):
315 322
         res = copy.copy(self.required_by)
316 323
         if not recursive:
317 324
             return res
@@ -323,29 +330,31 @@ class EmGroup(MlNamedObject):
323 330
                     to_scan.append(new_app)
324 331
                     res[new_app.uid] = new_app
325 332
         return res
326
-    
327
-    ##@brief Returns EmGroup components
333
+
334
+    # @brief Returns EmGroup components
328 335
     # @returns a copy of the set of components
329 336
     def components(self):
330 337
         return (self.__components).copy()
331 338
 
332
-    ##@brief Returns EmGroup display_name
339
+    # @brief Returns EmGroup display_name
333 340
     #  @param lang str | None : If None return default lang translation
334 341
     #  @returns None if display_name is None, a str for display_name else
335 342
     def get_display_name(self, lang=None):
336
-        name=self.display_name
337
-        if name is None : return None
338
-        return name.get(lang);
343
+        name = self.display_name
344
+        if name is None:
345
+            return None
346
+        return name.get(lang)
339 347
 
340
-    ##@brief Returns EmGroup help_text
348
+    # @brief Returns EmGroup help_text
341 349
     #  @param lang str | None : If None return default lang translation
342 350
     #  @returns None if display_name is None, a str for display_name else
343 351
     def get_help_text(self, lang=None):
344
-        help=self.help_text
345
-        if help is None : return None
346
-        return help.get(lang);
347
-    
348
-    ##@brief Add components in a group
352
+        help = self.help_text
353
+        if help is None:
354
+            return None
355
+        return help.get(lang)
356
+
357
+    # @brief Add components in a group
349 358
     # @param components list : EmComponent instances list
350 359
     def add_components(self, components):
351 360
         assert_edit()
@@ -356,10 +365,11 @@ class EmGroup(MlNamedObject):
356 365
                     msg %= (component, self)
357 366
                     warnings.warn(msg)
358 367
             elif not isinstance(component, EmClass):
359
-                raise EditorialModelError("Expecting components to be a list of EmComponent, but %s found in the list" % type(component))
368
+                raise EditorialModelError(
369
+                    "Expecting components to be a list of EmComponent, but %s found in the list" % type(component))
360 370
         self.__components |= set(components)
361 371
 
362
-    ##@brief Add a dependencie
372
+    # @brief Add a dependencie
363 373
     # @param em_group EmGroup|iterable : an EmGroup instance or list of instance
364 374
     def add_dependencie(self, grp):
365 375
         assert_edit()
@@ -367,16 +377,17 @@ class EmGroup(MlNamedObject):
367 377
             for group in grp:
368 378
                 self.add_dependencie(group)
369 379
             return
370
-        except TypeError: pass
371
-                
380
+        except TypeError:
381
+            pass
382
+
372 383
         if grp.uid in self.require:
373 384
             return
374 385
         if self.__circular_dependencie(grp):
375 386
             raise EditorialModelError("Circular dependencie detected, cannot add dependencie")
376 387
         self.require[grp.uid] = grp
377 388
         grp.required_by[self.uid] = self
378
-        
379
-    ##@brief Add a applicant
389
+
390
+    # @brief Add a applicant
380 391
     # @param em_group EmGroup|iterable : an EmGroup instance or list of instance
381 392
     # Useless ???
382 393
     def add_applicant(self, grp):
@@ -385,26 +396,27 @@ class EmGroup(MlNamedObject):
385 396
             for group in grp:
386 397
                 self.add_applicant(group)
387 398
             return
388
-        except TypeError: pass
389
-                
399
+        except TypeError:
400
+            pass
401
+
390 402
         if grp.uid in self.required_by:
391 403
             return
392 404
         if self.__circular_applicant(grp):
393 405
             raise EditorialModelError("Circular applicant detected, cannot add applicant")
394 406
         self.required_by[grp.uid] = grp
395 407
         grp.require[self.uid] = self
396
-    
397
-    ##@brief Search for circular dependencie
408
+
409
+    # @brief Search for circular dependencie
398 410
     # @return True if circular dep found else False
399 411
     def __circular_dependencie(self, new_dep):
400 412
         return self.uid in new_dep.dependencies(True)
401
-    
402
-    ##@brief Search for circular applicant
413
+
414
+    # @brief Search for circular applicant
403 415
     # @return True if circular app found else False
404 416
     def __circular_applicant(self, new_app):
405 417
         return self.uid in new_app.applicants(True)
406 418
 
407
-    ##@brief Fancy string representation of an EmGroup
419
+    # @brief Fancy string representation of an EmGroup
408 420
     # @return a string
409 421
     def __str__(self):
410 422
         if self.display_name is None:
@@ -413,11 +425,11 @@ class EmGroup(MlNamedObject):
413 425
             return self.display_name.get()
414 426
 
415 427
     def d_hash(self):
416
-        
428
+
417 429
         payload = "%s%s%s" % (
418
-                                self.uid,
419
-                                'NODNAME' if self.display_name is None else self.display_name.d_hash(),
420
-                                'NOHELP' if self.help_text is None else self.help_text.d_hash()
430
+            self.uid,
431
+            'NODNAME' if self.display_name is None else self.display_name.d_hash(),
432
+            'NOHELP' if self.help_text is None else self.help_text.d_hash()
421 433
         )
422 434
         for recurs in (False, True):
423 435
             deps = self.dependencies(recurs)
@@ -426,11 +438,11 @@ class EmGroup(MlNamedObject):
426 438
         for req_by_uid in self.required_by:
427 439
             payload += req_by_uid
428 440
         return int.from_bytes(
429
-                                bytes(payload, 'utf-8'),
430
-                                byteorder = 'big'
441
+            bytes(payload, 'utf-8'),
442
+            byteorder='big'
431 443
         )
432
-    
433
-    ##@brief Complete string representation of an EmGroup
444
+
445
+    # @brief Complete string representation of an EmGroup
434 446
     # @return a string
435 447
     def __repr__(self):
436
-        return "<class EmGroup '%s' depends : [%s]>" % (self.uid, ', '.join([duid for duid in self.dependencies(False)]) )
448
+        return "<class EmGroup '%s' depends : [%s]>" % (self.uid, ', '.join([duid for duid in self.dependencies(False)]))

+ 63
- 65
lodel/editorial_model/model.py Прегледај датотеку

@@ -15,23 +15,23 @@ LodelContext.expose_modules(globals(), {
15 15
     'lodel.editorial_model.components': ['EmClass', 'EmField', 'EmGroup']})
16 16
 
17 17
 
18
-##@brief Describe an editorial model
18
+# @brief Describe an editorial model
19 19
 #@ingroup lodel2_em
20 20
 class EditorialModel(MlNamedObject):
21
-    
22
-    ##@brief Create a new editorial model
21
+
22
+    # @brief Create a new editorial model
23 23
     # @param name MlString|str|dict : the editorial model name
24 24
     # @param description MlString|str|dict : the editorial model description
25
-    def __init__(self, name, description = None, display_name = None, help_text = None):
25
+    def __init__(self, name, description=None, display_name=None, help_text=None):
26 26
         self.name = MlString(name)
27 27
         self.description = MlString(description)
28
-        ##@brief Stores all groups indexed by id
28
+        # @brief Stores all groups indexed by id
29 29
         self.__groups = dict()
30
-        ##@brief Stores all classes indexed by id
30
+        # @brief Stores all classes indexed by id
31 31
         self.__classes = dict()
32
-        ## @brief Stores all activated groups indexed by id
32
+        #  @brief Stores all activated groups indexed by id
33 33
         self.__active_groups = dict()
34
-        ## @brief Stores all activated classes indexed by id
34
+        #  @brief Stores all activated classes indexed by id
35 35
         self.__active_classes = dict()
36 36
         self.__set_actives()
37 37
         if display_name is None:
@@ -39,10 +39,10 @@ class EditorialModel(MlNamedObject):
39 39
         if help_text is None:
40 40
             help_text = description
41 41
         super().__init__(display_name, help_text)
42
-    
43
-    ##@brief EmClass uids accessor
42
+
43
+    # @brief EmClass uids accessor
44 44
     #@return a dict of emclasses
45
-    def all_classes(self, uid = None):
45
+    def all_classes(self, uid=None):
46 46
         if uid is None:
47 47
             return copy.copy(self.__classes)
48 48
         else:
@@ -50,8 +50,8 @@ class EditorialModel(MlNamedObject):
50 50
                 return copy.copy(self.__classes[uid])
51 51
             except KeyError:
52 52
                 raise EditorialModelException("EmClass not found : '%s'" % uid)
53
-                
54
-    def all_classes_ref(self, uid = None):
53
+
54
+    def all_classes_ref(self, uid=None):
55 55
         if uid is None:
56 56
             return self.__classes
57 57
         else:
@@ -59,16 +59,15 @@ class EditorialModel(MlNamedObject):
59 59
                 return self.__classes[uid]
60 60
             except KeyError:
61 61
                 raise EditorialModelException("EmGroup not found : '%s'" % uid)
62
-                                
63
-    ##@brief active EmClass uids accessor
62
+
63
+    # @brief active EmClass uids accessor
64 64
     #@return a list of class uids
65 65
     def active_classes_uids(self):
66
-            return list(self.__active_classes.keys())
67
-        
68
-    
69
-    ##@brief EmGroups accessor
66
+        return list(self.__active_classes.keys())
67
+
68
+    # @brief EmGroups accessor
70 69
     #@return a dict of groups
71
-    def all_groups(self, uid = None):
70
+    def all_groups(self, uid=None):
72 71
         if uid is None:
73 72
             return copy.copy(self.__groups)
74 73
         else:
@@ -76,10 +75,10 @@ class EditorialModel(MlNamedObject):
76 75
                 return copy.copy(self.__groups[uid])
77 76
             except KeyError:
78 77
                 raise EditorialModelException("EmGroup not found : '%s'" % uid)
79
-    
80
-    ##@brief EmGroups accessor
78
+
79
+    # @brief EmGroups accessor
81 80
     #@return a dict of groups
82
-    def all_groups_ref(self, uid = None):
81
+    def all_groups_ref(self, uid=None):
83 82
         if uid is None:
84 83
             return self.__groups
85 84
         else:
@@ -87,26 +86,26 @@ class EditorialModel(MlNamedObject):
87 86
                 return self.__groups[uid]
88 87
             except KeyError:
89 88
                 raise EditorialModelException("EmGroup not found : '%s'" % uid)
90
-                
91
-    ##@brief active EmClass uids accessor
89
+
90
+    # @brief active EmClass uids accessor
92 91
     #@return a list of class uids
93 92
     def active_groups_uids(self):
94
-            return list(self.__active_groups.keys())
93
+        return list(self.__active_groups.keys())
95 94
 
96
-    ##@brief EmClass accessor
95
+    # @brief EmClass accessor
97 96
     #@param uid None | str : give this argument to get a specific EmClass
98 97
     #@return if uid is given returns an EmClass else returns an EmClass
99 98
     # iterator
100 99
     #@todo use Settings.editorialmodel.groups to determine wich classes should
101 100
     # be returned
102
-    def classes(self, uid = None):
101
+    def classes(self, uid=None):
103 102
         try:
104
-            return self.__elt_getter(   self.__active_classes,
105
-                                        uid)
103
+            return self.__elt_getter(self.__active_classes,
104
+                                     uid)
106 105
         except KeyError:
107 106
             raise EditorialModelException("EmClass not found : '%s'" % uid)
108
-    
109
-    ##@brief EmClass child list accessor
107
+
108
+    # @brief EmClass child list accessor
110 109
     #@param uid str : the EmClass uid
111 110
     #@return a set of EmClass
112 111
     def get_class_childs(self, uid):
@@ -117,24 +116,23 @@ class EditorialModel(MlNamedObject):
117 116
                 res.append(cls)
118 117
         return set(res)
119 118
 
120
-
121
-    ##@brief EmGroup getter
119
+    # @brief EmGroup getter
122 120
     # @param uid None | str : give this argument to get a specific EmGroup
123 121
     # @return if uid is given returns an EmGroup else returns an EmGroup iterator
124
-    def groups(self, uid = None):
122
+    def groups(self, uid=None):
125 123
         try:
126
-            return self.__elt_getter(   self.__active_groups,
127
-                                        uid)
124
+            return self.__elt_getter(self.__active_groups,
125
+                                     uid)
128 126
         except KeyError:
129 127
             raise EditorialModelException("EmGroup not found : '%s'" % uid)
130
-    
131
-    ##@brief Private getter for __groups or __classes
128
+
129
+    # @brief Private getter for __groups or __classes
132 130
     # @see classes() groups()
133 131
     def __elt_getter(self, elts, uid):
134 132
         return list(elts.values()) if uid is None else elts[uid]
135
-    
136
-    ##@brief Update the EditorialModel.__active_groups and
137
-    #EditorialModel.__active_classes attibutes
133
+
134
+    # @brief Update the EditorialModel.__active_groups and
135
+    # EditorialModel.__active_classes attibutes
138 136
     def __set_actives(self):
139 137
         if Settings.editorialmodel.editormode:
140 138
             logger.warning("All EM groups active because editormode in ON")
@@ -142,7 +140,7 @@ class EditorialModel(MlNamedObject):
142 140
             self.__active_groups = self.__groups
143 141
             self.__active_classes = self.__classes
144 142
         else:
145
-            #determine groups first
143
+            # determine groups first
146 144
             self.__active_groups = dict()
147 145
             self.__active_classes = dict()
148 146
             for agrp in Settings.editorialmodel.groups:
@@ -159,13 +157,13 @@ class EditorialModel(MlNamedObject):
159 157
                 raise RuntimeError("No active class found. Abording")
160 158
             for clsname, acls in self.__active_classes.items():
161 159
                 acls._set_active_fields(self.__active_groups)
162
-    
163
-    ##@brief EmField getter
160
+
161
+    # @brief EmField getter
164 162
     # @param uid str : An EmField uid represented by "CLASSUID.FIELDUID"
165 163
     # @return Fals or an EmField instance
166 164
     #
167 165
     # @todo delete it, useless...
168
-    def field(self, uid = None):
166
+    def field(self, uid=None):
169 167
         spl = uid.split('.')
170 168
         if len(spl) != 2:
171 169
             raise ValueError("Malformed EmField identifier : '%s'" % uid)
@@ -181,7 +179,7 @@ class EditorialModel(MlNamedObject):
181 179
             pass
182 180
         return False
183 181
 
184
-    ##@brief Add a class to the editorial model
182
+    # @brief Add a class to the editorial model
185 183
     # @param emclass EmClass : the EmClass instance to add
186 184
     # @return emclass
187 185
     def add_class(self, emclass):
@@ -193,7 +191,7 @@ class EditorialModel(MlNamedObject):
193 191
         self.__classes[emclass.uid] = emclass
194 192
         return emclass
195 193
 
196
-    ##@brief Add a group to the editorial model
194
+    # @brief Add a group to the editorial model
197 195
     # @param emgroup EmGroup : the EmGroup instance to add
198 196
     # @return emgroup
199 197
     def add_group(self, emgroup):
@@ -205,15 +203,15 @@ class EditorialModel(MlNamedObject):
205 203
         self.__groups[emgroup.uid] = emgroup
206 204
         return emgroup
207 205
 
208
-    ##@brief Add a new EmClass to the editorial model
206
+    # @brief Add a new EmClass to the editorial model
209 207
     #@param uid str : EmClass uid
210
-    #@param **kwargs : EmClass constructor options ( 
208
+    #@param **kwargs : EmClass constructor options (
211 209
     # see @ref lodel.editorial_model.component.EmClass.__init__() )
212 210
     def new_class(self, uid, **kwargs):
213 211
         assert_edit()
214 212
         return self.add_class(EmClass(uid, **kwargs))
215
-    
216
-    ##@brief Add a new EmGroup to the editorial model
213
+
214
+    # @brief Add a new EmGroup to the editorial model
217 215
     #@param uid str : EmGroup uid
218 216
     #@param *kwargs : EmGroup constructor keywords arguments (
219 217
     # see @ref lodel.editorial_model.component.EmGroup.__init__() )
@@ -221,7 +219,7 @@ class EditorialModel(MlNamedObject):
221 219
         assert_edit()
222 220
         return self.add_group(EmGroup(uid, **kwargs))
223 221
 
224
-    ##@brief Save a model
222
+    # @brief Save a model
225 223
     # @param translator module : The translator module to use
226 224
     # @param **translator_args
227 225
     def save(self, translator, **translator_kwargs):
@@ -229,14 +227,15 @@ class EditorialModel(MlNamedObject):
229 227
         if isinstance(translator, str):
230 228
             translator = self.translator_from_name(translator)
231 229
         return translator.save(self, **translator_kwargs)
232
-    
233
-    ##@brief Raise an error if lodel is not in EM edition mode
230
+
231
+    # @brief Raise an error if lodel is not in EM edition mode
234 232
     @staticmethod
235 233
     def raise_if_ro():
236 234
         if not Settings.editorialmodel.editormode:
237
-            raise EditorialModelError("Lodel in not in EM editor mode. The EM is in read only state")
235
+            raise EditorialModelError(
236
+                "Lodel in not in EM editor mode. The EM is in read only state")
238 237
 
239
-    ##@brief Load a model
238
+    # @brief Load a model
240 239
     # @param translator module : The translator module to use
241 240
     # @param **translator_args
242 241
     @classmethod
@@ -247,7 +246,7 @@ class EditorialModel(MlNamedObject):
247 246
         res.__set_actives()
248 247
         return res
249 248
 
250
-    ##@brief Return a translator module given a translator name
249
+    # @brief Return a translator module given a translator name
251 250
     # @param translator_name str : The translator name
252 251
     # @return the translator python module
253 252
     # @throw NameError if the translator does not exists
@@ -259,12 +258,12 @@ class EditorialModel(MlNamedObject):
259 258
         except ImportError:
260 259
             raise NameError("No translator named %s")
261 260
         return mod
262
-        
263
-    ##@brief Lodel hash
261
+
262
+    # @brief Lodel hash
264 263
     def d_hash(self):
265 264
         payload = "%s%s" % (
266
-                            self.name,
267
-                            'NODESC' if self.description is None else self.description.d_hash()
265
+            self.name,
266
+            'NODESC' if self.description is None else self.description.d_hash()
268 267
         )
269 268
         for guid in sorted(self.__groups):
270 269
             payload += str(self.__groups[guid].d_hash())
@@ -273,7 +272,6 @@ class EditorialModel(MlNamedObject):
273 272
             payload += str(self.__classes[cuid].d_hash())
274 273
 
275 274
         return int.from_bytes(
276
-                                hashlib.md5(bytes(payload, 'utf-8')).digest(),
277
-                                byteorder='big'
275
+            hashlib.md5(bytes(payload, 'utf-8')).digest(),
276
+            byteorder='big'
278 277
         )
279
-

+ 4
- 2
lodel/mlnamedobject/mlnamedobject.py Прегледај датотеку

@@ -4,11 +4,13 @@ from lodel.context import LodelContext
4 4
 LodelContext.expose_modules(globals(), {
5 5
     'lodel.utils.mlstring': ['MlString']})
6 6
 
7
-## @package lodel.mlnamedobject Lodel2 description of objects module
7
+# @package lodel.mlnamedobject Lodel2 description of objects module
8 8
 #
9 9
 # Display name and Description of a lodel2 object
10 10
 
11
-##@brief Class allows dislpay name and help text for lodel2 objects and fields
11
+# @brief Class allows display name and help text for lodel2 objects and fields
12
+
13
+
12 14
 class MlNamedObject(object):
13 15
 
14 16
     def __init__(self, display_name=None, help_text=None):

+ 79
- 67
lodel/settings/settings.py Прегледај датотеку

@@ -5,40 +5,42 @@ import os
5 5
 import configparser
6 6
 import copy
7 7
 import warnings
8
-import types # for dynamic bindings
8
+import types  # for dynamic bindings
9 9
 from collections import namedtuple
10 10
 
11 11
 from lodel.context import LodelContext
12 12
 
13
-LodelContext.expose_modules(globals(),{
13
+LodelContext.expose_modules(globals(), {
14 14
     'lodel.logger': 'logger',
15 15
     'lodel.settings.utils': ['SettingsError', 'SettingsErrors'],
16 16
     'lodel.validator.validator': ['Validator', 'LODEL2_CONF_SPECS',
17
-        'confspec_append'],
18
-    'lodel.settings.settings_loader':['SettingsLoader']})
19
-    
17
+                                  'confspec_append'],
18
+    'lodel.settings.settings_loader': ['SettingsLoader']})
20 19
 
21
-## @package lodel.settings.settings Lodel2 settings module
20
+
21
+#  @package lodel.settings.settings Lodel2 settings module
22 22
 #
23 23
 # Contains the class that handles the namedtuple tree of settings
24 24
 
25
-##@brief A default python system lib path
25
+# @brief A default python system lib path
26 26
 PYTHON_SYS_LIB_PATH = '/usr/local/lib/python{major}.{minor}/'.format(
27 27
 
28
-                                                major = sys.version_info.major,
29
-                                                minor = sys.version_info.minor)
28
+    major=sys.version_info.major,
29
+    minor=sys.version_info.minor)
30
+
30 31
 
31 32
 class MetaSettings(type):
33
+
32 34
     @property
33 35
     def s(self):
34 36
         self.singleton_assert(True)
35 37
         return self.instance.settings
36 38
 
37
-##@brief Handles configuration load etc.
39
+# @brief Handles configuration load etc.
38 40
 #
39
-# To see howto bootstrap Settings and use it in lodel instance see 
41
+# To see howto bootstrap Settings and use it in lodel instance see
40 42
 # @ref lodel.settings
41
-# 
43
+#
42 44
 # @par Basic instance usage
43 45
 # For example if a file defines confs like :
44 46
 # <pre>
@@ -50,15 +52,15 @@ class MetaSettings(type):
50 52
 #
51 53
 # @par Init sequence
52 54
 # The initialization sequence is a bit tricky. In fact, plugins adds allowed
53
-# configuration sections/values, but the list of plugins to load are in... the 
55
+# configuration sections/values, but the list of plugins to load are in... the
54 56
 # settings.
55 57
 # Here is the conceptual presentation of Settings class initialization stages :
56 58
 #   -# Preloading (sets values like lodel2 library path or the plugins path)
57
-#   -# Ask a @ref lodel.settings.setting_loader.SettingsLoader to load all 
58
-#configurations files
59
+#   -# Ask a @ref lodel.settings.setting_loader.SettingsLoader to load all
60
+# configurations files
59 61
 #   -# Fetch the list of plugins in the loaded settings
60
-#   -# Merge plugins settings specification with the global lodel settings 
61
-#specs ( see @ref lodel.plugin )
62
+#   -# Merge plugins settings specification with the global lodel settings
63
+# specs ( see @ref lodel.plugin )
62 64
 #   -# Fetch all settings from the merged settings specs
63 65
 #
64 66
 # @par Init sequence in practical
@@ -68,39 +70,41 @@ class MetaSettings(type):
68 70
 #   -# @ref Settings.__populate_from_specs() (step 5)
69 71
 #   -# And finally @ref Settings.__confs_to_namedtuple()
70 72
 #
71
-# @todo handles default sections for variable sections (sections ending with 
73
+# @todo handles default sections for variable sections (sections ending with
72 74
 # '.*')
73 75
 # @todo delete the first stage, the lib path HAVE TO BE HARDCODED. In fact
74
-#when we will run lodel in production the lodel2 lib will be in the python path
76
+# when we will run lodel in production the lodel2 lib will be in the python path
75 77
 #@todo add log messages (now we can)
78
+
79
+
76 80
 class Settings(object, metaclass=MetaSettings):
77 81
 
78
-    ## @brief Stores the singleton instance
82
+    #  @brief Stores the singleton instance
79 83
     instance = None
80
-    
81
-    ## @brief Instanciate the Settings singleton
84
+
85
+    #  @brief Instanciate the Settings singleton
82 86
     # @param conf_dir str : The configuration directory
83 87
     #@param custom_confspecs None | dict : if given overwrite default lodel2
84
-    #confspecs
85
-    def __init__(self, conf_dir, custom_confspecs = None):
86
-        self.singleton_assert() # check that it is the only instance
88
+    # confspecs
89
+    def __init__(self, conf_dir, custom_confspecs=None):
90
+        self.singleton_assert()  # check that it is the only instance
87 91
         Settings.instance = self
88
-        ## @brief Configuration specification
92
+        #  @brief Configuration specification
89 93
         #
90 94
         # Initialized by Settings.__bootstrap() method
91 95
         self.__conf_specs = custom_confspecs
92
-        ## @brief Stores the configurations in namedtuple tree
96
+        #  @brief Stores the configurations in namedtuple tree
93 97
         self.__confs = None
94 98
         self.__conf_dir = conf_dir
95 99
         self.__started = False
96 100
         self.__bootstrap()
97
-    
98
-    ## @brief Get the named tuple representing configuration
101
+
102
+    #  @brief Get the named tuple representing configuration
99 103
     @property
100 104
     def settings(self):
101 105
         return self.__confs.lodel2
102
-    
103
-    ## @brief Delete the singleton instance
106
+
107
+    #  @brief Delete the singleton instance
104 108
     @classmethod
105 109
     def stop(cls):
106 110
         del(cls.instance)
@@ -110,7 +114,7 @@ class Settings(object, metaclass=MetaSettings):
110 114
     def started(cls):
111 115
         return cls.instance is not None and cls.instance.__started
112 116
 
113
-    ##@brief An utility method that raises if the singleton is not in a good
117
+    # @brief An utility method that raises if the singleton is not in a good
114 118
     # state
115 119
     #@param expect_instanciated bool : if True we expect that the class is
116 120
     # allready instanciated, else not
@@ -124,17 +128,17 @@ class Settings(object, metaclass=MetaSettings):
124 128
             if cls.started():
125 129
                 raise RuntimeError("The Settings class is already started")
126 130
 
127
-    ##@brief Saves a new configuration for section confname
131
+    # @brief Saves a new configuration for section confname
128 132
     #@param confname is the name of the modified section
129 133
     #@param confvalue is a dict with variables to save
130 134
     #@param validator is a dict with adapted validator
131 135
     @classmethod
132
-    def set(cls, confname, confvalue,validator):
136
+    def set(cls, confname, confvalue, validator):
133 137
         loader = SettingsLoader(cls.instance.__conf_dir)
134
-        confkey=confname.rpartition('.')
138
+        confkey = confname.rpartition('.')
135 139
         loader.setoption(confkey[0], confkey[2], confvalue, validator)
136 140
 
137
-    ##@brief This method handles Settings instance bootstraping
141
+    # @brief This method handles Settings instance bootstraping
138 142
     def __bootstrap(self):
139 143
         LodelContext.expose_modules(globals(), {
140 144
             'lodel.plugin.plugins': ['Plugin', 'PluginError']})
@@ -144,9 +148,9 @@ class Settings(object, metaclass=MetaSettings):
144 148
         else:
145 149
             lodel2_specs = self.__conf_specs
146 150
             self.__conf_specs = None
147
-        loader = SettingsLoader(self.__conf_dir) 
151
+        loader = SettingsLoader(self.__conf_dir)
148 152
         plugin_list = []
149
-        for ptype_name,ptype in Plugin.plugin_types().items():
153
+        for ptype_name, ptype in Plugin.plugin_types().items():
150 154
             pls = ptype.plist_confspecs()
151 155
             lodel2_specs = confspec_append(lodel2_specs, **pls)
152 156
             cur_list = loader.getoption(
@@ -162,13 +166,15 @@ class Settings(object, metaclass=MetaSettings):
162 166
                 plugin_list += cur_list
163 167
             except TypeError:
164 168
                 plugin_list += [cur_list]
165
-        #Checking confspecs
169
+        # Checking confspecs
166 170
         for section in lodel2_specs:
167 171
             if section.lower() != section:
168
-                raise SettingsError("Only lower case are allowed in section name (thank's ConfigParser...)")
172
+                raise SettingsError(
173
+                    "Only lower case are allowed in section name (thank's ConfigParser...)")
169 174
             for kname in lodel2_specs[section]:
170 175
                 if kname.lower() != kname:
171
-                    raise SettingsError("Only lower case are allowed in section name (thank's ConfigParser...)")
176
+                    raise SettingsError(
177
+                        "Only lower case are allowed in section name (thank's ConfigParser...)")
172 178
 
173 179
         # Starting the Plugins class
174 180
         logger.debug("Starting lodel.plugin.Plugin class")
@@ -181,13 +187,13 @@ class Settings(object, metaclass=MetaSettings):
181 187
                 specs.append(Plugin.get(plugin_name).confspecs)
182 188
             except PluginError as e:
183 189
                 errors.append(SettingsError(msg=str(e)))
184
-        if len(errors) > 0: #Raise all plugins import errors
190
+        if len(errors) > 0:  # Raise all plugins import errors
185 191
             raise SettingsErrors(errors)
186 192
         self.__conf_specs = self.__merge_specs(specs)
187 193
         self.__populate_from_specs(self.__conf_specs, loader)
188 194
         self.__started = True
189
-    
190
-    ##@brief Produce a configuration specification dict by merging all specifications
195
+
196
+    # @brief Produce a configuration specification dict by merging all specifications
191 197
     #
192 198
     # Merges global lodel2 conf spec from @ref lodel.settings.validator.LODEL2_CONF_SPECS
193 199
     # and configuration specifications from loaded plugins
@@ -198,31 +204,35 @@ class Settings(object, metaclass=MetaSettings):
198 204
         for spec in specs:
199 205
             for section in spec:
200 206
                 if section.lower() != section:
201
-                    raise SettingsError("Only lower case are allowed in section name (thank's ConfigParser...)")
207
+                    raise SettingsError(
208
+                        "Only lower case are allowed in section name (thank's ConfigParser...)")
202 209
                 if section not in res:
203 210
                     res[section] = dict()
204 211
                 for kname in spec[section]:
205 212
                     if kname.lower() != kname:
206
-                        raise SettingsError("Only lower case are allowed in section name (thank's ConfigParser...)")
213
+                        raise SettingsError(
214
+                            "Only lower case are allowed in section name (thank's ConfigParser...)")
207 215
                     if kname in res[section]:
208
-                        raise SettingsError("Duplicated key '%s' in section '%s'" % (kname, section))
216
+                        raise SettingsError("Duplicated key '%s' in section '%s'" %
217
+                                            (kname, section))
209 218
                     res[section.lower()][kname] = copy.copy(spec[section][kname])
210 219
         return res
211
-    
212
-    ##@brief Populate the Settings instance with options values fetched with the loader from merged specs
220
+
221
+    # @brief Populate the Settings instance with options values fetched with the loader from merged specs
213 222
     #
214 223
     # Populate the __confs attribute
215 224
     # @param specs dict : Settings specification dictionnary as returned by __merge_specs
216 225
     # @param loader SettingsLoader : A SettingsLoader instance
217 226
     def __populate_from_specs(self, specs, loader):
218 227
         self.__confs = dict()
219
-        specs = copy.copy(specs) #Avoid destroying original specs dict (may be useless)
228
+        specs = copy.copy(specs)  # Avoid destroying original specs dict (may be useless)
220 229
         # Construct final specs dict replacing variable sections
221 230
         # by the actual existing sections
222
-        variable_sections = [ section for section in specs if section.endswith('.*') ]
231
+        variable_sections = [section for section in specs if section.endswith('.*')]
223 232
         for vsec in variable_sections:
224 233
             preffix = vsec[:-2]
225
-            for section in loader.getsection(preffix, 'default'): #WARNING : hardcoded default section
234
+            # WARNING : hardcoded default section
235
+            for section in loader.getsection(preffix, 'default'):
226 236
                 specs[section] = copy.copy(specs[vsec])
227 237
             del(specs[vsec])
228 238
         # Fetching values for sections
@@ -238,8 +248,8 @@ class Settings(object, metaclass=MetaSettings):
238 248
 
239 249
         self.__confs_to_namedtuple()
240 250
         pass
241
-    
242
-    ##@brief Transform the __confs attribute into imbricated namedtuple
251
+
252
+    # @brief Transform the __confs attribute into imbricated namedtuple
243 253
     #
244 254
     # For example an option named "foo" in a section named "hello.world" will
245 255
     # be acessible with self.__confs.hello.world.foo
@@ -257,7 +267,7 @@ class Settings(object, metaclass=MetaSettings):
257 267
             section_name = ""
258 268
             cur = section_tree
259 269
             for sec_part in spl:
260
-                section_name += sec_part+'.'
270
+                section_name += sec_part + '.'
261 271
                 if sec_part not in cur:
262 272
                     cur[sec_part] = dict()
263 273
                 cur = cur[sec_part]
@@ -267,35 +277,35 @@ class Settings(object, metaclass=MetaSettings):
267 277
                     raise SettingsError("Duplicated key for '%s.%s'" % (section_name, kname))
268 278
                 cur[kname] = kval
269 279
 
270
-        path = [ ('root', section_tree) ]
280
+        path = [('root', section_tree)]
271 281
         visited = set()
272
-        
282
+
273 283
         curname = 'root'
274 284
         nodename = 'Lodel2Settings'
275 285
         cur = section_tree
276 286
         while True:
277 287
             visited.add(nodename)
278
-            left = [    (kname, cur[kname])
279
-                        for kname in cur
280
-                        if nodename+'.'+kname.title() not in visited and isinstance(cur[kname], dict)
288
+            left = [(kname, cur[kname])
289
+                    for kname in cur
290
+                    if nodename + '.' + kname.title() not in visited and isinstance(cur[kname], dict)
281 291
                     ]
282 292
             if len(left) == 0:
283 293
                 name, leaf = path.pop()
284 294
                 typename = nodename.replace('.', '')
285 295
                 if len(path) == 0:
286 296
                     # END
287
-                    self.__confs = self.__tree2namedtuple(leaf,typename)
297
+                    self.__confs = self.__tree2namedtuple(leaf, typename)
288 298
                     break
289 299
                 else:
290
-                    path[-1][1][name] = self.__tree2namedtuple(leaf,typename)
300
+                    path[-1][1][name] = self.__tree2namedtuple(leaf, typename)
291 301
                 nodename = '.'.join(nodename.split('.')[:-1])
292 302
                 cur = path[-1][1]
293 303
             else:
294 304
                 curname, cur = left[0]
295
-                path.append( (curname, cur) )
305
+                path.append((curname, cur))
296 306
                 nodename += '.' + curname.title()
297
-    
298
-    ##@brief Forge a named tuple given a conftree node
307
+
308
+    # @brief Forge a named tuple given a conftree node
299 309
     # @param conftree dict : A conftree node
300 310
     # @param name str
301 311
     # @return a named tuple with fieldnames corresponding to conftree keys
@@ -303,11 +313,13 @@ class Settings(object, metaclass=MetaSettings):
303 313
         ResNamedTuple = namedtuple(name, conftree.keys())
304 314
         return ResNamedTuple(**conftree)
305 315
 
316
+
306 317
 class MetaSettingsRO(type):
318
+
307 319
     def __getattr__(self, name):
308 320
         return getattr(Settings.s, name)
309
-        
310 321
 
311
-## @brief A class that provide . notation read only access to configurations
322
+
323
+#  @brief A class that provide . notation read only access to configurations
312 324
 class SettingsRO(object, metaclass=MetaSettingsRO):
313 325
     pass

+ 1
- 1
lodel/settings/settings_loader.py Прегледај датотеку

@@ -181,7 +181,7 @@ class SettingsLoader(object):
181 181
         for key_id, filename in remains.items():
182 182
             err_l.append(SettingsError(msg="Invalid configuration key", \
183 183
                                     key_id=key_id, \
184
-                                    filename=filename))
184
+                                    filename =filename))
185 185
         if len(err_l) > 0:
186 186
             raise SettingsErrors(err_l)
187 187
         else:

+ 1
- 1
lodel/utils/datetime.py Прегледај датотеку

@@ -6,4 +6,4 @@ def get_utc_timestamp():
6 6
     d = datetime.datetime.utcnow()
7 7
     epoch = datetime.datetime(1970, 1, 1)
8 8
     t = (d - epoch).total_seconds()
9
-    return t
9
+    return t

+ 17
- 16
lodel/utils/mlstring.py Прегледај датотеку

@@ -5,9 +5,9 @@ import hashlib
5 5
 import json
6 6
 
7 7
 
8
-##@brief Stores multilangage string
8
+# @brief Stores multilangage string
9 9
 class MlString(object):
10
-    
10
+
11 11
     __default_lang = 'eng'
12 12
 
13 13
     langs = [
@@ -17,7 +17,7 @@ class MlString(object):
17 17
         'esp',
18 18
     ]
19 19
 
20
-    ##@brief Create a new MlString instance
20
+    # @brief Create a new MlString instance
21 21
     # @param arg str | dict : Can be a json string, a string or a dict. It could be also a MlString object
22 22
     def __init__(self, arg):
23 23
         self.values = dict()
@@ -31,11 +31,12 @@ class MlString(object):
31 31
         elif isinstance(arg, MlString):
32 32
             self.values = copy.copy(arg.values)
33 33
         else:
34
-            raise ValueError('<class str>, <class dict> or <class MlString> expected, but %s found' % type(arg))
35
-    
36
-    ##@brief Return a translation given a lang
34
+            raise ValueError(
35
+                '<class str>, <class dict> or <class MlString> expected, but %s found' % type(arg))
36
+
37
+    # @brief Return a translation given a lang
37 38
     # @param lang str | None : If None return default lang translation
38
-    def get(self, lang = None):
39
+    def get(self, lang=None):
39 40
         lang = self.__default_lang if lang is None else lang
40 41
         if not self.lang_is_valid(lang):
41 42
             raise ValueError("Invalid lang : '%s'" % lang)
@@ -44,7 +45,7 @@ class MlString(object):
44 45
         else:
45 46
             return str(self)
46 47
 
47
-    ##@brief Set a translation
48
+    # @brief Set a translation
48 49
     # @param lang str : the lang
49 50
     # @param val str | None:  the translation if None delete the translation
50 51
     def set(self, lang, val):
@@ -57,7 +58,7 @@ class MlString(object):
57 58
         else:
58 59
             self.values[lang] = val
59 60
 
60
-    ##@brief Checks that given lang is valid
61
+    # @brief Checks that given lang is valid
61 62
     # @param lang str : the lang
62 63
     @classmethod
63 64
     def lang_is_valid(cls, lang):
@@ -65,16 +66,16 @@ class MlString(object):
65 66
             raise ValueError('Invalid value for lang. Str expected but %s found' % type(lang))
66 67
         return lang in cls.langs
67 68
 
68
-    ##@brief Get or set the default lang
69
+    # @brief Get or set the default lang
69 70
     @classmethod
70
-    def default_lang(cls, lang = None):
71
+    def default_lang(cls, lang=None):
71 72
         if lang is None:
72 73
             return cls.__default_lang
73 74
         if not cls.lang_is_valid(lang):
74 75
             raise ValueError('lang "%s" is not valid"' % lang)
75 76
         cls.__default_lang = lang
76
-    
77
-    ##@brief Return a mlstring loaded from a json string
77
+
78
+    # @brief Return a mlstring loaded from a json string
78 79
     # @param json_str str : Json string
79 80
     @classmethod
80 81
     def from_json(cls, json_str):
@@ -89,13 +90,13 @@ class MlString(object):
89 90
     def d_hash(self):
90 91
         m = hashlib.md5()
91 92
         for lang in sorted(list(self.values.keys())):
92
-            m.update(bytes(lang+";"+self.values[lang], 'utf-8'))
93
+            m.update(bytes(lang + ";" + self.values[lang], 'utf-8'))
93 94
         return int.from_bytes(m.digest(), byteorder='big')
94 95
 
95 96
     def __eq__(self, a):
96 97
         return hash(self) == hash(a)
97
-    
98
-    ## @return The default langage translation or any available translation
98
+
99
+    # @return The default langage translation or any available translation
99 100
     def __str__(self):
100 101
         if self.__default_lang in self.values:
101 102
             return self.values[self.__default_lang]

+ 107
- 75
lodel/validator/validator.py Прегледај датотеку

@@ -11,30 +11,34 @@ from lodel.context import LodelContext
11 11
 LodelContext.expose_modules(globals(), {
12 12
     'lodel.mlnamedobject.mlnamedobject': ['MlNamedObject'],
13 13
     'lodel.exceptions': ['LodelException', 'LodelExceptions',
14
-    'LodelFatalError', 'FieldValidationError']})
14
+                         'LodelFatalError', 'FieldValidationError']})
15 15
 
16
-## @package lodel.settings.validator Lodel2 settings validators/cast module
16
+# @package lodel.settings.validator Lodel2 settings validators/cast module
17 17
 #
18 18
 # Validator are registered in the Validator class.
19 19
 # @note to get a list of registered default validators just run
20 20
 # <pre>$ python scripts/settings_validator.py</pre>
21 21
 
22
-##@brief Exception class that should be raised when a validation fails
22
+# @brief Exception class that should be raised when a validation fails
23
+
24
+
23 25
 class ValidationError(Exception):
24 26
     pass
25 27
 
26
-##@brief Handles settings validators
28
+# @brief Handles settings validators
27 29
 #
28 30
 # Class instance are callable objects that takes a value argument (the value to validate). It raises
29 31
 # a ValidationError if validation fails, else it returns a properly
30 32
 # casted value.
31 33
 #@todo implement an IP validator and use it in multisite confspec
34
+
35
+
32 36
 class Validator(MlNamedObject):
33 37
 
34 38
     _validators = dict()
35 39
     _description = dict()
36 40
 
37
-    ##@brief Instanciate a validator
41
+    # @brief Instanciate a validator
38 42
     #@param name str : validator name
39 43
     #@param none_is_valid bool : if True None will be validated
40 44
     #@param **kwargs : more arguement for the validator
@@ -48,7 +52,7 @@ class Validator(MlNamedObject):
48 52
             display_name = name
49 53
         super().__init__(display_name, help_text)
50 54
 
51
-    ##@brief Call the validator
55
+    # @brief Call the validator
52 56
     # @param value *
53 57
     # @return properly casted value
54 58
     # @throw ValidationError
@@ -61,7 +65,7 @@ class Validator(MlNamedObject):
61 65
         except Exception as exp:
62 66
             raise ValidationError(exp)
63 67
 
64
-    ##@brief Register a new validator
68
+    # @brief Register a new validator
65 69
     # @param name str : validator name
66 70
     # @param callback callable : the function that will validate a value
67 71
     # @param description str
@@ -75,12 +79,12 @@ class Validator(MlNamedObject):
75 79
         cls._validators[name] = callback
76 80
         cls._description[name] = description
77 81
 
78
-    ##@brief Get the validator list associated with description
82
+    # @brief Get the validator list associated with description
79 83
     @classmethod
80 84
     def validators_list(cls):
81 85
         return copy.copy(cls._description)
82 86
 
83
-    ##@brief Create and register a list validator
87
+    # @brief Create and register a list validator
84 88
     # @param elt_validator callable : The validator that will be used for validate each elt value
85 89
     # @param validator_name str
86 90
     # @param description None | str
@@ -99,7 +103,7 @@ class Validator(MlNamedObject):
99 103
         cls.register_validator(validator_name, list_validator, description)
100 104
         return cls(validator_name)
101 105
 
102
-    ##@brief Create and register a list validator which reads an array and returns a string
106
+    # @brief Create and register a list validator which reads an array and returns a string
103 107
     # @param elt_validator callable : The validator that will be used for validate each elt value
104 108
     # @param validator_name str
105 109
     # @param description None | str
@@ -111,12 +115,12 @@ class Validator(MlNamedObject):
111 115
             res = ''
112 116
             for elt in value:
113 117
                 res += elt_validator(elt) + ','
114
-            return res[:len(res)-1]
118
+            return res[:len(res) - 1]
115 119
         description = "Convert value to a string" if description is None else description
116 120
         cls.register_validator(validator_name, write_list_validator, description)
117 121
         return cls(validator_name)
118 122
 
119
-    ##@brief Create and register a regular expression validator
123
+    # @brief Create and register a regular expression validator
120 124
     # @param pattern str : regex pattern
121 125
     # @param validator_name str : The validator name
122 126
     # @param description str : Validator description
@@ -125,17 +129,17 @@ class Validator(MlNamedObject):
125 129
     def create_re_validator(cls, pattern, validator_name, description=None):
126 130
         def re_validator(value):
127 131
             if not re.match(pattern, value):
128
-                raise ValidationError(\
129
-                    "The value '%s' doesn't match the following pattern '%s'" \
132
+                raise ValidationError(
133
+                    "The value '%s' doesn't match the following pattern '%s'"
130 134
                     % pattern)
131 135
             return value
132
-        #registering the validator
133
-        cls.register_validator(validator_name, re_validator, \
134
-            ("Match value to '%s'" % pattern) \
135
-            if description is None else description)
136
+        # registering the validator
137
+        cls.register_validator(validator_name, re_validator,
138
+                               ("Match value to '%s'" % pattern)
139
+                               if description is None else description)
136 140
         return cls(validator_name)
137 141
 
138
-    ## @return a list of registered validators
142
+    #  @return a list of registered validators
139 143
     @classmethod
140 144
     def validators_list_str(cls):
141 145
         result = ''
@@ -146,12 +150,16 @@ class Validator(MlNamedObject):
146 150
             result += "\n"
147 151
         return result
148 152
 
149
-##@brief Integer value validator callback
153
+# @brief Integer value validator callback
154
+
155
+
150 156
 def int_val(value):
151 157
     return int(value)
152 158
 
153
-##@brief Output file validator callback
159
+# @brief Output file validator callback
154 160
 # @return A file object (if filename is '-' return sys.stderr)
161
+
162
+
155 163
 def file_err_output(value):
156 164
     if not isinstance(value, str):
157 165
         raise ValidationError("A string was expected but got '%s' " % value)
@@ -159,7 +167,9 @@ def file_err_output(value):
159 167
         return None
160 168
     return value
161 169
 
162
-##@brief Boolean value validator callback
170
+# @brief Boolean value validator callback
171
+
172
+
163 173
 def boolean_val(value):
164 174
     if isinstance(value, bool):
165 175
         return value
@@ -171,49 +181,63 @@ def boolean_val(value):
171 181
         raise ValidationError("A boolean was expected but got '%s' " % value)
172 182
     return bool(value)
173 183
 
174
-##@brief Validate a directory path
184
+# @brief Validate a directory path
185
+
186
+
175 187
 def directory_val(value):
176 188
     res = Validator('strip')(value)
177 189
     if not os.path.isdir(res):
178
-        raise ValidationError("Following path don't exists or is not a directory : '%s'"%res)
190
+        raise ValidationError("Following path don't exists or is not a directory : '%s'" % res)
179 191
     return res
180 192
 
181
-##@brief Validate a loglevel value
193
+# @brief Validate a loglevel value
194
+
195
+
182 196
 def loglevel_val(value):
183 197
     valids = ['DEBUG', 'INFO', 'WARNING', 'SECURITY', 'ERROR', 'CRITICAL']
184 198
     if value.upper() not in valids:
185
-        raise ValidationError( \
199
+        raise ValidationError(
186 200
             "The value '%s' is not a valid loglevel" % value)
187 201
     return value.upper()
188 202
 
189
-##@brief Validate a path
203
+# @brief Validate a path
204
+
205
+
190 206
 def path_val(value):
191 207
     if value is None or not os.path.exists(value):
192
-        raise ValidationError( \
208
+        raise ValidationError(
193 209
             "path '%s' doesn't exists" % value)
194 210
     return value
195 211
 
196
-##@brief Validate None
212
+# @brief Validate None
213
+
214
+
197 215
 def none_val(value):
198 216
     if value is None:
199 217
         return None
200 218
     raise ValidationError("This settings cannot be set in configuration file")
201 219
 
202
-##@brief Validate a string
220
+# @brief Validate a string
221
+
222
+
203 223
 def str_val(value):
204 224
     try:
205 225
         return str(value)
206 226
     except Exception as exp:
207 227
         raise ValidationError("Can't to convert value to string: " + str(exp))
208 228
 
209
-##@brief Validate using a regex
229
+# @brief Validate using a regex
230
+
231
+
210 232
 def regex_val(value, pattern):
211 233
     if re.match(pattern, value) is None:
212 234
         raise ValidationError("The value '%s' is not validated by : \
213
-r\"%s\"" %(value, pattern))
235
+r\"%s\"" % (value, pattern))
214 236
     return value
215 237
 
216
-##@brief Validate a hostname (ipv4 or ipv6)
238
+# @brief Validate a hostname (ipv4 or ipv6)
239
+
240
+
217 241
 def host_val(value):
218 242
     if value == 'localhost':
219 243
         return value
@@ -235,6 +259,7 @@ def host_val(value):
235 259
         msg = "The value '%s' is not a valid host"
236 260
         raise ValidationError(msg % value)
237 261
 
262
+
238 263
 def custom_list_validator(value, validator_name, validator_kwargs=None):
239 264
     validator_kwargs = dict() if validator_kwargs is None else validator_kwargs
240 265
     validator = Validator(validator_name, **validator_kwargs)
@@ -246,8 +271,8 @@ def custom_list_validator(value, validator_name, validator_kwargs=None):
246 271
 #   Default validators registration
247 272
 #
248 273
 
249
-Validator.register_validator('custom_list', custom_list_validator, \
250
-    'A list validator that takes a "validator_name" as argument')
274
+Validator.register_validator('custom_list', custom_list_validator,
275
+                             'A list validator that takes a "validator_name" as argument')
251 276
 
252 277
 Validator.register_validator('dummy', lambda value: value, 'Validate anything')
253 278
 
@@ -261,11 +286,11 @@ Validator.register_validator('int', int_val, 'Integer value validator')
261 286
 
262 287
 Validator.register_validator('bool', boolean_val, 'Boolean value validator')
263 288
 
264
-Validator.register_validator('errfile', file_err_output,\
265
-    'Error output file validator (return stderr if filename is "-")')
289
+Validator.register_validator('errfile', file_err_output,
290
+                             'Error output file validator (return stderr if filename is "-")')
266 291
 
267
-Validator.register_validator('directory', directory_val, \
268
-    'Directory path validator')
292
+Validator.register_validator('directory', directory_val,
293
+                             'Directory path validator')
269 294
 
270 295
 Validator.register_validator('loglevel', loglevel_val, 'Loglevel validator')
271 296
 
@@ -273,48 +298,50 @@ Validator.register_validator('path', path_val, 'path validator')
273 298
 
274 299
 Validator.register_validator('host', host_val, 'host validator')
275 300
 
276
-Validator.register_validator('regex', regex_val, \
277
-    'RegEx name validator (take re as argument)')
301
+Validator.register_validator('regex', regex_val,
302
+                             'RegEx name validator (take re as argument)')
278 303
 
279
-Validator.create_list_validator('list', Validator('strip'), description=\
280
-    "Simple list validator. Validate a list of values separated by ','", \
281
-    separator=',')
304
+Validator.create_list_validator('list', Validator('strip'), description="Simple list validator. Validate a list of values separated by ','",
305
+                                separator=',')
282 306
 
283
-Validator.create_list_validator( \
284
-    'directory_list', \
285
-    Validator('directory'), \
286
-    description="Validator for a list of directory path separated with ','", \
307
+Validator.create_list_validator(
308
+    'directory_list',
309
+    Validator('directory'),
310
+    description="Validator for a list of directory path separated with ','",
287 311
     separator=',')
288 312
 
289
-Validator.create_write_list_validator( \
290
-    'write_list', \
291
-    Validator('directory'), \
313
+Validator.create_write_list_validator(
314
+    'write_list',
315
+    Validator('directory'),
292 316
     description="Validator for an array of values \
293 317
         which will be set in a string, separated by ','",
294 318
     separator=',')
295 319
 
296
-Validator.create_re_validator( \
297
-    r'^https?://[^\./]+.[^\./]+/?.*$', \
298
-    'http_url', \
320
+Validator.create_re_validator(
321
+    r'^https?://[^\./]+.[^\./]+/?.*$',
322
+    'http_url',
299 323
     'Url validator')
300 324
 
301
-##@brief Validator for Editorial model component
325
+# @brief Validator for Editorial model component
302 326
 #
303 327
 # Designed to validate a conf that indicate a class.field in an EM
304 328
 #@todo modified the hardcoded dyncode import (it's a warning)
329
+
330
+
305 331
 def emfield_val(value):
306
-    LodelContext.expose_modules(globals(), \
307
-        {'lodel.plugin.hooks': ['LodelHook']})
332
+    LodelContext.expose_modules(globals(),
333
+                                {'lodel.plugin.hooks': ['LodelHook']})
308 334
     spl = value.split('.')
309 335
     if len(spl) != 2:
310 336
         msg = "Expected a value in the form CLASSNAME.FIELDNAME but got : %s"
311 337
         raise SettingsValidationError(msg % value)
312 338
     value = tuple(spl)
313
-    #Late validation hook
339
+    # Late validation hook
340
+
314 341
     @LodelHook('lodel2_dyncode_bootstraped')
315 342
     def emfield_conf_check(hookname, caller, payload):
316
-        import leapi_dyncode as dyncode # <-- dirty & quick
317
-        classnames = { cls.__name__.lower(): cls for cls in dyncode.dynclasses}
343
+        import leapi_dyncode as dyncode  # <-- dirty & quick
344
+        classnames = {cls.__name__.lower(): cls for cls in dyncode.dynclasses}
318 345
         if value[0].lower() not in classnames:
319 346
             msg = "Following dynamic class do not exists in current EM : %s"
320 347
             raise SettingsValidationError(msg % value[0])
@@ -324,17 +351,20 @@ def emfield_val(value):
324 351
             raise SettingsValidationError(msg % value)
325 352
     return value
326 353
 
327
-##@brief Validator for plugin name & optionnaly type
354
+# @brief Validator for plugin name & optionnaly type
328 355
 #
329
-#Able to check that the value is a plugin and if it is of a specific type
356
+# Able to check that the value is a plugin and if it is of a specific type
357
+
358
+
330 359
 def plugin_validator(value, ptype=None):
331
-    LodelContext.expose_modules(globals(), { \
360
+    LodelContext.expose_modules(globals(), {
332 361
         'lodel.plugin.hooks': ['LodelHook']})
333 362
     value = copy.copy(value)
363
+
334 364
     @LodelHook('lodel2_dyncode_bootstraped')
335 365
     def plugin_type_checker(hookname, caller, payload):
336
-        LodelContext.expose_modules(globals(), { \
337
-            'lodel.plugin.plugins': ['Plugin'], \
366
+        LodelContext.expose_modules(globals(), {
367
+            'lodel.plugin.plugins': ['Plugin'],
338 368
             'lodel.plugin.exceptions': ['PluginError']})
339 369
         if value is None:
340 370
             return
@@ -352,21 +382,21 @@ named  '%s' that is a '%s' plugin"
352 382
     return value
353 383
 
354 384
 
355
-Validator.register_validator( \
356
-    'plugin', \
357
-    plugin_validator, \
385
+Validator.register_validator(
386
+    'plugin',
387
+    plugin_validator,
358 388
     'plugin name & type validator')
359 389
 
360
-Validator.register_validator( \
361
-    'emfield', \
362
-    emfield_val, \
390
+Validator.register_validator(
391
+    'emfield',
392
+    emfield_val,
363 393
     'EmField name validator')
364 394
 
365 395
 #
366 396
 #   Lodel 2 configuration specification
367 397
 #
368 398
 
369
-##@brief Append a piece of confspec
399
+# @brief Append a piece of confspec
370 400
 #@note orig is modified during the process
371 401
 #@param orig dict : the confspec to update
372 402
 #@param section str : section name
@@ -374,6 +404,8 @@ Validator.register_validator( \
374 404
 #@param validator Validator : the validator to use to check this configuration key's value
375 405
 #@param default
376 406
 #@return new confspec
407
+
408
+
377 409
 def confspec_append(orig, section, key, validator, default):
378 410
     if section not in orig:
379 411
         orig[section] = dict()
@@ -381,19 +413,19 @@ def confspec_append(orig, section, key, validator, default):
381 413
         orig[section][key] = (default, validator)
382 414
     return orig
383 415
 
384
-##@brief Global specifications for lodel2 settings
416
+# @brief Global specifications for lodel2 settings
385 417
 LODEL2_CONF_SPECS = {
386 418
     'lodel2': {
387 419
         'debug': (True, Validator('bool')),
388 420
         'sitename': ('noname', Validator('strip')),
389 421
         'runtest': (False, Validator('bool')),
390 422
     },
391
-    'lodel2.logging.*' : {
423
+    'lodel2.logging.*': {
392 424
         'level': ('ERROR', Validator('loglevel')),
393 425
         'context': (False, Validator('bool')),
394 426
         'filename': ("-", Validator('errfile', none_is_valid=False)),
395 427
         'backupcount': (5, Validator('int', none_is_valid=False)),
396
-        'maxbytes': (1024*10, Validator('int', none_is_valid=False)),
428
+        'maxbytes': (1024 * 10, Validator('int', none_is_valid=False)),
397 429
     },
398 430
     'lodel2.editorialmodel': {
399 431
         'emfile': ('em.pickle', Validator('strip')),

Loading…
Откажи
Сачувај