Browse Source

Adjustements for doxygen

prieto 7 years ago
parent
commit
aa2db00ccf

+ 25
- 25
lodel/auth/client.py View File

@@ -14,7 +14,7 @@ LodelContext.expose_modules(globals(), {
14 14
                               'ClientPermissionDenied', 'ClientAuthenticationError'],
15 15
     'lodel.leapi.query': ['LeGetQuery'], })
16 16
 
17
-# @brief Client metaclass designed to implements container accessor on
17
+## @brief Client metaclass designed to implements container accessor on
18 18
 # Client Class
19 19
 #
20 20
 #@todo Maybe we can delete this metaclass....
@@ -40,14 +40,14 @@ class ClientMetaclass(type):
40 40
     def __str__(self):
41 41
         return str(self._instance)
42 42
 
43
-# @brief Abstract singleton class designed to handle client informations
43
+## @brief Abstract singleton class designed to handle client informations
44 44
 #
45 45
 # This class is designed to handle client authentication and sessions
46 46
 
47 47
 
48 48
 class Client(object, metaclass=ClientMetaclass):
49 49
 
50
-    # @brief Singleton instance
50
+    ## @brief Singleton instance
51 51
     _instance = None
52 52
     # @brief List of dict that stores field ref for login and password
53 53
     #
@@ -63,11 +63,11 @@ class Client(object, metaclass=ClientMetaclass):
63 63
     # - password typle contains (LeObjectChild, FieldName)
64 64
     _infos_fields = None
65 65
 
66
-    # @brief Constant that stores the session key that stores authentication
66
+    ## @brief Constant that stores the session key that stores authentication
67 67
     # informations
68 68
     _AUTH_DATANAME = '__auth_user_infos'
69 69
 
70
-    # @brief Constructor
70
+    ## @brief Constructor
71 71
     #@param session_token mixed : Session token provided by client to interface
72 72
     def __init__(self, session_token=None):
73 73
         logger.debug(session_token)
@@ -81,13 +81,13 @@ class Client(object, metaclass=ClientMetaclass):
81 81
             del(old)
82 82
             logger.debug("Replacing old Client instance by a new one")
83 83
         else:
84
-            # first instanciation, fetching settings
84
+            ## first instanciation, fetching settings
85 85
             self.fetch_settings()
86 86
         # @brief Stores infos for authenticated users (None == anonymous)
87 87
         self.__user = None
88
-        # @brief Stores the session handler
88
+        ## @brief Stores the session handler
89 89
         Client._instance = self
90
-        # @brief Stores LodelSession instance
90
+        ## @brief Stores LodelSession instance
91 91
         self.__data = dict()
92 92
         if session_token is not None:
93 93
             self.__data = SessionHandler.restore(session_token)
@@ -98,14 +98,14 @@ class Client(object, metaclass=ClientMetaclass):
98 98
     def __del__(self):
99 99
         del(self.__session_token)
100 100
         del(self.__data)
101
-    # @brief Returns session
101
+    ## @brief Returns session
102 102
     #@ returns the dict which stores session
103 103
 
104 104
     @classmethod
105 105
     def data(cls):
106 106
         return cls._instance.__data
107 107
 
108
-    # @brief Returns the user's information contained in the session's data
108
+    ## @brief Returns the user's information contained in the session's data
109 109
     @classmethod
110 110
     def user(cls):
111 111
         if '__auth_user_infos' in cls._instance.__data:
@@ -113,18 +113,18 @@ class Client(object, metaclass=ClientMetaclass):
113 113
         else:
114 114
             return None
115 115
 
116
-    # @brief Returns the session's token
116
+    ## @brief Returns the session's token
117 117
     @classmethod
118 118
     def get_session_token(cls):
119 119
         return cls._instance.__session_token
120 120
 
121
-    # @brief Set the session's token
121
+    ## @brief Set the session's token
122 122
     #@param the value of the token
123 123
     @classmethod
124 124
     def set_session_token(cls, value):
125 125
         cls._instance.__session_token = value
126 126
 
127
-    # @brief Try to authenticate a user with a login and a password
127
+    ## @brief Try to authenticate a user with a login and a password
128 128
     #@param login str : provided login
129 129
     #@param password str : provided password (hash)
130 130
     #@warning brokes composed UID
@@ -160,7 +160,7 @@ class Client(object, metaclass=ClientMetaclass):
160 160
         if self.is_anonymous():
161 161
             self.authentication_failure()  # Security logging
162 162
 
163
-    # @brief Attempt to restore a session given a session token
163
+    ## @brief Attempt to restore a session given a session token
164 164
     #@param token mixed : a session token
165 165
     #@return Session data (a dict)
166 166
     #@throw ClientAuthenticationFailure if token is not valid or not
@@ -178,14 +178,14 @@ a session is already started !!!")
178 178
             logger.warning("Session restoring failed")
179 179
         return copy.copy(cls._instance.data)
180 180
 
181
-    # @brief Returns the current session token or None
181
+    ## @brief Returns the current session token or None
182 182
     #@return A session token or None
183 183
     @classmethod
184 184
     def session_token(cls):
185 185
         cls._assert_instance()
186 186
         return cls._instance.__session_token
187 187
 
188
-    # @brief Deletes current session
188
+    ## @brief Deletes current session
189 189
     @classmethod
190 190
     def destroy(cls):
191 191
         cls._assert_instance()
@@ -193,7 +193,7 @@ a session is already started !!!")
193 193
         cls._instance.__session_token = None
194 194
         cls._instance.__data = dict()
195 195
 
196
-    # @brief Deletes current client and saves its session
196
+    ## @brief Deletes current client and saves its session
197 197
     @classmethod
198 198
     def clean(cls):
199 199
         if cls._instance.__session_token is not None:
@@ -202,34 +202,34 @@ a session is already started !!!")
202 202
             del(Client._instance)
203 203
         Client._instance = None
204 204
 
205
-    # @brief Tests if a client is anonymous or logged in
205
+    ## @brief Tests if a client is anonymous or logged in
206 206
     #@return True if client is anonymous
207 207
     @classmethod
208 208
     def is_anonymous(cls):
209 209
         return Client._instance.user() is None
210 210
 
211
-    # @brief Method to be called on authentication failure
211
+    ## @brief Method to be called on authentication failure
212 212
     #@throw ClientAuthenticationFailure
213 213
     #@throw LodelFatalError if no Client child instance is found
214 214
     @classmethod
215 215
     def authentication_failure(cls):
216 216
         cls._generic_error(ClientAuthenticationFailure)
217 217
 
218
-    # @brief Method to be called on authentication error
218
+    ## @brief Method to be called on authentication error
219 219
     #@throw ClientAuthenticationError
220 220
     #@throw LodelFatalError if no Client child instance is found
221 221
     @classmethod
222 222
     def authentication_error(cls, msg="Unknow error"):
223 223
         cls._generic_error(ClientAuthenticationError, msg)
224 224
 
225
-    # @brief Method to be called on permission denied error
225
+    ## @brief Method to be called on permission denied error
226 226
     #@throw ClientPermissionDenied
227 227
     #@throw LodelFatalError if no Client child instance is found
228 228
     @classmethod
229 229
     def permission_denied_error(cls, msg=""):
230 230
         cls._generic_error(ClientPermissionDenied, msg)
231 231
 
232
-    # @brief Generic error method
232
+    ## @brief Generic error method
233 233
     #@see Client::authentication_failure() Client::authentication_error()
234 234
     # Client::permission_denied_error()
235 235
     #@throw LodelFatalError if no Client child instance is found
@@ -238,14 +238,14 @@ a session is already started !!!")
238 238
         cls._assert_instance()
239 239
         raise expt(Client._instance, msg)
240 240
 
241
-    # @brief Asserts that an instance of Client child class exists
241
+    ## @brief Asserts that an instance of Client child class exists
242 242
     #@throw LodelFataError if no instance of Client child class is found
243 243
     @classmethod
244 244
     def _assert_instance(cls):
245 245
         if Client._instance is None:
246 246
             raise LodelFatalError("No client instance found. Abording.")
247 247
 
248
-    # @brief Class method that fetches conf
248
+    ## @brief Class method that fetches conf
249 249
     #
250 250
     # This method populates Client._infos_fields . This attribute stores
251 251
     # informations on login and password location (LeApi object & field)
@@ -282,7 +282,7 @@ login EmClass '%s' and password EmClass '%s'. Abording..." % (
282 282
         cls._infos_fields.append(
283 283
             {'login': res_infos[0], 'password': res_infos[1]})
284 284
 
285
-    # @brief Sets a user as authenticated and starts a new session
285
+    ## @brief Sets a user as authenticated and starts a new session
286 286
     #@param leo LeObject child class : the LeObject the user is stored in
287 287
     #@param uid str : uniq id (in leo)
288 288
     #@return None

+ 41
- 41
lodel/editorial_model/components.py View File

@@ -17,7 +17,7 @@ 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
@@ -25,7 +25,7 @@ LodelContext.expose_modules(globals(), {
25 25
 
26 26
 class EmComponent(MlNamedObject):
27 27
 
28
-    # @brief Instanciate an EmComponent
28
+    ## @brief Instanciate an EmComponent
29 29
     # @param uid str : uniq identifier
30 30
     # @param display_name MlString|str|dict : component display_name
31 31
     # @param help_text MlString|str|dict : help_text
@@ -36,13 +36,13 @@ class EmComponent(MlNamedObject):
36 36
         self.group = group
37 37
         super().__init__(display_name, help_text)
38 38
 
39
-    # @brief Returns the display_name of the component if it is not None, its uid else
39
+    ## @brief Returns the display_name of the component if it is not None, its uid else
40 40
     def __str__(self):
41 41
         if self.display_name is None:
42 42
             return str(self.uid)
43 43
         return str(self.display_name)
44 44
 
45
-    # @brief Returns a hash code for the component
45
+    ## @brief Returns a hash code for the component
46 46
     def d_hash(self):
47 47
         m = hashlib.md5()
48 48
         for data in (
@@ -55,11 +55,11 @@ class EmComponent(MlNamedObject):
55 55
         return int.from_bytes(m.digest(), byteorder='big')
56 56
 
57 57
 
58
-# @brief Handles editorial model objects classes
58
+## @brief Handles editorial model objects classes
59 59
 #@ingroup lodel2_em
60 60
 class EmClass(EmComponent):
61 61
 
62
-    # @brief Instanciates a new EmClass
62
+    ## @brief Instanciates a new EmClass
63 63
     #@param uid str : uniq identifier
64 64
     #@param display_name MlString|str|dict : component display_name
65 65
     #@param abstract bool : set the class as asbtract if True
@@ -94,7 +94,7 @@ class EmClass(EmComponent):
94 94
         else:
95 95
             parents = list()
96 96
         self.parents = parents
97
-        # @brief Stores EmFields instances indexed by field uid
97
+        ## @brief Stores EmFields instances indexed by field uid
98 98
         self.__fields = dict()
99 99
 
100 100
         self.group = group
@@ -117,7 +117,7 @@ class EmClass(EmComponent):
117 117
                 internal=True,
118 118
                 group=group)
119 119
 
120
-    # @brief Property that represents a dict of all fields 
120
+    ## @brief Property that represents a dict of all fields
121 121
     # (the EmField objects defined in this class and all their parents)
122 122
     # @todo use Settings.editorialmodel.groups to determine which fields should be returned
123 123
     @property
@@ -128,12 +128,12 @@ class EmClass(EmComponent):
128 128
         res.update(self.__fields)
129 129
         return res
130 130
 
131
-    # @brief RO access to datasource attribute
131
+    ## @brief RO access to datasource attribute
132 132
     @property
133 133
     def datasource(self):
134 134
         return self.__datasource
135 135
 
136
-    # @brief Returns the list of all dependencies
136
+    ## @brief Returns the list of all dependencies
137 137
     #
138 138
     # Recursive parents listing
139 139
     @property
@@ -146,7 +146,7 @@ class EmClass(EmComponent):
146 146
             res |= parent.parents_recc
147 147
         return res
148 148
 
149
-    # @brief EmField getter
149
+    ## @brief EmField getter
150 150
     # @param uid None | str : If None returns an iterator on EmField instances else return an EmField instance
151 151
     # @param no_parents bool : If True returns only fields defined is this class and not the one defined in parents classes
152 152
     # @return A list on EmFields instances (if uid is None) else return an EmField instance
@@ -158,7 +158,7 @@ class EmClass(EmComponent):
158 158
         except KeyError:
159 159
             raise EditorialModelError("No such EmField '%s'" % uid)
160 160
 
161
-    # @brief Keeps in __fields only fields contained in active groups
161
+    ## @brief Keeps in __fields only fields contained in active groups
162 162
     def _set_active_fields(self, active_groups):
163 163
         if not Settings.editorialmodel.editormode:
164 164
             active_fields = []
@@ -168,7 +168,7 @@ class EmClass(EmComponent):
168 168
             self.__fields = {fname: fdh for fname, fdh in self.__fields.items()
169 169
                              if fdh in active_fields}
170 170
 
171
-    # @brief Adds a field to the EmClass
171
+    ## @brief Adds a field to the EmClass
172 172
     # @param emfield EmField : an EmField instance
173 173
     # @warning do not add an EmField already in another class !
174 174
     # @throw EditorialModelException if an EmField with same uid already in this EmClass (overwriting allowed from parents)
@@ -187,7 +187,7 @@ class EmClass(EmComponent):
187 187
         self.__fields[emfield.uid] = emfield
188 188
         return emfield
189 189
 
190
-    # @brief Creates a new EmField and adds it to the EmClass
190
+    ## @brief Creates a new EmField and adds it to the EmClass
191 191
     # @param data_handler str : A DataHandler name
192 192
     # @param uid str : the EmField uniq id
193 193
     # @param **field_kwargs :  EmField constructor parameters ( see @ref EmField.__init__() )
@@ -220,11 +220,11 @@ class EmClass(EmComponent):
220 220
         return "<class %s EmClass uid=%s>" % (abstract, repr(self.uid))
221 221
 
222 222
 
223
-# @brief Handles editorial model classes fields
223
+## @brief Handles editorial model classes fields
224 224
 #@ingroup lodel2_em
225 225
 class EmField(EmComponent):
226 226
 
227
-    # @brief Instanciates a new EmField
227
+    ## @brief Instanciates a new EmField
228 228
     # @param uid str : uniq identifier
229 229
     # @param display_name MlString|str|dict : field display_name
230 230
     # @param data_handler str : A DataHandler name
@@ -234,15 +234,15 @@ class EmField(EmComponent):
234 234
     def __init__(self, uid, data_handler, em_class=None, display_name=None, help_text=None, group=None, **handler_kwargs):
235 235
         from lodel.leapi.datahandlers.base_classes import DataHandler
236 236
         super().__init__(uid, display_name, help_text, group)
237
-        # @brief The data handler name
237
+        ## @brief The data handler name
238 238
         self.data_handler_name = data_handler
239
-        # @brief The data handler class
239
+        ## @brief The data handler class
240 240
         self.data_handler_cls = DataHandler.from_name(data_handler)
241
-        # @brief The data handler instance associated with this EmField
241
+        ## @brief The data handler instance associated with this EmField
242 242
         self.data_handler_instance = self.data_handler_cls(**handler_kwargs)
243
-        # @brief Stores data handler instanciation options
243
+        ## @brief Stores data handler instanciation options
244 244
         self.data_handler_options = handler_kwargs
245
-        # @brief Stores the emclass that contains this field (set by EmClass.add_field() method)
245
+        ## @brief Stores the emclass that contains this field (set by EmClass.add_field() method)
246 246
         self._emclass = em_class
247 247
         if self._emclass is None:
248 248
             warnings.warn("No EmClass for field %s" % uid)
@@ -251,11 +251,11 @@ class EmField(EmComponent):
251 251
         else:
252 252
             group.add_components([self])
253 253
 
254
-    # @brief Returns data_handler_name attribute
254
+    ## @brief Returns data_handler_name attribute
255 255
     def get_data_handler_name(self):
256 256
         return copy.copy(self.data_handler_name)
257 257
 
258
-    # @brief Returns data_handler_cls attribute
258
+    ## @brief Returns data_handler_cls attribute
259 259
     def get_data_handler_cls(self):
260 260
         return copy.copy(self.data_handler_cls)
261 261
 
@@ -274,13 +274,13 @@ class EmField(EmComponent):
274 274
                 'utf-8')
275 275
         ).digest(), byteorder='big')
276 276
 
277
-# @brief Handles functionnal group of EmComponents
277
+## @brief Handles functionnal group of EmComponents
278 278
 #@ingroup lodel2_em
279 279
 
280 280
 
281 281
 class EmGroup(MlNamedObject):
282 282
 
283
-    # @brief Creates a new EmGroup
283
+    ## @brief Creates a new EmGroup
284 284
     # @note you should NEVER call the constructor yourself. Use Model.add_group instead
285 285
     # @param uid str : Uniq identifier
286 286
     # @param depends list : A list of EmGroup dependencies
@@ -288,11 +288,11 @@ class EmGroup(MlNamedObject):
288 288
     # @param help_text MlString|str :
289 289
     def __init__(self, uid, depends=None, display_name=None, help_text=None):
290 290
         self.uid = uid
291
-        # @brief Stores the list of groups that depends on this EmGroup indexed by uid
291
+        ## @brief Stores the list of groups that depends on this EmGroup indexed by uid
292 292
         self.required_by = dict()
293
-        # @brief Stores the list of dependencies (EmGroup) indexed by uid
293
+        ## @brief Stores the list of dependencies (EmGroup) indexed by uid
294 294
         self.require = dict()
295
-        # @brief Stores the list of EmComponent instances contained in this group
295
+        ## @brief Stores the list of EmComponent instances contained in this group
296 296
         self.__components = set()
297 297
         super().__init__(display_name, help_text)
298 298
 
@@ -302,7 +302,7 @@ class EmGroup(MlNamedObject):
302 302
                     raise ValueError("EmGroup expected in depends argument but %s found" % grp)
303 303
                 self.add_dependency(grp)
304 304
 
305
-    # @brief Returns EmGroup dependencies
305
+    ## @brief Returns EmGroup dependencies
306 306
     # @param recursive bool : if True returns all dependencies and their own dependencies
307 307
     # @return a dict of EmGroup identified by uid
308 308
     def dependencies(self, recursive=False):
@@ -318,7 +318,7 @@ class EmGroup(MlNamedObject):
318 318
                     res[new_dep.uid] = new_dep
319 319
         return res
320 320
 
321
-    # @brief Returns EmGroup applicants
321
+    ## @brief Returns EmGroup applicants
322 322
     # @param recursive bool : if True returns all dependencies and their dependencies
323 323
     # @returns a dict of EmGroup identified by uid
324 324
     def applicants(self, recursive=False):
@@ -334,12 +334,12 @@ class EmGroup(MlNamedObject):
334 334
                     res[new_app.uid] = new_app
335 335
         return res
336 336
 
337
-    # @brief Returns EmGroup components
337
+    ## @brief Returns EmGroup components
338 338
     # @returns a copy of the set of components
339 339
     def components(self):
340 340
         return (self.__components).copy()
341 341
 
342
-    # @brief Returns EmGroup display_name
342
+    ## @brief Returns EmGroup display_name
343 343
     #  @param lang str | None : If None returns default lang translation
344 344
     #  @returns None if display_name is None, a str for display_name else
345 345
     def get_display_name(self, lang=None):
@@ -348,7 +348,7 @@ class EmGroup(MlNamedObject):
348 348
             return None
349 349
         return name.get(lang)
350 350
 
351
-    # @brief Returns EmGroup help_text
351
+    ## @brief Returns EmGroup help_text
352 352
     #  @param lang str | None : If None returns default lang translation
353 353
     #  @returns None if display_name is None, a str for display_name else
354 354
     def get_help_text(self, lang=None):
@@ -357,7 +357,7 @@ class EmGroup(MlNamedObject):
357 357
             return None
358 358
         return help.get(lang)
359 359
 
360
-    # @brief Adds components in a group
360
+    ## @brief Adds components in a group
361 361
     # @param components list : EmComponent instances list
362 362
     def add_components(self, components):
363 363
         assert_edit()
@@ -372,7 +372,7 @@ class EmGroup(MlNamedObject):
372 372
                     "Expecting components to be a list of EmComponent, but %s found in the list" % type(component))
373 373
         self.__components |= set(components)
374 374
 
375
-    # @brief Add a dependency
375
+    ## @brief Add a dependency
376 376
     # @param em_group EmGroup|iterable : an EmGroup instance or list of instances
377 377
     def add_dependency(self, grp):
378 378
         assert_edit()
@@ -390,7 +390,7 @@ class EmGroup(MlNamedObject):
390 390
         self.require[grp.uid] = grp
391 391
         grp.required_by[self.uid] = self
392 392
 
393
-    # @brief Add a applicant
393
+    ## @brief Add a applicant
394 394
     # @param em_group EmGroup|iterable : an EmGroup instance or list of instance
395 395
     # Useless ???
396 396
     def add_applicant(self, grp):
@@ -409,17 +409,17 @@ class EmGroup(MlNamedObject):
409 409
         self.required_by[grp.uid] = grp
410 410
         grp.require[self.uid] = self
411 411
 
412
-    # @brief Search for circular dependency
412
+    ## @brief Search for circular dependency
413 413
     # @return True if circular dep found else False
414 414
     def __circular_dependency(self, new_dep):
415 415
         return self.uid in new_dep.dependencies(True)
416 416
 
417
-    # @brief Search for circular applicant
417
+    ## @brief Search for circular applicant
418 418
     # @return True if circular app found else False
419 419
     def __circular_applicant(self, new_app):
420 420
         return self.uid in new_app.applicants(True)
421 421
 
422
-    # @brief Fancy string representation of an EmGroup
422
+    ## @brief Fancy string representation of an EmGroup
423 423
     # @return a string
424 424
     def __str__(self):
425 425
         if self.display_name is None:
@@ -427,7 +427,7 @@ class EmGroup(MlNamedObject):
427 427
         else:
428 428
             return self.display_name.get()
429 429
 
430
-    # @brief Computes a d-hash code for the EmGroup
430
+    ## @brief Computes a d-hash code for the EmGroup
431 431
     # @return a string
432 432
     def d_hash(self):
433 433
 
@@ -447,7 +447,7 @@ class EmGroup(MlNamedObject):
447 447
             byteorder='big'
448 448
         )
449 449
 
450
-    # @brief Complete string representation of an EmGroup
450
+    ## @brief Complete string representation of an EmGroup
451 451
     # @return a string
452 452
     def __repr__(self):
453 453
         return "<class EmGroup '%s' depends : [%s]>" % (self.uid, ', '.join([duid for duid in self.dependencies(False)]))

+ 26
- 26
lodel/editorial_model/model.py View File

@@ -16,19 +16,19 @@ LodelContext.expose_modules(globals(), {
16 16
     'lodel.editorial_model.components': ['EmClass', 'EmField', 'EmGroup']})
17 17
 
18 18
 
19
-# @brief Describe an editorial model
19
+## @brief Describe an editorial model
20 20
 #@ingroup lodel2_em
21 21
 class EditorialModel(MlNamedObject):
22 22
 
23
-    # @brief Create a new editorial model
23
+    ## @brief Create a new editorial model
24 24
     # @param name MlString|str|dict : the editorial model name
25 25
     # @param description MlString|str|dict : the editorial model description
26 26
     def __init__(self, name, description=None, display_name=None, help_text=None):
27 27
         self.name = MlString(name)
28 28
         self.description = MlString(description)
29
-        # @brief Stores all groups indexed by id
29
+        ## @brief Stores all groups indexed by id
30 30
         self.__groups = dict()
31
-        # @brief Stores all classes indexed by id
31
+        ## @brief Stores all classes indexed by id
32 32
         self.__classes = dict()
33 33
         #  @brief Stores all activated groups indexed by id
34 34
         self.__active_groups = dict()
@@ -41,7 +41,7 @@ class EditorialModel(MlNamedObject):
41 41
             help_text = description
42 42
         super().__init__(display_name, help_text)
43 43
 
44
-    # @brief EmClass uids accessor
44
+    ## @brief EmClass uids accessor
45 45
     #@return a copy of the dict containing all emclasses of the model if uid is None
46 46
     # else a copy the class with uid uid
47 47
     def all_classes(self, uid=None):
@@ -53,7 +53,7 @@ class EditorialModel(MlNamedObject):
53 53
             except KeyError:
54 54
                 raise EditorialModelException("EmClass not found : '%s'" % uid)
55 55
 
56
-    # @brief EmClass uids accessor
56
+    ## @brief EmClass uids accessor
57 57
     #@return the dict containing all emclasses of the model if uid is None
58 58
     # else the class with uid uid
59 59
     def all_classes_ref(self, uid=None):
@@ -65,12 +65,12 @@ class EditorialModel(MlNamedObject):
65 65
             except KeyError:
66 66
                 raise EditorialModelException("EmGroup not found : '%s'" % uid)
67 67
 
68
-    # @brief active EmClass uids accessor
68
+    ## @brief active EmClass uids accessor
69 69
     #@return a list of active class uids
70 70
     def active_classes_uids(self):
71 71
         return list(self.__active_classes.keys())
72 72
 
73
-    # @brief EmGroups accessor
73
+    ## @brief EmGroups accessor
74 74
     #@return a copy of the dict of the model's group if uid is None
75 75
     # else a copy of the group with uniq id uid
76 76
     def all_groups(self, uid=None):
@@ -82,7 +82,7 @@ class EditorialModel(MlNamedObject):
82 82
             except KeyError:
83 83
                 raise EditorialModelException("EmGroup not found : '%s'" % uid)
84 84
 
85
-    # @brief EmGroups accessor
85
+    ## @brief EmGroups accessor
86 86
     #@return the dict of the model's group if uid is None
87 87
     # else the group with uniq id uid
88 88
     def all_groups_ref(self, uid=None):
@@ -94,12 +94,12 @@ class EditorialModel(MlNamedObject):
94 94
             except KeyError:
95 95
                 raise EditorialModelException("EmGroup not found : '%s'" % uid)
96 96
 
97
-    # @brief active EmClass uids accessor
97
+    ## @brief active EmClass uids accessor
98 98
     #@return a list of active group uids
99 99
     def active_groups_uids(self):
100 100
         return list(self.__active_groups.keys())
101 101
 
102
-    # @brief EmClass accessor
102
+    ## @brief EmClass accessor
103 103
     #@param uid None | str : give this argument to get a specific EmClass
104 104
     #@return if uid is given returns an EmClass else returns an EmClass
105 105
     # iterator
@@ -112,7 +112,7 @@ class EditorialModel(MlNamedObject):
112 112
         except KeyError:
113 113
             raise EditorialModelException("EmClass not found : '%s'" % uid)
114 114
 
115
-    # @brief EmClass child list accessor
115
+    ## @brief EmClass child list accessor
116 116
     #@param uid str : the EmClass uid
117 117
     #@return a set of EmClass
118 118
     def get_class_childs(self, uid):
@@ -123,7 +123,7 @@ class EditorialModel(MlNamedObject):
123 123
                 res.append(cls)
124 124
         return set(res)
125 125
 
126
-    # @brief EmGroup getter
126
+    ## @brief EmGroup getter
127 127
     # @param uid None | str : give this argument to get a specific EmGroup
128 128
     # @return if uid is given returns an EmGroup else returns an EmGroup iterator
129 129
     def groups(self, uid=None):
@@ -133,12 +133,12 @@ class EditorialModel(MlNamedObject):
133 133
         except KeyError:
134 134
             raise EditorialModelException("EmGroup not found : '%s'" % uid)
135 135
 
136
-    # @brief Private getter for __groups or __classes
136
+    ## @brief Private getter for __groups or __classes
137 137
     # @see classes() groups()
138 138
     def __elt_getter(self, elts, uid):
139 139
         return list(elts.values()) if uid is None else elts[uid]
140 140
 
141
-    # @brief Update the EditorialModel.__active_groups and
141
+    ## @brief Update the EditorialModel.__active_groups and
142 142
     # EditorialModel.__active_classes attibutes
143 143
     def __set_actives(self):
144 144
         if Settings.editorialmodel.editormode:
@@ -165,7 +165,7 @@ class EditorialModel(MlNamedObject):
165 165
             for clsname, acls in self.__active_classes.items():
166 166
                 acls._set_active_fields(self.__active_groups)
167 167
 
168
-    # @brief EmField getter
168
+    ## @brief EmField getter
169 169
     # @param uid str : An EmField uid represented by "CLASSUID.FIELDUID"
170 170
     # @return Fals or an EmField instance
171 171
     #
@@ -186,7 +186,7 @@ class EditorialModel(MlNamedObject):
186 186
             pass
187 187
         return False
188 188
 
189
-    # @brief Add a class to the editorial model
189
+    ## @brief Add a class to the editorial model
190 190
     # @param emclass EmClass : the EmClass instance to add
191 191
     # @return emclass
192 192
     def add_class(self, emclass):
@@ -198,7 +198,7 @@ class EditorialModel(MlNamedObject):
198 198
         self.__classes[emclass.uid] = emclass
199 199
         return emclass
200 200
 
201
-    # @brief Add a group to the editorial model
201
+    ## @brief Add a group to the editorial model
202 202
     # @param emgroup EmGroup : the EmGroup instance to add
203 203
     # @return emgroup
204 204
     def add_group(self, emgroup):
@@ -210,7 +210,7 @@ class EditorialModel(MlNamedObject):
210 210
         self.__groups[emgroup.uid] = emgroup
211 211
         return emgroup
212 212
 
213
-    # @brief Add a new EmClass to the editorial model
213
+    ## @brief Add a new EmClass to the editorial model
214 214
     #@param uid str : EmClass uid
215 215
     #@param **kwargs : EmClass constructor options (
216 216
     # see @ref lodel.editorial_model.component.EmClass.__init__() )
@@ -218,7 +218,7 @@ class EditorialModel(MlNamedObject):
218 218
         assert_edit()
219 219
         return self.add_class(EmClass(uid, **kwargs))
220 220
 
221
-    # @brief Add a new EmGroup to the editorial model
221
+    ## @brief Add a new EmGroup to the editorial model
222 222
     #@param uid str : EmGroup uid
223 223
     #@param *kwargs : EmGroup constructor keywords arguments (
224 224
     # see @ref lodel.editorial_model.component.EmGroup.__init__() )
@@ -226,7 +226,7 @@ class EditorialModel(MlNamedObject):
226 226
         assert_edit()
227 227
         return self.add_group(EmGroup(uid, **kwargs))
228 228
 
229
-    # @brief Save a model
229
+    ## @brief Save a model
230 230
     # @param translator module : The translator module to use
231 231
     # @param **translator_args
232 232
     def save(self, translator, **translator_kwargs):
@@ -235,14 +235,14 @@ class EditorialModel(MlNamedObject):
235 235
             translator = self.translator_from_name(translator)
236 236
         return translator.save(self, **translator_kwargs)
237 237
 
238
-    # @brief Raise an error if lodel is not in EM edition mode
238
+    ## @brief Raise an error if lodel is not in EM edition mode
239 239
     @staticmethod
240 240
     def raise_if_ro():
241 241
         if not Settings.editorialmodel.editormode:
242 242
             raise EditorialModelError(
243 243
                 "Lodel in not in EM editor mode. The EM is in read only state")
244 244
 
245
-    # @brief Load a model
245
+    ## @brief Load a model
246 246
     # @param translator module : The translator module to use
247 247
     # @param **translator_args
248 248
     @classmethod
@@ -253,7 +253,7 @@ class EditorialModel(MlNamedObject):
253 253
         res.__set_actives()
254 254
         return res
255 255
 
256
-    # @brief Return a translator module given a translator name
256
+    ## @brief Return a translator module given a translator name
257 257
     # @param translator_name str : The translator name
258 258
     # @return the translator python module
259 259
     # @throw NameError if the translator does not exists
@@ -266,7 +266,7 @@ class EditorialModel(MlNamedObject):
266 266
             raise NameError("No translator named %s")
267 267
         return mod
268 268
 
269
-    # @brief Lodel hash
269
+    ## @brief Lodel hash
270 270
     def d_hash(self):
271 271
         payload = "%s%s" % (
272 272
             self.name,
@@ -283,7 +283,7 @@ class EditorialModel(MlNamedObject):
283 283
             byteorder='big'
284 284
         )
285 285
 
286
-    # @brief Returns a list of all datahandlers
286
+    ## @brief Returns a list of all datahandlers
287 287
     # @return a list of all datahandlers
288 288
     @staticmethod
289 289
     def list_datahandlers():

+ 7
- 7
lodel/leapi/lefactory.py View File

@@ -12,7 +12,7 @@ LodelContext.expose_modules(globals(), {
12 12
     'lodel.leapi.datahandlers.base_classes': ['DataHandler'],
13 13
     'lodel.logger': 'logger'})
14 14
 
15
-# @brief Generates python module code from a given model
15
+## @brief Generates python module code from a given model
16 16
 # @param model lodel.editorial_model.model.EditorialModel
17 17
 
18 18
 
@@ -52,7 +52,7 @@ dynclasses_dict = {class_dict}
52 52
     )
53 53
     return res_code
54 54
 
55
-# @brief Returns the content of lodel.leapi.lefactory_common
55
+## @brief Returns the content of lodel.leapi.lefactory_common
56 56
 #
57 57
 # @return a string
58 58
 
@@ -68,7 +68,7 @@ def common_code():
68 68
     return res
69 69
 
70 70
 
71
-# @brief return A list of EmClass sorted by dependencies
71
+## @brief return A list of EmClass sorted by dependencies
72 72
 #
73 73
 # The first elts in the list depend on nothing, etc.
74 74
 # @param a list of Emclass instances to be sorted
@@ -79,7 +79,7 @@ def emclass_sorted_by_deps(emclass_list):
79 79
     ret = sorted(emclass_list, key=functools.cmp_to_key(emclass_deps_cmp))
80 80
     return ret
81 81
 
82
-# @brief Returns a list of EmClass instances that will be represented as LeObject child classes
82
+## @brief Returns a list of EmClass instances that will be represented as LeObject child classes
83 83
 # @param model : an EditorialModel instance
84 84
 # @return a list of EmClass instances
85 85
 
@@ -87,7 +87,7 @@ def emclass_sorted_by_deps(emclass_list):
87 87
 def get_classes(model):
88 88
     return [cls for cls in emclass_sorted_by_deps(model.classes()) if not cls.pure_abstract]
89 89
 
90
-# @brief Given an EmField returns the data_handler constructor suitable for dynamic code
90
+## @brief Given an EmField returns the data_handler constructor suitable for dynamic code
91 91
 # @param a EmField instance
92 92
 # @return a string
93 93
 
@@ -109,7 +109,7 @@ def data_handler_constructor(emfield):
109 109
         handler_instr=get_handler_class_instr,
110 110
         options=', '.join(options))
111 111
 
112
-# @brief Return a python repr of option values
112
+## @brief Return a python repr of option values
113 113
 # @param A value of any type which represents option
114 114
 # @return a string
115 115
 
@@ -131,7 +131,7 @@ def forge_optval(optval):
131 131
 
132 132
     return repr(optval)
133 133
 
134
-# @brief Generate dyncode from an EmClass
134
+## @brief Generate dyncode from an EmClass
135 135
 # @param model EditorialModel :
136 136
 # @return a tuple with emclass python code, a set containing modules name to import, and a list of python instruction to bootstrap dynamic code, in this order
137 137
 

+ 67
- 64
lodel/leapi/query.py View File

@@ -18,12 +18,12 @@ LodelContext.expose_modules(globals(), {
18 18
 
19 19
 class LeQuery(object):
20 20
 
21
-    # @brief Hookname prefix
21
+    ## @brief Hookname prefix
22 22
     _hook_prefix = None
23
-    # @brief arguments for the LeObject.check_data_value()
23
+    ## @brief arguments for the LeObject.check_data_value()
24 24
     _data_check_args = {'complete': False, 'allow_internal': False}
25 25
 
26
-    # @brief Abstract constructor
26
+    ## @brief Abstract constructor
27 27
     # @param target_class LeObject : class of object the query is about
28 28
     def __init__(self, target_class):
29 29
         from .leobject import LeObject
@@ -37,7 +37,7 @@ class LeQuery(object):
37 37
         self._ro_datasource = target_class._ro_datasource
38 38
         self._rw_datasource = target_class._rw_datasource
39 39
 
40
-    # @brief Executes a query and returns the result
40
+    ## @brief Executes a query and returns the result
41 41
     #@param **data
42 42
     #@return the query result
43 43
     #@see LeQuery._query()
@@ -59,7 +59,7 @@ class LeQuery(object):
59 59
                                   ret)
60 60
         return ret
61 61
 
62
-    # @brief Child classes implement this method to execute the query
62
+    ## @brief Child classes implement this method to execute the query
63 63
     #@param **data
64 64
     #@return query result
65 65
     def _query(self, **data):
@@ -75,11 +75,11 @@ class LeQuery(object):
75 75
             classname=self.__class__.__name__,
76 76
             target_class=self._target_class)
77 77
 
78
-# @brief Abstract class handling query with filters
78
+## @brief Abstract class handling query with filters
79 79
 
80 80
 
81 81
 class LeFilteredQuery(LeQuery):
82
-    # @brief The available operators used in query definitions
82
+    ## @brief The available operators used in query definitions
83 83
     _query_operators = [
84 84
         ' = ',
85 85
         ' <= ',
@@ -92,19 +92,19 @@ class LeFilteredQuery(LeQuery):
92 92
         ' like ',
93 93
         ' not like ']
94 94
 
95
-    # @brief Regular expression to process filters
95
+    ## @brief Regular expression to process filters
96 96
     _query_re = None
97 97
 
98
-    # @brief Abtract constructor for queries with filter
98
+    ## @brief Abtract constructor for queries with filter
99 99
     #@param target_class LeObject : class of object the query is about
100 100
     #@param query_filters list : with a tuple (only one filter) or a list of
101 101
     # tuple or a dict: {OP,list(filters)} with OP = 'OR' or 'AND for tuple
102 102
     # (FIELD,OPERATOR,VALUE)
103 103
     def __init__(self, target_class, query_filters=None):
104 104
         super().__init__(target_class)
105
-        # @brief The query filter tuple(std_filter, relational_filters)
105
+        ## @brief The query filter tuple(std_filter, relational_filters)
106 106
         self._query_filter = None
107
-        # @brief Stores potential subqueries (used when a query implies
107
+        ## @brief Stores potential subqueries (used when a query implies
108 108
         # more than one datasource.
109 109
         #
110 110
         # Subqueries are tuple(target_class_ref_field, LeGetQuery)
@@ -112,7 +112,7 @@ class LeFilteredQuery(LeQuery):
112 112
         query_filters = [] if query_filters is None else query_filters
113 113
         self.set_query_filter(query_filters)
114 114
 
115
-    # @brief Abstract FilteredQuery execution method
115
+    ## @brief Abstract FilteredQuery execution method
116 116
     #
117 117
     # This method takes care to execute subqueries before calling super execute
118 118
     def execute(self, data=None):
@@ -138,7 +138,7 @@ class LeFilteredQuery(LeQuery):
138 138
         self._query_filter = orig_filters
139 139
         return res
140 140
 
141
-    # @brief Add filter(s) to the query
141
+    ## @brief Add filter(s) to the query
142 142
     #
143 143
     # This method is also able to slice query if different datasources are
144 144
     # implied in the request
@@ -149,27 +149,27 @@ class LeFilteredQuery(LeQuery):
149 149
     def set_query_filter(self, query_filter):
150 150
         if isinstance(query_filter, str):
151 151
             query_filter = [query_filter]
152
-        # Query filter prepration
152
+        # Query filter preparation
153 153
         filters_orig, rel_filters = self._prepare_filters(query_filter)
154
-        # Here we now that each relational filter concern only one datasource
154
+        # Here we know that each relational filter concerns only one datasource
155 155
         # thank's to _prepare_relational_fields
156 156
 
157 157
         # Multiple datasources detection
158 158
         self_ds_name = self._target_class._datasource_name
159
-        result_rel_filters = list()  # The filters that will stay in the query
159
+        result_rel_filters = list()  # The filters that will remain in the query
160 160
         other_ds_filters = dict()
161 161
         for rfilter in rel_filters:
162 162
             (rfield, ref_dict), op, value = rfilter
163 163
             # rfield : the field in self._target_class
164
-            tmp_rel_filter = dict()  # designed to stores rel_field of same DS
164
+            tmp_rel_filter = dict()  # designed to store rel_field of same DS
165 165
             # First step : simplification
166 166
             # Trying to delete relational filters done on referenced class uid
167 167
             for tclass, tfield in copy.copy(ref_dict).items():
168
-                # tclass : reference target class
168
+                # tclass : referenced target class
169 169
                 # tfield : referenced field from target class
170 170
                 #
171 171
                 #   !!!WARNING!!!
172
-                # The line below brake multi UID support
172
+                # The line below breaks multi UID support
173 173
                 #
174 174
                 if tfield == tclass.uid_fieldname()[0]:
175 175
                     # This relational filter can be simplified as
@@ -179,17 +179,17 @@ class LeFilteredQuery(LeQuery):
179 179
                     del(ref_dict[tclass])
180 180
             if len(ref_dict) == 0:
181 181
                 continue
182
-            # Determine what to do with other relational filters given
183
-            # referenced class datasource
184
-            # Remember : each class in a relational filter has the same
182
+            # Determines what to do with the other relational filters according
183
+            # to the referenced class datasource
184
+            # Remember : all classes in a relational filter have the same
185 185
             # datasource
186 186
             tclass = list(ref_dict.keys())[0]
187 187
             cur_ds = tclass._datasource_name
188 188
             if cur_ds == self_ds_name:
189
-                # Same datasource, the filter stay is self query
189
+                # Same datasource, the filter stays in this query
190 190
                 result_rel_filters.append(((rfield, ref_dict), op, value))
191 191
             else:
192
-                # Different datasource, we will have to create a subquery
192
+                # Different datasources, we will have to create a subquery
193 193
                 if cur_ds not in other_ds_filters:
194 194
                     other_ds_filters[cur_ds] = list()
195 195
                 other_ds_filters[cur_ds].append(
@@ -243,7 +243,7 @@ class LeFilteredQuery(LeQuery):
243 243
         res += '>'
244 244
         return res
245 245
 
246
-    # @brief Prepare filters for datasource
246
+    ## @brief Prepares filters for datasource
247 247
     #
248 248
     # A filter can be a string or a tuple with len = 3.
249 249
     #
@@ -251,7 +251,7 @@ class LeFilteredQuery(LeQuery):
251 251
     #
252 252
     #@par Simple filters
253 253
     #
254
-    # Those filters concerns fields that represent object values (a title,
254
+    # Those filters concern fields that represent object values (a title,
255 255
     # the content, etc.) They are composed of three elements : FIELDNAME OP
256 256
     # VALUE . Where :
257 257
     #- FIELDNAME is the name of the field
@@ -261,12 +261,12 @@ class LeFilteredQuery(LeQuery):
261 261
     #
262 262
     #@par Relational filters
263 263
     #
264
-    # Those filters concerns on reference fields (see the corresponding
264
+    # Those filters concern on reference fields (see the corresponding
265 265
     # abstract datahandler @ref lodel.leapi.datahandlers.base_classes.Reference)
266 266
     # The filter as quite the same composition than simple filters :
267 267
     # FIELDNAME[.REF_FIELD] OP VALUE . Where :
268 268
     #- FIELDNAME is the name of the reference field
269
-    #- REF_FIELD is an optionnal addon to the base field. It indicate on wich
269
+    #- REF_FIELD is an optionnal addon to the base field. It indicates on which
270 270
     # field of the referenced object the comparison as to be done. If no
271 271
     # REF_FIELD is indicated the comparison will be done on identifier.
272 272
     #
@@ -274,7 +274,7 @@ class LeFilteredQuery(LeQuery):
274 274
     #@param filters_l list : This list of str or tuple (or both)
275 275
     #@return a tuple(FILTERS, RELATIONNAL_FILTERS
276 276
     #@todo move this doc in another place (a dedicated page ?)
277
-    #@warning Does not supports multiple UID for an EmClass
277
+    #@warning Does not support multiple UID for an EmClass
278 278
     def _prepare_filters(self, filters_l):
279 279
         filters = list()
280 280
         res_filters = list()
@@ -292,7 +292,7 @@ class LeFilteredQuery(LeQuery):
292 292
 
293 293
         for field, operator, value in filters:
294 294
             err_key = "%s %s %s" % (field, operator, value)  # to push in err_l
295
-            # Spliting field name to be able to detect a relational field
295
+            # Splitting field name to be able to detect a relational field
296 296
             field_spl = field.split('.')
297 297
             if len(field_spl) == 2:
298 298
                 field, ref_field = field_spl
@@ -336,14 +336,14 @@ a relational field, but %s.%s was present in the filter"
336 336
                     else:
337 337
                         if len(ref_uid) > 1:
338 338
                             msg = "The referenced classes are identified by \
339
-fields with different name. Unable to determine wich field to use for the \
339
+fields with different names. Unable to determine which field to use for the \
340 340
 reference"
341 341
                         else:
342
-                            msg = "Unknow error when trying to determine wich \
342
+                            msg = "Unknow error when trying to determine which \
343 343
 field to use for the relational filter"
344 344
                         err_l[err_key] = RuntimeError(msg)
345 345
                         continue
346
-                # Prepare relational field
346
+                # Prepares relational field
347 347
                 ret = self._prepare_relational_fields(field, ref_field)
348 348
                 if isinstance(ret, Exception):
349 349
                     err_l[err_key] = ret
@@ -362,7 +362,7 @@ field to use for the relational filter"
362 362
                 err_l)
363 363
         return (res_filters, rel_filters)
364 364
 
365
-    # @brief Check and split a query filter
365
+    ## @brief Checks and splits a query filter
366 366
     # @note The query_filter format is "FIELD OPERATOR VALUE"
367 367
     # @param query_filter str : A query_filter string
368 368
     # @param cls
@@ -387,8 +387,8 @@ field to use for the relational filter"
387 387
                 raise ValueError(msg % query_filter)
388 388
         return result
389 389
 
390
-    # @brief Compile the regex for query_filter processing
391
-    # @note Set _LeObject._query_re
390
+    ## @brief Compiles the regex for query_filter processing
391
+    # @note Sets _LeObject._query_re
392 392
     @classmethod
393 393
     def __compile_query_re(cls):
394 394
         op_re_piece = '(?P<operator>(%s)'
@@ -412,10 +412,10 @@ field to use for the relational filter"
412 412
             msg %= (fieldname, target_class.__name__)
413 413
             return NameError(msg)
414 414
 
415
-    # @brief Prepare a relational filter
415
+    ## @brief Prepares a relational filter
416 416
     #
417 417
     # Relational filters are composed of a tuple like the simple filters
418
-    # but the first element of this tuple is a tuple to :
418
+    # but the first element of this tuple is also a tuple :
419 419
     #
420 420
     #<code>((FIELDNAME, {REF_CLASS: REF_FIELD}), OP, VALUE)</code>
421 421
     # Where :
@@ -426,7 +426,7 @@ field to use for the relational filter"
426 426
     #
427 427
     # Visibly the REF_FIELD value of the dict will vary only when
428 428
     # no REF_FIELD is explicitly given in the filter string notation
429
-    # and REF_CLASSES has differents uid
429
+    # and REF_CLASS classes have different uids
430 430
     #
431 431
     #@par String notation examples
432 432
     #<pre>contributeur IN (1,2,3,5)</pre> will be transformed into :
@@ -443,7 +443,7 @@ field to use for the relational filter"
443 443
     #@todo move the documentation to another place
444 444
     #
445 445
     #@param fieldname str : The relational field name
446
-    #@param ref_field str|None : The referenced field name (if None use
446
+    #@param ref_field str|None : The referenced field name (if None uses
447 447
     # uniq identifiers as referenced field
448 448
     #@return a well formed relational filter tuple or an Exception instance
449 449
     def _prepare_relational_fields(self, fieldname, ref_field=None):
@@ -461,7 +461,7 @@ field to use for the relational filter"
461 461
                 if r_ds is None:
462 462
                     r_ds = ref_class._datasource_name
463 463
                 elif ref_class._datasource_name != r_ds:
464
-                    return RuntimeError("All referenced class doesn't have the\
464
+                    return RuntimeError("All referenced classes don't have the\
465 465
  same datasource. Query not possible")
466 466
                 if ref_field in ref_class.fieldnames(True):
467 467
                     ref_dict[ref_class] = ref_field
@@ -477,7 +477,7 @@ the relational filter %s"
477 477
         return (fieldname, ref_dict)
478 478
 
479 479
 
480
-# @brief A query to insert a new object
480
+## @brief A query to insert a new object
481 481
 class LeInsertQuery(LeQuery):
482 482
     _hook_prefix = 'leapi_insert_'
483 483
     _data_check_args = {'complete': True, 'allow_internal': False}
@@ -505,20 +505,20 @@ abstract LeObject : %s" % target_class)
505 505
         return nb_inserted
506 506
     """
507 507
 
508
-    #  @brief Execute the insert query
508
+    #  @brief Executes the insert query
509 509
     def execute(self, data):
510 510
         return super().execute(data=data)
511 511
 
512 512
 
513
-# @brief A query to update data for a given object
513
+## @brief A query to update data for a given object
514 514
 #
515 515
 #@todo Change behavior, Huge optimization problem when updating using filters
516
-# and not instance. We have to run a GET and then 1 update by fecthed object...
516
+# and not instance. We have to run a GET and then one update by fetched object...
517 517
 class LeUpdateQuery(LeFilteredQuery):
518 518
     _hook_prefix = 'leapi_update_'
519 519
     _data_check_args = {'complete': False, 'allow_internal': False}
520 520
 
521
-    # @brief Instanciate an update query
521
+    ## @brief Instanciates an update query
522 522
     #
523 523
     # If a class and not an instance is given, no query_filters are expected
524 524
     # and the update will be fast and simple. Else we have to run a get query
@@ -529,7 +529,7 @@ class LeUpdateQuery(LeFilteredQuery):
529 529
     #@todo change strategy with instance update. We have to accept data for
530 530
     # the execute method
531 531
     def __init__(self, target, query_filters=None):
532
-        # @brief This attr is set only if the target argument is an
532
+        ## @brief This attr is set only if the target argument is an
533 533
         # instance of a LeObject subclass
534 534
         self.__leobject_instance_datas = None
535 535
         target_class = target
@@ -547,9 +547,9 @@ target to LeUpdateQuery constructor"
547 547
 
548 548
         super().__init__(target_class, query_filters)
549 549
 
550
-    # @brief Implements an update query
550
+    ## @brief Implements an update query
551 551
     #@param data dict : data to be updated
552
-    #@returns the number of updated items
552
+    #@return the number of updated items
553 553
     #@todo change stategy for instance update. Data should be allowed
554 554
     # for execute method (and query)
555 555
     def _query(self, data):
@@ -593,21 +593,21 @@ query on a class with filters")
593 593
         return super().execute(data=data)
594 594
 
595 595
 
596
-# @brief A query to delete an object
596
+## @brief A query to delete an object
597 597
 class LeDeleteQuery(LeFilteredQuery):
598 598
     _hook_prefix = 'leapi_delete_'
599 599
 
600 600
     def __init__(self, target_class, query_filter):
601 601
         super().__init__(target_class, query_filter)
602 602
 
603
-    #  @brief Execute the delete query
603
+    #  @brief Executes the delete query
604 604
     # @param data
605 605
     def execute(self, data=None):
606 606
         return super().execute()
607 607
 
608
-    # @brief Implements delete query operations
608
+    ## @brief Implements delete query operations
609 609
     # @param data
610
-    #@returns the number of deleted items
610
+    #@return the number of deleted items
611 611
     def _query(self, data=None):
612 612
         filters, rel_filters = self._query_filter
613 613
         nb_deleted = self._rw_datasource.delete(
@@ -618,7 +618,7 @@ class LeDeleteQuery(LeFilteredQuery):
618 618
 class LeGetQuery(LeFilteredQuery):
619 619
     _hook_prefix = 'leapi_get_'
620 620
 
621
-    # @brief Instanciate a new get query
621
+    ## @brief Instanciates a new get query
622 622
     #@param target_class LeObject : class of object the query is about
623 623
     #@param query_filters dict : {OP, list of query filters}
624 624
     # or tuple (FIELD, OPERATOR, VALUE) )
@@ -630,15 +630,15 @@ class LeGetQuery(LeFilteredQuery):
630 630
     #   - offset int : offset
631 631
     def __init__(self, target_class, query_filters, **kwargs):
632 632
         super().__init__(target_class, query_filters)
633
-        # @brief The fields to get
633
+        ## @brief The fields to get
634 634
         self._field_list = None
635
-        # @brief An equivalent to the SQL ORDER BY
635
+        ## @brief An equivalent to the SQL ORDER BY
636 636
         self._order = None
637
-        # @brief An equivalent to the SQL GROUP BY
637
+        ## @brief An equivalent to the SQL GROUP BY
638 638
         self._group = None
639
-        # @brief An equivalent to the SQL LIMIT x
639
+        ## @brief An equivalent to the SQL LIMIT x
640 640
         self._limit = None
641
-        # @brief An equivalent to the SQL LIMIT x, OFFSET
641
+        ## @brief An equivalent to the SQL LIMIT x, OFFSET
642 642
         self._offset = 0
643 643
 
644 644
         # Checking kwargs and assigning default values if there is some
@@ -675,7 +675,7 @@ class LeGetQuery(LeFilteredQuery):
675 675
                 msg = "offset argument expected to be an integer >= 0"
676 676
                 raise ValueError(msg)
677 677
 
678
-    # @brief Set the field list
678
+    ## @brief Set the field list
679 679
     # @param field_list list | None : If None use all fields
680 680
     # @return None
681 681
     # @throw LeApiQueryError if unknown field given
@@ -694,12 +694,12 @@ class LeGetQuery(LeFilteredQuery):
694 694
                 raise LeApiQueryErrors(msg=msg, exceptions=err_l)
695 695
             self._field_list = list(set(field_list))
696 696
 
697
-    # @brief Execute the get query
697
+    ## @brief Executes the get query
698 698
     def execute(self, data=None):
699 699
         return super().execute()
700 700
 
701
-    # @brief Implements select query operations
702
-    # @returns a list containing the item(s)
701
+    ## @brief Implements select query operations
702
+    # @return a list containing the item(s)
703 703
     def _query(self, data=None):
704 704
         # select data corresponding to query_filter
705 705
         fl = list(self._field_list) if self._field_list is not None else None
@@ -714,7 +714,8 @@ class LeGetQuery(LeFilteredQuery):
714 714
             offset=self._offset)
715 715
         return l_data
716 716
 
717
-    # @return a dict with query infos
717
+    ## @brief Returns a dict with query infos
718
+    # @return a dict
718 719
     def dump_infos(self):
719 720
         ret = super().dump_infos()
720 721
         ret.update({'field_list': self._field_list,
@@ -725,6 +726,8 @@ class LeGetQuery(LeFilteredQuery):
725 726
                     })
726 727
         return ret
727 728
 
729
+    ## @brief Returns a string representation of the query
730
+    # @return a string
728 731
     def __repr__(self):
729 732
         res = "<LeGetQuery target={target_class} filter={query_filter} \
730 733
 field_list={field_list} order={order} group={group} limit={limit} \

+ 97
- 67
lodel/plugin/core_scripts.py View File

@@ -1,19 +1,21 @@
1 1
 import operator
2 2
 import shutil
3 3
 import tempfile
4
-import os, os.path
4
+import os
5
+import os.path
6
+import argparse
5 7
 from lodel.context import LodelContext
6 8
 LodelContext.expose_modules(globals(), {
7 9
     'lodel.plugin.scripts': 'lodel_script',
8 10
     'lodel.logger': 'logger'})
9 11
 
10
-##@package lodel.plugin.core_scripts
12
+# @package lodel.plugin.core_scripts
11 13
 #@brief Lodel2 internal scripts declaration
12 14
 #@ingroup lodel2_plugins
13 15
 #@ingroup lodel2_script
14 16
 
15 17
 
16
-##@brief Implements lodel_admin.py list-plugins action
18
+## @brief Implement lodel_admin.py list-plugins action
17 19
 #@ingroup lodel2_plugins
18 20
 #@ingroup lodel2_script
19 21
 #
@@ -21,31 +23,36 @@ class ListPlugins(lodel_script.LodelScript):
21 23
     _action = 'plugins-list'
22 24
     _description = "List all installed plugins"
23 25
 
26
+    ## @brief Set available arguments for the script lodel_admin with action plugin-list
27
+    # @param parser : a parser (see argparse python module)
24 28
     @classmethod
25 29
     def argparser_config(cls, parser):
26 30
         parser.add_argument('-v', '--verbose',
27
-            help="Display more informations on installed plugins",
28
-            action='store_true')
31
+                            help="Display more informations on installed plugins",
32
+                            action='store_true')
29 33
         parser.add_argument('-c', '--csv',
30
-            help="Format output in CSV format",
31
-            action='store_true')
34
+                            help="Format output in CSV format",
35
+                            action='store_true')
32 36
 
37
+    ## @brief Display the list of plugins according to given arguments
38
+    # @param args : grabbed from argv of command line
33 39
     @classmethod
34 40
     def run(cls, args):
35 41
         import lodel.plugin.plugins
36 42
         from lodel.plugin.plugins import Plugin
37 43
         if args.verbose:
38
-            #_discover do not returns duplicated names
44
+            #_discover does not return duplicated names
39 45
             tmp_plist = Plugin._discover(lodel.plugin.plugins.PLUGINS_PATH)
40 46
             plist = []
41
-            #ordering the list by plugin's name
47
+            # ordering the list by plugin's name
42 48
             for pname in sorted(set([d['name'] for d in tmp_plist])):
43 49
                 for pinfos in tmp_plist:
44 50
                     if pinfos['name'] == pname:
45 51
                         plist.append(pinfos)
46 52
         else:
53
+            # Retrieve the dict with the list of plugins
47 54
             pdict = Plugin.discover()
48
-            #casting to a list ordered by names
55
+            # casting to a list ordered by names
49 56
             plist = []
50 57
             for pname in sorted(pdict.keys()):
51 58
                 plist.append(pdict[pname])
@@ -71,35 +78,39 @@ class ListPlugins(lodel_script.LodelScript):
71 78
         print(res)
72 79
 
73 80
 
74
-##@brief Handle install & uninstall of lodel plugins
81
+## @brief Handle install & uninstall of lodel plugins
75 82
 class PluginManager(lodel_script.LodelScript):
76 83
     _action = 'plugins'
77 84
     _description = "Install/Uninstall plugins"
78 85
 
86
+    ## @brief Set parser's available arguments for lodel_admin.py with action plugins
87
+    # @param parser : a parser (see argparse python module)
79 88
     @classmethod
80 89
     def argparser_config(cls, parser):
81 90
         parser.add_argument('-u', '--uninstall',
82
-            help="Uninstall specified plugin",
83
-            action='store_true')
91
+                            help="Uninstall specified plugin",
92
+                            action='store_true')
84 93
         parser.add_argument('-c', '--clean',
85
-            help="Uninstall duplicated plugins with smallest version number",
86
-            action="store_true")
94
+                            help="Uninstall duplicated plugins with smallest version number",
95
+                            action="store_true")
87 96
         parser.add_argument('-n', '--plugin-name', nargs='*',
88
-            default = list(),
89
-            help="Indicate a plugin name to uninstall",
90
-            type=str)
97
+                            default=list(),
98
+                            help="Indicate a plugin name to uninstall",
99
+                            type=str)
91 100
         parser.add_argument('-a', '--archive', nargs='*',
92
-            default = list(),
93
-            help="(NOT IMPLEMENTED) Specify a tarball containing a plugin \
101
+                            default=list(),
102
+                            help="(NOT IMPLEMENTED) Specify a tarball containing a plugin \
94 103
 to install",
95
-            type=str)
104
+                            type=str)
96 105
         parser.add_argument('-d', '--directory', nargs='*',
97
-            default = list(),
98
-            help="Specify a plugin by its directory",
99
-            type=str)
106
+                            default=list(),
107
+                            help="Specify a plugin by its directory",
108
+                            type=str)
100 109
         parser.add_argument('-f', '--force', action="store_true",
101
-            help="Force plugin directory deletion in case of check errors")
110
+                            help="Force plugin directory deletion in case of check errors")
102 111
 
112
+    ## @brief Install, uninstall or clean a plugin according to the option given
113
+    # @param args : grabbed from argv of command line
103 114
     @classmethod
104 115
     def run(cls, args):
105 116
         if args.clean:
@@ -111,46 +122,55 @@ only use option -n --name to clean plugins with specified names")
111 122
         if args.uninstall:
112 123
             return cls.uninstall(args)
113 124
         return cls.install(args)
114
-    
115
-    ##@brief Handles plugins install
125
+
126
+    ## @brief Install plugins
127
+    # @param args : grabbed from argv of command line
116 128
     @classmethod
117 129
     def install(cls, args):
118 130
         import lodel.plugin.plugins
119 131
         from lodel.plugin.plugins import Plugin
120 132
         from lodel.plugin.exceptions import PluginError
133
+
134
+        # We can't install a plugin with just its name, we have to know where
135
+        # it is
121 136
         if len(args.plugin_name) > 0:
122 137
             raise RuntimeError("Unable to install a plugin from its name !\
123 138
 We do not know where to find it...")
124 139
         plist = Plugin.discover()
125 140
         errors = dict()
141
+
142
+        # For now we do not handle archive for plugins
126 143
         if len(args.archive) > 0:
127 144
             raise NotImplementedError("Not supported yet")
128
-        
145
+
129 146
         plugins_infos = {}
130 147
         for cur_dir in args.directory:
148
+            # Check that the directories obtained correspond to plugins
131 149
             try:
132
-                res = Plugin.dir_is_plugin(cur_dir, assert_in_package = False)
150
+                res = Plugin.dir_is_plugin(cur_dir, assert_in_package=False)
133 151
                 if res is False:
134 152
                     errors[cur_dir] = PluginError("Not a plugin")
135 153
                 else:
136 154
                     plugins_infos[res['name']] = res
137 155
             except Exception as e:
138 156
                 errors[cur_dir] = e
139
-        #Abording because of previous errors
157
+
158
+        # Abording because of previous errors
140 159
         if len(errors) > 0:
141 160
             msg = "Abording installation because of following errors :\n"
142 161
             for path, expt in errors.items():
143 162
                 msg += ("\t- For path '%s' : %s\n" % (path, expt))
144 163
             raise RuntimeError(msg)
145
-        #No errors continuing to install
164
+
165
+        # No errors continuing to install
146 166
         for pname, pinfos in plugins_infos.items():
147 167
             if pname in plist:
148
-                #Found an installed plugin with the same name
149
-                #Cehcking both versions
168
+                # Found an installed plugin with the same name
169
+                # Checking both versions
150 170
                 if plist[pname]['version'] == pinfos['version']:
151 171
                     errors[pinfos['path']] = 'Abording installation of %s \
152 172
 found in %s because it seems to be allready installed in %s' % (
153
-    pname, pinfos['path'], plist[pname]['path'])
173
+                        pname, pinfos['path'], plist[pname]['path'])
154 174
                     continue
155 175
                 if plist[pname]['version'] > pinfos['version']:
156 176
                     errors[pinfos['path']] = 'Abording installation of %s \
@@ -159,46 +179,49 @@ installed in %s' % (pname, pinfos['path'], plist[pname]['path'])
159 179
                     continue
160 180
                 logger.info("Found a plugin with the same name but with an \
161 181
 inferior version. Continuing to install")
162
-            #Checking that we can safely copy our plugin
182
+            # Checking that we can safely copy our plugin
163 183
             dst_path = os.path.join(lodel.plugin.plugins.PLUGINS_PATH,
164
-                os.path.basename(os.path.dirname(pinfos['path'])))
184
+                                    os.path.basename(os.path.dirname(pinfos['path'])))
165 185
             orig_path = dst_path
166 186
             if os.path.isdir(dst_path):
167 187
                 dst_path = tempfile.mkdtemp(
168
-                    prefix = os.path.basename(dst_path)+'_',
169
-                    dir = lodel.plugin.plugins.PLUGINS_PATH)
170
-                logger.warning("A plugin allready exists in %s. Installing \
188
+                    prefix=os.path.basename(dst_path) + '_',
189
+                    dir=lodel.plugin.plugins.PLUGINS_PATH)
190
+                logger.warning("A plugin already exists in %s. Installing \
171 191
 in %s" % (orig_path, dst_path))
172 192
                 shutil.rmtree(dst_path)
173
-                
174
-            #Installing the plugin
175
-            shutil.copytree(pinfos['path'], dst_path, symlinks = False)
193
+
194
+            # Install the plugin
195
+            shutil.copytree(pinfos['path'], dst_path, symlinks=False)
176 196
             print("%s(%s) installed in %s" % (
177 197
                 pname, pinfos['version'], dst_path))
178 198
         if len(errors) > 0:
179
-            msg = "Following errors occurs during instalation process :\n"
199
+            msg = "Following errors occurs during installation process :\n"
180 200
             for path, error_msg in errors.items():
181 201
                 msg += "\t- For '%s' : %s" % (path, error_msg)
182 202
             print(msg)
183
-    
184
-    ##@brief Handles plugins uninstall
185
-    #@todo uninstall by path is broken
203
+
204
+    ## @brief Uninstall plugins
205
+    # @param args : grabbed from argv of command line
206
+    # @todo Does nothing for now : delete is commented
186 207
     @classmethod
187 208
     def uninstall(cls, args):
188 209
         import lodel.plugin.plugins
189 210
         from lodel.plugin.plugins import Plugin
190 211
         if len(args.archive) > 0:
191 212
             raise RuntimeError("Cannot uninstall plugin using -f --file \
192
-oprtions. Use -d --directory instead")
193
-        to_delete = dict() #Path to delete accumulator
213
+options. Use -d --directory instead")
214
+        to_delete = dict()  # will contain all pathes of plugins to delete
194 215
         errors = dict()
216
+        # Uninstall by pathes
195 217
         if len(args.directory) > 0:
196
-            #processing & checking -d --directory arguments
218
+            # processing & checking -d --directory arguments
197 219
             for path in args.directory:
198 220
                 apath = os.path.abspath(path)
199
-                if not apath.startswith(lodel.plugin.plugins.PLUGINS_PATH):
221
+                # We assume plugins are in lodel/plugins
222
+                if not apath.startswith(lodel.plugins.PLUGINS_PATH):
200 223
                     errors[path] = "Not a subdir of %s"
201
-                    errors[path] %= lodel.plugin.plugins.PLUGINS_PATH
224
+                    errors[path] %= lodel.plugins.PLUGINS_PATH
202 225
                     continue
203 226
                 try:
204 227
                     pinfos = Plugin.dir_is_plugin(apath)
@@ -208,13 +231,16 @@ oprtions. Use -d --directory instead")
208 231
                         continue
209 232
                 to_delete[path] = pinfos
210 233
 
234
+        # Uninstall by plugin's names
235
+        # We retrieve the path of the plugin from its name
211 236
         if len(args.plugin_name) > 0:
212
-            #Processing -n --plugin-name arguments
213
-            plist = Plugin._discover(lodel.plugin.plugins.PLUGINS_PATH)
237
+            # Processing -n --plugin-name arguments
238
+            plist = Plugin._discover(lodel.plugins.PLUGINS_PATH)
214 239
             for pinfos in plist:
215 240
                 if pinfos['name'] in args.plugin_name:
216 241
                     to_delete[pinfos['path']] = pinfos
217
-        
242
+
243
+        # Manage errors and exit if there is no force option
218 244
         if len(errors) > 0:
219 245
             msg = "Following errors detected before begining deletions :\n"
220 246
             for path, errmsg in errors.items():
@@ -222,15 +248,17 @@ oprtions. Use -d --directory instead")
222 248
             print(msg)
223 249
             if not args.force:
224 250
                 exit(1)
225
-        
251
+
226 252
         print("Begining deletion :")
227 253
         for path, pinfos in to_delete.items():
228
-            #shutil.rmtree(path)
254
+            # shutil.rmtree(path)
229 255
             print("rm -R %s" % path)
230 256
             print("\t%s(%s) in %s deleted" % (
231 257
                 pinfos['name'], pinfos['version'], pinfos['path']))
232 258
 
233
-    ##@brief Handles plugins clean
259
+    ## @brief Clean plugins by removing plugins with same names \
260
+    # The last version is kept
261
+    # @param args : grabbed from argv of command line
234 262
     @classmethod
235 263
     def clean(cls, args):
236 264
         import lodel.plugin.plugins
@@ -242,9 +270,11 @@ oprtions. Use -d --directory instead")
242 270
             names = args.plugin_name
243 271
         else:
244 272
             names = list(Plugin.discover().keys())
245
-        #_dicover do not remove duplicated names
246
-        full_list = Plugin._discover(lodel.plugin.plugins.PLUGINS_PATH)
247
-        #Casting into a dict with list of plugins infos
273
+
274
+        #_discover do not remove duplicated names
275
+        full_list = Plugin._discover(lodel.plugins.PLUGINS_PATH)
276
+
277
+        # Casting into a dict with list of plugins infos
248 278
         pdict = dict()
249 279
         for pinfos in full_list:
250 280
             if pinfos['name'] in names:
@@ -256,7 +286,7 @@ oprtions. Use -d --directory instead")
256 286
         clean_count = 0
257 287
         for pname, pinfos_l in pdict.items():
258 288
             if len(pinfos_l) > 1:
259
-                #There are some plugins to clean
289
+                # There are some plugins to clean
260 290
                 tmp_l = sorted(pinfos_l, key=lambda item: item['version'])
261 291
                 to_clean += tmp_l[:-1]
262 292
                 msg = "Found %s(%s). Cleaning " % (
@@ -270,10 +300,10 @@ oprtions. Use -d --directory instead")
270 300
         if clean_count > 0:
271 301
             print("%d plugins were uninstalled" % clean_count)
272 302
         else:
273
-            print("Allready clean")
303
+            print("Already clean")
274 304
 
275 305
 
276
-##@brief Implements lodel_admin.py **hooks-list** action
306
+## @brief Implements lodel_admin.py **hooks-list** action
277 307
 #@ingroup lodel2_script
278 308
 #@ingroup lodel2_hooks
279 309
 class ListHooks(lodel_script.LodelScript):
@@ -284,6 +314,7 @@ class ListHooks(lodel_script.LodelScript):
284 314
     def argparser_config(cls, parser):
285 315
         pass
286 316
 
317
+    ## @brief Display the list of hooks registered
287 318
     @classmethod
288 319
     def run(cls, args):
289 320
         import loader
@@ -296,8 +327,7 @@ class ListHooks(lodel_script.LodelScript):
296 327
             for hfun, priority in hlist[name]:
297 328
                 msg = "\t\t- {modname}.{funname} with priority : {priority}"
298 329
                 print(msg.format(
299
-                    modname = hfun.__module__,
300
-                    funname = hfun.__name__,
301
-                    priority = priority))
330
+                    modname=hfun.__module__,
331
+                    funname=hfun.__name__,
332
+                    priority=priority))
302 333
             print("\n")
303
-

+ 218
- 219
lodel/plugin/plugins.py View File

@@ -13,96 +13,90 @@ LodelContext.expose_modules(globals(), {
13 13
     'lodel.settings.utils': ['SettingsError'],
14 14
     'lodel.plugin.hooks': ['LodelHook'],
15 15
     'lodel.plugin.exceptions': ['PluginError', 'PluginVersionError',
16
-        'PluginTypeError', 'LodelScriptError', 'DatasourcePluginError'],
16
+                                'PluginTypeError', 'LodelScriptError', 'DatasourcePluginError'],
17 17
     'lodel.exceptions': ['LodelException', 'LodelExceptions',
18
-        'LodelFatalError', 'DataNoneValid', 'FieldValidationError']})
18
+                         'LodelFatalError', 'DataNoneValid', 'FieldValidationError']})
19 19
 
20
-## @package lodel.plugins Lodel2 plugins management
20
+#  @package lodel.plugins Lodel2 plugins management
21 21
 #@ingroup lodel2_plugins
22 22
 #
23 23
 # Lodel2 plugins are stored in directories
24
-# A typicall lodel2 plugin directory structure looks like :
24
+# A typical lodel2 plugin directory structure looks like :
25 25
 # - {{__init__.py}}} containing informations like full_name, authors, licence etc.
26 26
 # - main.py containing hooks registration etc
27 27
 # - confspec.py containing a configuration specification dictionary named CONFSPEC
28 28
 #
29
-# All plugins are expected to be found in multiple locations :
30
-# - in the lodel package (lodel.plugins)
31
-# - in the context directorie in a plugins/ dir (symlink to lodel.plugins) <-
32
-#this is obsolete now, since we enforce ALL plugins to be in the lodel package
29
+# All plugins are expected to be found in the lodel package (lodel.plugins)
33 30
 #
34
-#@todo Check if the symlink in the lodelcontext dir is obsolete !!!
35
-#@warning The plugins dir is at two locations : in lodel package and in
36
-#instance directory. Some stuff seems to still needs plugins to be in
37
-#the instance directory but it seems to be a really bad idea...
38
-
39
-##@defgroup plugin_init_specs Plugins __init__.py specifications
31
+# @defgroup plugin_init_specs Plugins __init__.py specifications
40 32
 #@ingroup lodel2_plugins
41 33
 #@{
42 34
 
43
-##@brief The package in which we will load plugins modules
35
+# @brief The package in which we will load plugins modules
44 36
 VIRTUAL_PACKAGE_NAME = 'lodel.plugins'
45
-##@brief The temporary package to import python sources
37
+# @brief The temporary package to import python sources
46 38
 VIRTUAL_TEMP_PACKAGE_NAME = 'lodel.plugin_tmp'
47
-##@brief Plugin init filename
48
-INIT_FILENAME = '__init__.py' # Loaded with settings
49
-##@brief Name of the variable containing the plugin name
39
+# @brief Plugin init filename
40
+INIT_FILENAME = '__init__.py'  # Loaded with settings
41
+# @brief Name of the variable containing the plugin name
50 42
 PLUGIN_NAME_VARNAME = '__plugin_name__'
51
-##@brief Name of the variable containing the plugin type
43
+# @brief Name of the variable containing the plugin type
52 44
 PLUGIN_TYPE_VARNAME = '__plugin_type__'
53
-##@brief Name of the variable containing the plugin version
45
+# @brief Name of the variable containing the plugin version
54 46
 PLUGIN_VERSION_VARNAME = '__version__'
55
-##@brief Name of the variable containing the confpsec filename
47
+# @brief Name of the variable containing the confpsec filename
56 48
 CONFSPEC_FILENAME_VARNAME = '__confspec__'
57
-##@brief Name of the variable containing the confspecs
49
+# @brief Name of the variable containing the confspecs
58 50
 CONFSPEC_VARNAME = 'CONFSPEC'
59
-##@brief Name of the variable containing the loader filename
51
+# @brief Name of the variable containing the loader filename
60 52
 LOADER_FILENAME_VARNAME = '__loader__'
61
-##@brief Name of the variable containing the plugin dependencies
53
+# @brief Name of the variable containing the plugin dependencies
62 54
 PLUGIN_DEPS_VARNAME = '__plugin_deps__'
63
-##@brief Name of the optionnal activate method
55
+# @brief Name of the optionnal activate method
64 56
 ACTIVATE_METHOD_NAME = '_activate'
65
-##@brief Default & failover value for plugins path list
66
-PLUGINS_PATH = os.path.join(LodelContext.context_dir(),'plugins')
57
+# @brief Default & failover value for plugins path list
58
+PLUGINS_PATH = os.path.join(LodelContext.context_dir(), 'plugins')
67 59
 
68
-##@brief List storing the mandatory variables expected in a plugin __init__.py
69
-#file
60
+# @brief List storing the mandatory variables expected in a plugin __init__.py
61
+# file
70 62
 MANDATORY_VARNAMES = [PLUGIN_NAME_VARNAME, LOADER_FILENAME_VARNAME,
71
-    PLUGIN_VERSION_VARNAME]
63
+                      PLUGIN_VERSION_VARNAME]
72 64
 
73
-##@brief Default plugin type
74
-DEFAULT_PLUGIN_TYPE = 'extension' #Value found in lodel/plugin/extensions.py::Extensions._type_conf_name
65
+# @brief Default plugin type
66
+DEFAULT_PLUGIN_TYPE = 'extension'  # Value found in lodel/plugin/extensions.py::Extensions._type_conf_name
75 67
 
76
-## @}
68
+# @}
77 69
 
78
-##@brief Describe and handle version numbers
70
+# @brief Describe and handle version numbers
79 71
 #@ingroup lodel2_plugins
80 72
 #
81
-#A version number can be represented by a string like MAJOR.MINOR.PATCH
82
-#or by a list [MAJOR, MINOR,PATCH ].
73
+# A version number can be represented by a string like MAJOR.MINOR.PATCH
74
+# or by a list [MAJOR, MINOR,PATCH ].
83 75
 #
84
-#The class implements basics comparison function and string repr
76
+# The class implements basics comparison function and string repr
77
+
78
+
85 79
 class PluginVersion(object):
86 80
 
87
-    PROPERTY_LIST = ['major', 'minor', 'revision' ]
81
+    PROPERTY_LIST = ['major', 'minor', 'revision']
88 82
 
89
-    ##@brief Version constructor
83
+    # @brief Version constructor
90 84
     #@param *args : You can either give a str that will be splitted on . or you
91
-    #can give a iterable containing 3 integer or 3 arguments representing
92
-    #major, minor and revision version
85
+    # can give a iterable containing 3 integers or 3 arguments representing
86
+    # major, minor and revision version
93 87
     def __init__(self, *args):
94
-        self.__version = [0 for _ in range(3) ]
88
+        self.__version = [0 for _ in range(3)]
95 89
         if len(args) == 1:
96 90
             arg = args[0]
97 91
             if isinstance(arg, str):
98
-                #Casting from string to version numbers
92
+                # Casting from string to version numbers
99 93
                 spl = arg.split('.')
100 94
                 invalid = False
101 95
                 if len(spl) > 3:
102 96
                     raise PluginVersionError("The string '%s' is not a valid plugin \
103 97
 version number" % arg)
104 98
                 if len(spl) < 3:
105
-                    spl += [ 0 for _ in range(3-len(spl))]
99
+                    spl += [0 for _ in range(3 - len(spl))]
106 100
                 try:
107 101
                     self.__version = [int(s) for s in spl]
108 102
                 except (ValueError, TypeError):
@@ -123,29 +117,29 @@ version number" % arg)
123 117
             raise PluginError("Expected between 1 and 3 positional arguments \
124 118
 but %d arguments found" % len(args))
125 119
         else:
126
-            for i,v in enumerate(args):
120
+            for i, v in enumerate(args):
127 121
                 self.__version[i] = int(v)
128
-        #Checks that version numbering is correct
122
+        # Checks that version numbering is correct
129 123
         for v in self.__version:
130 124
             if v < 0:
131 125
                 raise PluginVersionError("No negative version number allowed !")
132 126
 
133
-    ##@brief Property to access major version number
127
+    # @brief Property to access major version number
134 128
     @property
135 129
     def major(self):
136 130
         return self.__version[0]
137 131
 
138
-    ##@brief Property to access minor version number
132
+    # @brief Property to access minor version number
139 133
     @property
140 134
     def minor(self):
141 135
         return self.__version[1]
142 136
 
143
-    ##@brief Property to access patch version number
137
+    # @brief Property to access patch version number
144 138
     @property
145 139
     def revision(self):
146 140
         return self.__version[2]
147 141
 
148
-    ##@brief Check and prepare comparisoon argument
142
+    # @brief Check and prepare comparison argument
149 143
     #@return A PluginVersion instance
150 144
     #@throw PluginError if invalid argument provided
151 145
     def __cmp_check(self, other):
@@ -155,10 +149,10 @@ but %d arguments found" % len(args))
155 149
                     return PluginVersion(other)
156 150
             except TypeError:
157 151
                 raise PluginError("Cannot compare argument '%s' with \
158
-a PluginVerison instance" % other)
152
+a PluginVersion instance" % other)
159 153
         return other
160 154
 
161
-    ##@brief Allow accessing to versions parts using interger index
155
+    # @brief Allow accessing to version parts using integer index
162 156
     #@param key int : index
163 157
     #@return major for key == 0, minor for key == 1, revision for key == 2
164 158
     def __getitem__(self, key):
@@ -208,40 +202,42 @@ a PluginVerison instance" % other)
208 202
         return "{'major': %d, 'minor': %d, 'revision': %d}" % tuple(
209 203
             self.__version)
210 204
 
211
-##@brief Plugin metaclass that allows to "catch" child class declaration
205
+# @brief Plugin metaclass that allows to "catch" child class declaration
212 206
 #@ingroup lodel2_plugins
213 207
 #
214
-#Automatic script registration on child class declaration
208
+# Automatic script registration on child class declaration
209
+
210
+
215 211
 class MetaPlugType(type):
216 212
 
217
-    ##@brief Dict storing all plugin types
213
+    # @brief Dict storing all plugin types
218 214
     #
219
-    #key is the _type_conf_name and value is the class
215
+    # key is the _type_conf_name and value is the class
220 216
     _all_ptypes = dict()
221 217
 
222
-    ##@brief type constructor reimplementation
218
+    # @brief type constructor reimplementation
223 219
     def __init__(self, name, bases, attrs):
224
-        #Here we can store all child classes of Plugin
220
+        # Here we can store all child classes of Plugin
225 221
         super().__init__(name, bases, attrs)
226 222
         if len(bases) == 1 and bases[0] == object:
227 223
             return
228
-        #Regitering a new plugin type
224
+        # Regitering a new plugin type
229 225
         MetaPlugType._all_ptypes[self._type_conf_name] = self
230 226
 
231
-    ##@brief Accessor to the list of plugin types
227
+    # @brief Accessor to the list of plugin types
232 228
     #@return A copy of _all_ptypes attribute (a dict with typename as key
233
-    #and the class as value)
229
+    # and the class as value)
234 230
     @classmethod
235 231
     def all_types(cls):
236 232
         return copy.copy(cls._all_ptypes)
237 233
 
238
-    ##@brief Accessor to the list of plugin names
239
-    #@return a list of plugin name
234
+    # @brief Accessor to the list of plugin names
235
+    #@return a list of all plugin names
240 236
     @classmethod
241 237
     def all_ptype_names(cls):
242 238
         return list(cls._all_ptypes.keys())
243 239
 
244
-    ##@brief Given a plugin type name return a Plugin child class
240
+    # @brief Given a plugin type name returns a Plugin child class
245 241
     #@param ptype_name str : a plugin type name
246 242
     #@return A Plugin child class
247 243
     #@throw PluginError if ptype_name is not an exsiting plugin type name
@@ -251,14 +247,14 @@ class MetaPlugType(type):
251 247
             raise PluginError("Unknown plugin type '%s'" % ptype_name)
252 248
         return cls._all_ptypes[ptype_name]
253 249
 
254
-    ##@brief Call the clear classmethod on each child classes
250
+    # @brief Call the clear classmethod on each child classes
255 251
     @classmethod
256 252
     def clear_cls(cls):
257 253
         for pcls in cls._all_ptypes.values():
258 254
             pcls.clear_cls()
259 255
 
260 256
 
261
-##@brief Handle plugins
257
+# @brief Handle plugins
262 258
 #@ingroup lodel2_plugins
263 259
 #
264 260
 # An instance represent a loaded plugin. Class methods allow to load/preload
@@ -270,32 +266,32 @@ class MetaPlugType(type):
270 266
 # 3. the loader call load_all to register hooks etc
271 267
 class Plugin(object, metaclass=MetaPlugType):
272 268
 
273
-    ##@brief Stores Plugin instances indexed by name
269
+    # @brief Stores Plugin instances indexed by name
274 270
     _plugin_instances = dict()
275 271
 
276
-    ##@brief Attribute used by load_all and load methods to detect circular
277
-    #dependencies
272
+    # @brief Attribute used by load_all and load methods to detect circular
273
+    # dependencies
278 274
     _load_called = []
279 275
 
280
-    ##@brief Attribute that stores plugins list from discover cache file
276
+    # @brief Attribute that stores plugins list from discover cache file
281 277
     _plugin_list = None
282 278
 
283 279
     #@brief Designed to store, in child classes, the confspec indicating \
284
-    #where plugin list is stored
280
+    # where plugin list is stored
285 281
     _plist_confspecs = None
286 282
 
287
-    ##@brief The name of the plugin type in the confguration
283
+    # @brief The name of the plugin type in the confguration
288 284
     #
289
-    #None in abstract classes and implemented by child classes
285
+    # None in abstract classes and implemented by child classes
290 286
     _type_conf_name = None
291 287
 
292
-    ##@brief Stores virtual modules uniq key
288
+    # @brief Stores virtual modules uniq key
293 289
     #@note When testing if a dir contains a plugin, if we reimport the __init__
294
-    #in a module with the same name, all non existing value (plugin_type for
295
-    #example) are replaced by previous plugin values
290
+    # in a module with the same name, all non existing value (plugin_type for
291
+    # example) are replaced by previous plugin values
296 292
     _mod_cnt = 0
297 293
 
298
-    ##@brief Plugin class constructor
294
+    # @brief Plugin class constructor
299 295
     #
300 296
     # Called by setting in early stage of lodel2 boot sequence using classmethod
301 297
     # register
@@ -304,18 +300,18 @@ class Plugin(object, metaclass=MetaPlugType):
304 300
     # @throw PluginError
305 301
     def __init__(self, plugin_name):
306 302
 
307
-        ##@brief The plugin name
303
+        # @brief The plugin name
308 304
         self.name = plugin_name
309
-        ##@brief The plugin package path
305
+        # @brief The plugin package path
310 306
         self.path = self.plugin_path(plugin_name)
311 307
 
312
-        ##@brief Stores the plugin module
308
+        # @brief Stores the plugin module
313 309
         self.module = None
314
-        ##@brief Stores the plugin loader module
310
+        # @brief Stores the plugin loader module
315 311
         self.__loader_module = None
316
-        ##@brief The plugin confspecs
312
+        # @brief The plugin confspecs
317 313
         self.__confspecs = dict()
318
-        ##@brief Boolean flag telling if the plugin is loaded or not
314
+        # @brief Boolean flag telling if the plugin is loaded or not
319 315
         self.loaded = False
320 316
 
321 317
         # Importing __init__.py infos in it
@@ -333,18 +329,18 @@ class Plugin(object, metaclass=MetaPlugType):
333 329
             except AttributeError:
334 330
                 msg = "Malformed plugin {plugin} . No {varname} not {filevar} found in __init__.py"
335 331
                 msg = msg.format(
336
-                    plugin = self.name,
337
-                    varname = CONFSPEC_VARNAME,
338
-                    filevar = CONFSPEC_FILENAME_VARNAME)
332
+                    plugin=self.name,
333
+                    varname=CONFSPEC_VARNAME,
334
+                    filevar=CONFSPEC_FILENAME_VARNAME)
339 335
                 raise PluginError(msg)
340 336
             except ImportError as e:
341 337
                 msg = "Broken plugin {plugin} : {expt}"
342 338
                 msg = msg.format(
343
-                    plugin = self.name,
344
-                    expt = str(e))
339
+                    plugin=self.name,
340
+                    expt=str(e))
345 341
                 raise PluginError(msg)
346 342
             except Exception as e:
347
-                msg = "Plugin '%s' :"+str(e)
343
+                msg = "Plugin '%s' :" + str(e)
348 344
                 raise e.__class__(msg)
349 345
 
350 346
             try:
@@ -353,13 +349,13 @@ class Plugin(object, metaclass=MetaPlugType):
353 349
             except AttributeError:
354 350
                 msg = "Broken plugin. {varname} not found in '{filename}'"
355 351
                 msg = msg.format(
356
-                    varname = CONFSPEC_VARNAME,
357
-                    filename = confspec_filename)
352
+                    varname=CONFSPEC_VARNAME,
353
+                    filename=confspec_filename)
358 354
                 raise PluginError(msg)
359 355
         # loading plugin version
360 356
         try:
361
-            #this try block should be useless. The existance of
362
-            #PLUGIN_VERSION_VARNAME in init file is mandatory
357
+            # this try block should be useless. The existance of
358
+            # PLUGIN_VERSION_VARNAME in init file is mandatory
363 359
             self.__version = getattr(self.module, PLUGIN_VERSION_VARNAME)
364 360
         except AttributeError:
365 361
             msg = "Error that should not append while loading plugin '%s': no \
@@ -377,8 +373,8 @@ class Plugin(object, metaclass=MetaPlugType):
377 373
             raise PluginError("Unknown plugin type '%s'" % self.__type)
378 374
         # Load plugin name from init file (just for checking)
379 375
         try:
380
-            #this try block should be useless. The existance of
381
-            #PLUGIN_NAME_VARNAME in init file is mandatory
376
+            # this try block should be useless. The existance of
377
+            # PLUGIN_NAME_VARNAME in init file is mandatory
382 378
             pname = getattr(self.module, PLUGIN_NAME_VARNAME)
383 379
         except AttributeError:
384 380
             msg = "Error that should not append : no %s found in plugin \
@@ -390,17 +386,17 @@ init file. Malformed plugin"
390 386
 name differ from the one found in plugin's init file"
391 387
             raise PluginError(msg)
392 388
 
393
-    ##@brief Try to import a file from a variable in __init__.py
389
+    # @brief Try to import a file from a variable in __init__.py
394 390
     #@param varname str : The variable name
395 391
     #@return loaded module
396 392
     #@throw AttributeError if varname not found
397 393
     #@throw ImportError if the file fails to be imported
398 394
     #@throw PluginError if the filename was not valid
399 395
     #@todo Some strange things append :
400
-    #when loading modules in test self.module.__name__ does not contains
401
-    #the package... but in prod cases the self.module.__name__ is
402
-    #the module fullname... Just a reminder note to explain the dirty
403
-    #if on self_modname
396
+    # when loading modules in test self.module.__name__ does not contains
397
+    # the package... but in prod cases the self.module.__name__ is
398
+    # the module fullname... Just a reminder note to explain the dirty
399
+    # if on self_modname
404 400
     def _import_from_init_var(self, varname):
405 401
         # Read varname
406 402
         try:
@@ -408,10 +404,10 @@ name differ from the one found in plugin's init file"
408 404
         except AttributeError:
409 405
             msg = "Malformed plugin {plugin}. No {varname} found in __init__.py"
410 406
             msg = msg.format(
411
-                plugin = self.name,
412
-                varname = LOADER_FILENAME_VARNAME)
407
+                plugin=self.name,
408
+                varname=LOADER_FILENAME_VARNAME)
413 409
             raise PluginError(msg)
414
-        #Path are not allowed
410
+        # Path are not allowed
415 411
         if filename != os.path.basename(filename):
416 412
             msg = "Invalid {varname} content : '{fname}' for plugin {name}"
417 413
             msg = msg.format(
@@ -419,17 +415,17 @@ name differ from the one found in plugin's init file"
419 415
                 fname=filename,
420 416
                 name=self.name)
421 417
             raise PluginError(msg)
422
-        #See the todo
418
+        # See the todo
423 419
         if len(self.module.__name__.split('.')) == 1:
424 420
             self_modname = self.module.__package__
425 421
         else:
426 422
             self_modname = self.module.__name__
427
-        #extract module name from filename
423
+        # extract module name from filename
428 424
         base_mod = '.'.join(filename.split('.')[:-1])
429
-        module_name = self_modname+"."+base_mod
425
+        module_name = self_modname + "." + base_mod
430 426
         return importlib.import_module(module_name)
431 427
 
432
-    ##@brief Return associated module name
428
+    # @brief Return associated module name
433 429
     def module_name(self):
434 430
         path_array = self.path.split('/')
435 431
         if 'plugins' not in self.path:
@@ -437,7 +433,7 @@ name differ from the one found in plugin's init file"
437 433
                 self.name, self.path))
438 434
         return '.'.join(['lodel'] + path_array[path_array.index('plugins'):])
439 435
 
440
-    ##@brief Check dependencies of plugin
436
+    # @brief Check dependencies of plugin
441 437
     #@return A list of plugin name to be loaded before
442 438
     def check_deps(self):
443 439
         try:
@@ -452,16 +448,16 @@ name differ from the one found in plugin's init file"
452 448
             except PluginError:
453 449
                 errors.append(plugin_name)
454 450
         if len(errors) > 0:
455
-            raise PluginError(  "Bad dependencie for '%s' :"%self.name,
456
-                                ', '.join(errors))
451
+            raise PluginError("Bad dependencie for '%s' :" % self.name,
452
+                              ', '.join(errors))
457 453
         return result
458 454
 
459
-    ##@brief Check if the plugin should be activated
455
+    # @brief Check if the plugin should be activated
460 456
     #
461
-    #Try to fetch a function called @ref ACTIVATE_METHOD_NAME in __init__.py
462
-    #of a plugin. If none found assert that the plugin can be loaded, else
463
-    #the method is called. If it returns anything else that True, the plugin
464
-    #is noted as not activable
457
+    # Try to fetch a function called @ref ACTIVATE_METHOD_NAME in __init__.py
458
+    # of a plugin. If none found assert that the plugin can be loaded, else
459
+    # the method is called. If it returns anything else that True, the plugin
460
+    # is noted as not activable
465 461
     #
466 462
     # @note Maybe we have to exit everything if a plugin cannot be loaded...
467 463
     def activable(self):
@@ -471,35 +467,35 @@ name differ from the one found in plugin's init file"
471 467
             msg = "No %s method found for plugin %s. Assuming plugin is ready to be loaded"
472 468
             msg %= (ACTIVATE_METHOD_NAME, self.name)
473 469
             logger.debug(msg)
474
-            test_fun = lambda:True
470
+            test_fun = lambda: True
475 471
         return test_fun()
476 472
 
477
-    ##@brief Load a plugin
473
+    # @brief Load a plugin
478 474
     #
479
-    #Loading a plugin means importing a file. The filename is defined in the
480
-    #plugin's __init__.py file in a LOADER_FILENAME_VARNAME variable.
475
+    # Loading a plugin means importing a file. The filename is defined in the
476
+    # plugin's __init__.py file in a LOADER_FILENAME_VARNAME variable.
481 477
     #
482
-    #The loading process has to take care of other things :
478
+    # The loading process has to take care of other things :
483 479
     #- loading dependencies (other plugins)
484 480
     #- check that the plugin can be activated using Plugin.activate() method
485 481
     #- avoid circular dependencies infinite loop
486 482
     def _load(self):
487 483
         if self.loaded:
488 484
             return
489
-        #Test that plugin "wants" to be activated
485
+        # Test that plugin "wants" to be activated
490 486
         activable = self.activable()
491 487
         if not(activable is True):
492 488
             msg = "Plugin %s is not activable : %s"
493 489
             msg %= (self.name, activable)
494 490
             raise PluginError(msg)
495 491
 
496
-        #Circular dependencie detection
492
+        # Circular dependencie detection
497 493
         if self.name in self._load_called:
498 494
             raise PluginError("Circular dependencie in Plugin detected. Abording")
499 495
         else:
500 496
             self._load_called.append(self.name)
501 497
 
502
-        #Dependencie load
498
+        # Dependencie load
503 499
         for dependencie in self.check_deps():
504 500
             activable = dependencie.activable()
505 501
             if activable is True:
@@ -507,11 +503,11 @@ name differ from the one found in plugin's init file"
507 503
             else:
508 504
                 msg = "Plugin {plugin_name} not activable because it depends on plugin {dep_name} that is not activable : {reason}"
509 505
                 msg = msg.format(
510
-                    plugin_name = self.name,
511
-                    dep_name = dependencie.name,
512
-                    reason = activable)
506
+                    plugin_name=self.name,
507
+                    dep_name=dependencie.name,
508
+                    reason=activable)
513 509
 
514
-        #Loading the plugin
510
+        # Loading the plugin
515 511
         try:
516 512
             self.__loader_module = self._import_from_init_var(LOADER_FILENAME_VARNAME)
517 513
         except PluginError as e:
@@ -519,24 +515,24 @@ name differ from the one found in plugin's init file"
519 515
         except ImportError as e:
520 516
             msg = "Broken plugin {plugin} : {expt}"
521 517
             msg = msg.format(
522
-                plugin = self.name,
523
-                expt = str(e))
518
+                plugin=self.name,
519
+                expt=str(e))
524 520
             raise PluginError(msg)
525 521
         logger.debug("Plugin '%s' loaded" % self.name)
526 522
         self.loaded = True
527 523
 
528
-    ##@brief Returns the loader module
524
+    # @brief Returns the loader module
529 525
     #
530
-    #Accessor for the __loader__ python module
526
+    # Accessor for the __loader__ python module
531 527
     def loader_module(self):
532 528
         if not self.loaded:
533
-            raise RuntimeError("Plugin %s not loaded yet."%self.name)
529
+            raise RuntimeError("Plugin %s not loaded yet." % self.name)
534 530
         return self.__loader_module
535 531
 
536 532
     def __str__(self):
537 533
         return "<LodelPlugin '%s' version %s>" % (self.name, self.__version)
538 534
 
539
-    ##@brief Call load method on every pre-loaded plugins
535
+    # @brief Call load method on every pre-loaded plugins
540 536
     #
541 537
     # Called by loader to trigger hooks registration.
542 538
     # This method have to avoid circular dependencies infinite loops. For this
@@ -554,21 +550,20 @@ name differ from the one found in plugin's init file"
554 550
         if len(errors) > 0:
555 551
             msg = "Errors while loading plugins :"
556 552
             for name, e in errors.items():
557
-                msg += "\n\t%20s : %s" % (name,e)
553
+                msg += "\n\t%20s : %s" % (name, e)
558 554
             msg += "\n"
559 555
             raise PluginError(msg)
560 556
         LodelHook.call_hook(
561 557
             "lodel2_plugins_loaded", cls, cls._plugin_instances)
562 558
 
563
-
564
-    ##@return a copy of __confspecs attr
559
+    # @return a copy of __confspecs attr
565 560
     @property
566 561
     def confspecs(self):
567 562
         return copy.copy(self.__confspecs)
568 563
 
569
-    ##@brief Accessor to confspec indicating where we can find the plugin list
564
+    # @brief Accessor to confspec indicating where we can find the plugin list
570 565
     #@note Abtract method implemented only for Plugin child classes
571
-    #This attribute indicate where we fetch the plugin list.
566
+    # This attribute indicate where we fetch the plugin list.
572 567
     @classmethod
573 568
     def plist_confspecs(cls):
574 569
         if cls._plist_confspecs is None:
@@ -576,11 +571,11 @@ name differ from the one found in plugin's init file"
576 571
 %s' % cls.__name__)
577 572
         return copy.copy(cls._plist_confspecs)
578 573
 
579
-    ##@brief Retrieves plugin list confspecs
574
+    # @brief Retrieves plugin list confspecs
580 575
     #
581
-    #This method ask for each Plugin child class the confspecs specifying where
582
-    #the wanted plugin list is stored. (For example DatasourcePlugin expect
583
-    #that a list of ds plugin to load stored in lodel2 section, datasources key
576
+    # This method ask for each Plugin child class the confspecs specifying where
577
+    # the wanted plugin list is stored. (For example DatasourcePlugin expect
578
+    # that a list of ds plugin to load stored in lodel2 section, datasources key
584 579
     # etc...
585 580
     @classmethod
586 581
     def plugin_list_confspec(cls):
@@ -592,7 +587,7 @@ name differ from the one found in plugin's init file"
592 587
             confspec_append(res, plcs)
593 588
         return res
594 589
 
595
-    ##@brief Register a new plugin
590
+    # @brief Register a new plugin
596 591
     #
597 592
     #@param plugin_name str : The plugin name
598 593
     #@return a Plugin instance
@@ -603,7 +598,7 @@ name differ from the one found in plugin's init file"
603 598
             msg = "Plugin allready registered with same name %s"
604 599
             msg %= plugin_name
605 600
             raise PluginError(msg)
606
-        #Here we check that previous discover found a plugin with that name
601
+        # Here we check that previous discover found a plugin with that name
607 602
         pdcache = cls.discover()
608 603
         if plugin_name not in pdcache:
609 604
             raise PluginError("No plugin named '%s' found" % plugin_name)
@@ -614,7 +609,7 @@ name differ from the one found in plugin's init file"
614 609
         logger.debug("Plugin %s available." % plugin)
615 610
         return plugin
616 611
 
617
-    ##@brief Plugins instances accessor
612
+    # @brief Plugins instances accessor
618 613
     #
619 614
     #@param plugin_name str: The plugin name
620 615
     #@return a Plugin instance
@@ -628,7 +623,7 @@ name differ from the one found in plugin's init file"
628 623
             msg %= plugin_name
629 624
             raise PluginError(msg)
630 625
 
631
-    ##@brief Given a plugin name returns the plugin path
626
+    # @brief Given a plugin name returns the plugin path
632 627
     # @param plugin_name str : The plugin name
633 628
     # @return the plugin directory path
634 629
     @classmethod
@@ -644,11 +639,11 @@ name differ from the one found in plugin's init file"
644 639
 
645 640
         return plist[plugin_name]['path']
646 641
 
647
-    ##@brief Return the plugin module name
642
+    # @brief Return the plugin module name
648 643
     #
649
-    #This module name is the "virtual" module where we imported the plugin.
644
+    # This module name is the "virtual" module where we imported the plugin.
650 645
     #
651
-    #Typically composed like VIRTUAL_PACKAGE_NAME.PLUGIN_NAME
646
+    # Typically composed like VIRTUAL_PACKAGE_NAME.PLUGIN_NAME
652 647
     #@warning Brokes subdire feature
653 648
     #@param plugin_name str : a plugin name
654 649
     #@return a string representing a module name
@@ -658,7 +653,7 @@ name differ from the one found in plugin's init file"
658 653
     def plugin_module_name(cls, plugin_name):
659 654
         return "%s.%s" % (VIRTUAL_PACKAGE_NAME, plugin_name)
660 655
 
661
-    ##@brief Start the Plugin class
656
+    # @brief Start the Plugin class
662 657
     #
663 658
     # Called by Settings.__bootstrap()
664 659
     #
@@ -668,7 +663,7 @@ name differ from the one found in plugin's init file"
668 663
         for plugin_name in plugins:
669 664
             cls.register(plugin_name)
670 665
 
671
-    ##@brief Attempt to "restart" the Plugin class
666
+    # @brief Attempt to "restart" the Plugin class
672 667
     @classmethod
673 668
     def clear(cls):
674 669
         if cls._plugin_instances != dict():
@@ -677,15 +672,15 @@ name differ from the one found in plugin's init file"
677 672
             cls._load_called = []
678 673
         MetaPlugType.clear_cls()
679 674
 
680
-    ##@brief Designed to be implemented by child classes
675
+    # @brief Designed to be implemented by child classes
681 676
     @classmethod
682 677
     def clear_cls(cls):
683 678
         pass
684 679
 
685
-    ##@brief Reccursively walk throught paths to find plugin, then stores
686
-    #found plugin in a static var
680
+    # @brief Reccursively walk throught paths to find plugin, then stores
681
+    # found plugin in a static var
687 682
     #
688
-    #Found plugins are stored in cls._plugin_list
683
+    # Found plugins are stored in cls._plugin_list
689 684
     #@note The discover is run only if no cached datas are found
690 685
     #@return a list of dict with plugin infos { see @ref _discover }
691 686
     #@todo add max_depth and no symlink following feature
@@ -695,60 +690,60 @@ name differ from the one found in plugin's init file"
695 690
             return cls._plugin_list
696 691
         logger.info("Running plugin discover")
697 692
         tmp_res = cls._discover(PLUGINS_PATH)
698
-        #Formating and dedoubloning result
693
+        # Formating and dedoubloning result
699 694
         result = dict()
700 695
         for pinfos in tmp_res:
701 696
             pname = pinfos['name']
702
-            if (    pname in result
703
-                    and pinfos['version'] > result[pname]['version'])\
704
-                or pname not in result:
697
+            if (pname in result
698
+                and pinfos['version'] > result[pname]['version'])\
699
+                    or pname not in result:
705 700
                 result[pname] = pinfos
706 701
             else:
707
-                #dropped
702
+                # dropped
708 703
                 pass
709 704
         cls._plugin_list = result
710 705
         return result
711 706
 
712
-    ##@brief Return discover result
707
+    # @brief Return discover result
713 708
     #@param refresh bool : if true invalidate all plugin list cache
714 709
     #@note If discover cache file not found run discover first
715 710
     #@note if refresh is set to True discover MUST have been run at least
716
-    #one time. In fact refresh action load the list of path to explore
717
-    #from the plugin's discover cache
711
+    # one time. In fact refresh action load the list of path to explore
712
+    # from the plugin's discover cache
718 713
     @classmethod
719
-    def plugin_list(cls, refresh = False):
714
+    def plugin_list(cls, refresh=False):
720 715
         return cls._plugin_list
721 716
 
722
-    ##@brief Return a list of child Class Plugin
717
+    # @brief Return a list of child Class Plugin
723 718
     @classmethod
724 719
     def plugin_types(cls):
725 720
         return MetaPlugType.all_types()
726 721
 
727
-    ##@brief Check if a directory is a plugin module
722
+    # @brief Check if a directory is a plugin module
728 723
     #@param path str : path to check
729 724
     #@param assert_in_package bool : if False didn't check that path is
730
-    #a subdir of PLUGINS_PATH
725
+    # a subdir of PLUGINS_PATH
731 726
     #@return a dict with name, version and path if path is a plugin module, else False
732 727
     @classmethod
733
-    def dir_is_plugin(cls, path, assert_in_package = True):
728
+    def dir_is_plugin(cls, path, assert_in_package=True):
734 729
         log_msg = "%s is not a plugin directory because : " % path
735 730
         if assert_in_package:
736
-            #Check that path is a subdir of PLUGINS_PATH
731
+            # Check that path is a subdir of PLUGINS_PATH
737 732
             abspath = os.path.abspath(path)
738 733
             if not abspath.startswith(os.path.abspath(PLUGINS_PATH)):
739 734
                 raise PluginError(
740 735
                     "%s is not a subdir of %s" % log_msg, PLUGINS_PATH)
741
-        #Checks that path exists
736
+        # Checks that path exists
742 737
         if not os.path.isdir(path):
743 738
             raise ValueError(
744 739
                 "Expected path to be a directory, but '%s' found" % path)
745
-        #Checks that path contains plugin's init file
740
+        # Checks that path contains plugin's init file
746 741
         initfile = os.path.join(path, INIT_FILENAME)
747 742
         if not os.path.isfile(initfile):
748 743
             log_msg += "'%s' not found" % (INIT_FILENAME)
749 744
             logger.debug(log_msg)
750 745
             return False
751
-        #Importing plugin's init file to check contained datas
746
+        # Importing plugin's init file to check contained datas
752 747
         try:
753 748
             initmod, modname = cls.import_init(path)
754 749
         except PluginError as e:
@@ -756,39 +751,39 @@ name differ from the one found in plugin's init file"
756 751
             log_msg %= (INIT_FILENAME, e)
757 752
             logger.debug(log_msg)
758 753
             return False
759
-        #Checking mandatory init module variables
754
+        # Checking mandatory init module variables
760 755
         for attr_name in MANDATORY_VARNAMES:
761
-            if not hasattr(initmod,attr_name):
756
+            if not hasattr(initmod, attr_name):
762 757
                 log_msg += " mandatory variable '%s' not found in '%s'"
763 758
                 log_msg %= (attr_name, INIT_FILENAME)
764 759
                 logger.debug(log_msg)
765 760
                 return False
766
-        #Fetching plugin's version
761
+        # Fetching plugin's version
767 762
         try:
768 763
             pversion = getattr(initmod, PLUGIN_VERSION_VARNAME)
769 764
         except (NameError, AttributeError) as e:
770 765
             msg = "Invalid plugin version found in %s : %s"
771 766
             msg %= (path, e)
772 767
             raise PluginError(msg)
773
-        #Fetching plugin's type
768
+        # Fetching plugin's type
774 769
         try:
775 770
             ptype = getattr(initmod, PLUGIN_TYPE_VARNAME)
776 771
         except (NameError, AttributeError) as e:
777 772
             ptype = DEFAULT_PLUGIN_TYPE
778 773
         pname = getattr(initmod, PLUGIN_NAME_VARNAME)
779 774
         return {'name': pname,
780
-            'version': PluginVersion(pversion),
781
-            'path': path,
782
-            'type': ptype}
775
+                'version': PluginVersion(pversion),
776
+                'path': path,
777
+                'type': ptype}
783 778
 
784
-    ##@brief Import init file from a plugin path
779
+    # @brief Import init file from a plugin path
785 780
     #@param path str : Directory path
786 781
     #@return a tuple (init_module, module_name)
787 782
     #@todo replace by LodelContext usage !!! (not mandatory, this fun
788
-    #is only used in plugin discover method)
783
+    # is only used in plugin discover method)
789 784
     @classmethod
790 785
     def import_init(cls, path):
791
-        cls._mod_cnt += 1 # in order to ensure module name unicity
786
+        cls._mod_cnt += 1  # in order to ensure module name unicity
792 787
         init_source = os.path.join(path, INIT_FILENAME)
793 788
         temp_module = '%s.%s.%s%d' % (
794 789
             VIRTUAL_TEMP_PACKAGE_NAME, os.path.basename(os.path.dirname(path)),
@@ -805,18 +800,18 @@ name differ from the one found in plugin's init file"
805 800
         return (res_module, temp_module)
806 801
 
807 802
     @classmethod
808
-    def debug_wrapper(cls, updglob = None):
803
+    def debug_wrapper(cls, updglob=None):
809 804
         if updglob is not None:
810 805
             for k, v in updglob.items():
811 806
                 globals()[k] = v
812 807
         print(logger)
813 808
 
814
-    ##@brief Reccursiv plugin discover given a path
809
+    # @brief Reccursiv plugin discover given a path
815 810
     #@param path str : the path to walk through
816 811
     #@return A dict with plugin_name as key and {'path':..., 'version':...} as value
817 812
     @classmethod
818 813
     def _discover(cls, path):
819
-        #Ensure plugins symlink creation
814
+        # Ensure plugins symlink creation
820 815
         LodelContext.expose_modules(globals(), {
821 816
             'lodel.plugins': 'plugins'})
822 817
         res = []
@@ -826,57 +821,60 @@ name differ from the one found in plugin's init file"
826 821
             for f in os.listdir(cur_path):
827 822
                 f_path = os.path.join(cur_path, f)
828 823
                 if f not in ['.', '..'] and os.path.isdir(f_path):
829
-                    #Check if it is a plugin directory
824
+                    # Check if it is a plugin directory
830 825
                     test_result = cls.dir_is_plugin(f_path)
831 826
                     if not (test_result is False):
832 827
                         logger.info("Plugin '%s' found in %s" % (
833
-                            test_result['name'],f_path))
828
+                            test_result['name'], f_path))
834 829
                         res.append(test_result)
835 830
                     else:
836 831
                         to_explore.append(f_path)
837 832
         return res
838 833
 
834
+
839 835
 def debug_wrapper_mod():
840
-    print("MOD : ",logger)
836
+    print("MOD : ", logger)
841 837
 
842
-##@brief Decorator class designed to allow plugins to add custom methods
843
-#to LeObject childs (dyncode objects)
838
+# @brief Decorator class designed to allow plugins to add custom methods
839
+# to LeObject childs (dyncode objects)
844 840
 #@ingroup lodel2_plugins
845 841
 #
842
+
843
+
846 844
 class CustomMethod(object):
847
-    ##@brief Stores registered custom methods
845
+    # @brief Stores registered custom methods
848 846
     #
849
-    #Key = LeObject child class name
850
-    #Value = CustomMethod instance
847
+    # Key = LeObject child class name
848
+    # Value = CustomMethod instance
851 849
     _custom_methods = dict()
852 850
 
853 851
     INSTANCE_METHOD = 0
854 852
     CLASS_METHOD = 1
855 853
     STATIC_METHOD = 2
856 854
 
857
-    ##@brief Decorator constructor
855
+    # @brief Decorator constructor
858 856
     #@param component_name str : the name of the component to enhance
859 857
     #@param method_name str : the name of the method to inject (if None given
860 858
     #@param method_type int : take value in one of
861
-    #CustomMethod::INSTANCE_METHOD CustomMethod::CLASS_METHOD or
862
-    #CustomMethod::STATIC_METHOD
863
-    #use the function name
864
-    def __init__(self, component_name, method_name = None, method_type=0):
865
-        ##@brief The targeted LeObject child class
859
+    # CustomMethod::INSTANCE_METHOD CustomMethod::CLASS_METHOD or
860
+    # CustomMethod::STATIC_METHOD
861
+    # use the function name
862
+    def __init__(self, component_name, method_name=None, method_type=0):
863
+        # @brief The targeted LeObject child class
866 864
         self._comp_name = component_name
867
-        ##@brief The method name
865
+        # @brief The method name
868 866
         self._method_name = method_name
869
-        ##@brief The function (that will be the injected method)
867
+        # @brief The function (that will be the injected method)
870 868
         self._fun = None
871
-        ##@brief Stores the type of method (instance, class or static)
869
+        # @brief Stores the type of method (instance, class or static)
872 870
         self._type = int(method_type)
873
-        if self._type not in (self.INSTANCE_METHOD, self.CLASS_METHOD,\
874
-            self.STATIC_METHOD):
871
+        if self._type not in (self.INSTANCE_METHOD, self.CLASS_METHOD,
872
+                              self.STATIC_METHOD):
875 873
             raise ValueError("Excepted value for method_type was one of \
876 874
 CustomMethod::INSTANCE_METHOD CustomMethod::CLASS_METHOD or \
877 875
 CustomMethod::STATIC_METHOD, but got %s" % self._type)
878 876
 
879
-    ##@brief called just after __init__
877
+    # @brief called just after __init__
880 878
     #@param fun function : the decorated function
881 879
     def __call__(self, fun):
882 880
         if self._method_name is None:
@@ -884,7 +882,7 @@ CustomMethod::STATIC_METHOD, but got %s" % self._type)
884 882
         if self._comp_name not in self._custom_methods:
885 883
             self._custom_methods[self._comp_name] = list()
886 884
 
887
-        if self._method_name in [ scm._method_name for scm in self._custom_methods[self._comp_name]]:
885
+        if self._method_name in [scm._method_name for scm in self._custom_methods[self._comp_name]]:
888 886
             raise RuntimeError("A method named %s allready registered by \
889 887
 another plugin : %s" % (
890 888
                 self._method_name,
@@ -892,24 +890,24 @@ another plugin : %s" % (
892 890
         self._fun = fun
893 891
         self._custom_methods[self._comp_name].append(self)
894 892
 
895
-    ##@brief Textual representation
893
+    # @brief Textual representation
896 894
     #@return textual representation of the CustomMethod instance
897 895
     def __repr__(self):
898 896
         res = "<CustomMethod name={method_name} target={classname} \
899 897
 source={module_name}.{fun_name}>"
900 898
         return res.format(
901
-            method_name = self._method_name,
902
-            classname = self._comp_name,
903
-            module_name = self._fun.__module__,
904
-            fun_name = self._fun.__name__)
899
+            method_name=self._method_name,
900
+            classname=self._comp_name,
901
+            module_name=self._fun.__module__,
902
+            fun_name=self._fun.__name__)
905 903
 
906
-    ##@brief Return a well formed method
904
+    # @brief Return a well formed method
907 905
     #
908 906
     #@note the type of method depends on the _type attribute
909 907
     #@return a method directly injectable in the target class
910 908
     def __get_method(self):
911 909
         if self._type == self.INSTANCE_METHOD:
912
-            def custom__get__(self, obj, objtype = None):
910
+            def custom__get__(self, obj, objtype=None):
913 911
                 return types.MethodType(self, obj, objtype)
914 912
             setattr(self._fun, '__get__', custom__get__)
915 913
             return self._fun
@@ -922,18 +920,18 @@ source={module_name}.{fun_name}>"
922 920
 CustomMethod::INSTANCE_METHOD CustomMethod::CLASS_METHOD \
923 921
 CustomMethod::STATIC_METHOD")
924 922
 
925
-    ##@brief Handle custom method dynamic injection in LeAPI dyncode
923
+    # @brief Handle custom method dynamic injection in LeAPI dyncode
926 924
     #
927
-    #Called by lodel2_dyncode_loaded hook defined at
928
-    #lodel.plugin.core_hooks.lodel2_plugin_custom_methods()
925
+    # Called by lodel2_dyncode_loaded hook defined at
926
+    # lodel.plugin.core_hooks.lodel2_plugin_custom_methods()
929 927
     #
930 928
     #@param cls
931 929
     #@param dynclasses LeObject child classes : List of dynamically generated
932
-    #LeObject child classes
930
+    # LeObject child classes
933 931
     @classmethod
934 932
     def set_registered(cls, dynclasses):
935 933
         from lodel import logger
936
-        dyn_cls_dict = { dc.__name__:dc for dc in dynclasses}
934
+        dyn_cls_dict = {dc.__name__: dc for dc in dynclasses}
937 935
         for cls_name, custom_methods in cls._custom_methods.items():
938 936
             for custom_method in custom_methods:
939 937
                 if cls_name not in dyn_cls_dict:
@@ -950,5 +948,6 @@ with %s" % (custom_method._method_name, custom_method))
950 948
                     logger.debug(
951 949
                         "Custom method %s added to target" % custom_method)
952 950
 
951
+
953 952
 def wrapper_debug_fun():
954 953
     print(logger)

Loading…
Cancel
Save