Browse Source

Delete is_exist

prieto 7 years ago
parent
commit
cdd13d9b4b

+ 109
- 101
lodel/auth/client.py View File

@@ -11,243 +11,251 @@ LodelContext.expose_modules(globals(), {
11 11
     'lodel.logger': 'logger',
12 12
     'lodel.plugin': [('SessionHandlerPlugin', 'SessionHandler')],
13 13
     'lodel.auth.exceptions': ['ClientError', 'ClientAuthenticationFailure',
14
-        'ClientPermissionDenied', 'ClientAuthenticationError'],
15
-    'lodel.leapi.query': ['LeGetQuery'],})
14
+                              'ClientPermissionDenied', 'ClientAuthenticationError'],
15
+    'lodel.leapi.query': ['LeGetQuery'], })
16 16
 
17
-##@brief Client metaclass designed to implements container accessor on 
18
-#Client Class
17
+# @brief Client metaclass designed to implements container accessor on
18
+# Client Class
19 19
 #
20 20
 #@todo Maybe we can delete this metaclass....
21
+
22
+
21 23
 class ClientMetaclass(type):
22
-    
24
+
23 25
     def __init__(self, name, bases, attrs):
24 26
         return super(ClientMetaclass, self).__init__(name, bases, attrs)
25 27
 
26 28
     def __getitem__(self, key):
27
-        return self.datas()[key]
29
+        return self.data()[key]
28 30
 
29 31
     def __delitem__(self, key):
30
-        del(self.datas()[key])
32
+        del(self.data()[key])
31 33
 
32 34
     def __setitem__(self, key, value):
33 35
         if self.get_session_token() is None:
34 36
             self.set_session_token(SessionHandler.start())
35
-        datas = self.datas()
36
-        datas[key] = value
37
+        data = self.data()
38
+        data[key] = value
37 39
 
38 40
     def __str__(self):
39 41
         return str(self._instance)
40 42
 
41
-##@brief Abstract singleton class designed to handle client informations
43
+# @brief Abstract singleton class designed to handle client informations
42 44
 #
43 45
 # This class is designed to handle client authentication and sessions
44
-class Client(object, metaclass = ClientMetaclass):
45
-    
46
-    ##@brief Singleton instance
46
+
47
+
48
+class Client(object, metaclass=ClientMetaclass):
49
+
50
+    # @brief Singleton instance
47 51
     _instance = None
48
-    ##@brief List of dict that stores field ref for login and password
52
+    # @brief List of dict that stores field ref for login and password
49 53
     #
50
-    # Storage specs : 
54
+    # Storage specs :
51 55
     #
52 56
     # A list of dict, with keys 'login' and 'password', items are tuple.
53
-    #- login tuple contains (LeObjectChild, FieldName, link_field) with:
57
+    # - login tuple contains (LeObjectChild, FieldName, link_field) with:
54 58
     # - LeObjectChild the dynclass containing the login
55 59
     # - Fieldname the fieldname of LeObjectChild containing the login
56 60
     # - link_field None if both login and password are in the same
57 61
     # LeObjectChild. Else contains the field that make the link between
58 62
     # login LeObject and password LeObject
59
-    #- password typle contains (LeObjectChild, FieldName)
63
+    # - password typle contains (LeObjectChild, FieldName)
60 64
     _infos_fields = None
61
-    
62
-    ##@brief Constant that stores the session key that stores authentication
63
-    #informations
65
+
66
+    # @brief Constant that stores the session key that stores authentication
67
+    # informations
64 68
     _AUTH_DATANAME = '__auth_user_infos'
65
-    
66 69
 
67
-    ##@brief Constructor
70
+    # @brief Constructor
68 71
     #@param session_token mixed : Session token provided by client to interface
69
-    def __init__(self,session_token = None):
72
+    def __init__(self, session_token=None):
70 73
         logger.debug(session_token)
71 74
         if self.__class__ == Client:
72 75
             raise NotImplementedError("Abstract class")
73 76
         logger.debug("New instance of Client child class %s" %
74
-            self.__class__.__name__)
77
+                     self.__class__.__name__)
75 78
         if Client._instance is not None:
76 79
             old = Client._instance
77 80
             Client._instance = None
78 81
             del(old)
79 82
             logger.debug("Replacing old Client instance by a new one")
80 83
         else:
81
-            #first instanciation, fetching settings
84
+            # first instanciation, fetching settings
82 85
             self.fetch_settings()
83
-        ##@brief Stores infos for authenticated users (None == anonymous)
86
+        # @brief Stores infos for authenticated users (None == anonymous)
84 87
         self.__user = None
85
-        ##@brief Stores the session handler
88
+        # @brief Stores the session handler
86 89
         Client._instance = self
87
-        ##@brief Stores LodelSession instance
88
-        
89
-        self.__datas = dict()
90
+        # @brief Stores LodelSession instance
91
+        self.__data = dict()
90 92
         if session_token is not None:
91
-            self.__datas = SessionHandler.restore(session_token)
93
+            self.__data = SessionHandler.restore(session_token)
92 94
         self.__session_token = session_token
93
-        
95
+
94 96
         logger.debug("New client : %s" % self)
95
-    
97
+
96 98
     def __del__(self):
97 99
         del(self.__session_token)
98
-        del(self.__datas)
100
+        del(self.__data)
101
+    # @brief Returns session
102
+    #@ returns the dict which stores session
99 103
 
100 104
     @classmethod
101
-    def datas(cls):
102
-        return cls._instance.__datas
103
-    
105
+    def data(cls):
106
+        return cls._instance.__data
107
+
108
+    # @brief Returns the user's information contained in the session's data
104 109
     @classmethod
105 110
     def user(cls):
106
-        if '__auth_user_infos' in cls._instance.__datas:
107
-            return cls._instance.__datas['__auth_user_infos']
111
+        if '__auth_user_infos' in cls._instance.__data:
112
+            return cls._instance.__data['__auth_user_infos']
108 113
         else:
109 114
             return None
115
+
116
+    # @brief Returns the session's token
110 117
     @classmethod
111 118
     def get_session_token(cls):
112 119
         return cls._instance.__session_token
113
-    
120
+
121
+    # @brief Set the session's token
122
+    #@param the value of the token
114 123
     @classmethod
115 124
     def set_session_token(cls, value):
116 125
         cls._instance.__session_token = value
117
-    
118
-    ##@brief Try to authenticate a user with a login and a password
126
+
127
+    # @brief Try to authenticate a user with a login and a password
119 128
     #@param login str : provided login
120 129
     #@param password str : provided password (hash)
121 130
     #@warning brokes composed UID
122
-    #@note implemets multiple login/password sources (useless ?)
131
+    #@note implements multiple login/password sources (useless ?)
123 132
     #@todo composed UID broken method
124 133
     #@todo allow to provide an authentication source
125 134
     @classmethod
126
-    def authenticate(self, login = None, password = None):
127
-        #Authenticate
135
+    def authenticate(self, login=None, password=None):
136
+        # Authenticate
128 137
         for infos in self._infos_fields:
129 138
             logger.debug(self._infos_fields)
130 139
             login_cls = infos['login'][0]
131 140
             pass_cls = infos['password'][0]
132 141
             qfilter = "{passfname} = {passhash}"
133
-            uid_fname = login_cls.uid_fieldname()[0] #COMPOSED UID BROKEN
142
+            uid_fname = login_cls.uid_fieldname()[0]  # COMPOSED UID BROKEN
134 143
             if login_cls == pass_cls:
135
-                #Same EmClass for login & pass
144
+                # Same EmClass for login & pass
136 145
                 qfilter = qfilter.format(
137
-                    passfname = infos['password'][1],
138
-                    passhash = password)
146
+                    passfname=infos['password'][1],
147
+                    passhash=password)
139 148
             else:
140
-                #Different EmClass, building a relational filter
149
+                # Different EmClass, building a relational filter
141 150
                 passfname = "%s.%s" % (infos['login'][2], infos['password'][1])
142 151
                 qfilter = qfilter.format(
143
-                    passfname = passfname,
144
-                    passhash = password)
152
+                    passfname=passfname,
153
+                    passhash=password)
145 154
             getq = LeGetQuery(infos['login'][0], qfilter,
146
-                field_list = [uid_fname], limit = 1)
155
+                              field_list=[uid_fname], limit=1)
147 156
             req = getq.execute()
148 157
             if len(req) == 1:
149
-                self.__set_authenticated(infos['login'][0],req[0][uid_fname])
158
+                self.__set_authenticated(infos['login'][0], req[0][uid_fname])
150 159
                 break
151 160
         if self.is_anonymous():
152
-            self.authentication_failure() #Security logging
153
-    
154
-    ##@brief Attempt to restore a session given a session token
161
+            self.authentication_failure()  # Security logging
162
+
163
+    # @brief Attempt to restore a session given a session token
155 164
     #@param token mixed : a session token
156
-    #@return Session datas (a dict)
165
+    #@return Session data (a dict)
157 166
     #@throw ClientAuthenticationFailure if token is not valid or not
158
-    #existing
167
+    # existing
159 168
     @classmethod
160 169
     def restore_session(cls, token):
161 170
         cls._assert_instance()
162 171
         if cls._instance.__session_token is not None:
163 172
             raise ClientAuthenticationError("Trying to restore a session, but \
164
-a session is allready started !!!")
173
+a session is already started !!!")
165 174
         try:
166
-            cls._instance.__datas = SessionHandler.restore(token)
175
+            cls._instance.__data = SessionHandler.restore(token)
167 176
             cls._instance.__session_token = token
168 177
         except ClientAuthenticationFailure:
169
-            logger.warning("Session restoring fails")
170
-        return copy.copy(cls._instance.datas)
171
-    
172
-    ##@brief Return the current session token or None
178
+            logger.warning("Session restoring failed")
179
+        return copy.copy(cls._instance.data)
180
+
181
+    # @brief Returns the current session token or None
173 182
     #@return A session token or None
174 183
     @classmethod
175 184
     def session_token(cls):
176 185
         cls._assert_instance()
177 186
         return cls._instance.__session_token
178 187
 
179
-   
180
-    ##@brief Delete current session
188
+    # @brief Deletes current session
181 189
     @classmethod
182 190
     def destroy(cls):
183 191
         cls._assert_instance()
184 192
         SessionHandler.destroy(cls._instance.__session_token)
185 193
         cls._instance.__session_token = None
186
-        cls._instance.__datas = dict()
187
-    
188
-    ##@brief Delete current client and save its session
194
+        cls._instance.__data = dict()
195
+
196
+    # @brief Deletes current client and saves its session
189 197
     @classmethod
190 198
     def clean(cls):
191 199
         if cls._instance.__session_token is not None:
192
-            SessionHandler.save(cls._instance.__session_token, cls._instance.__datas)
200
+            SessionHandler.save(cls._instance.__session_token, cls._instance.__data)
193 201
         if Client._instance is not None:
194 202
             del(Client._instance)
195 203
         Client._instance = None
196
-    
197
-    ##@brief Test wether a client is anonymous or logged in
204
+
205
+    # @brief Tests if a client is anonymous or logged in
198 206
     #@return True if client is anonymous
199 207
     @classmethod
200 208
     def is_anonymous(cls):
201 209
         return Client._instance.user() is None
202
-        
203
-    ##@brief Method to call on authentication failure
210
+
211
+    # @brief Method to be called on authentication failure
204 212
     #@throw ClientAuthenticationFailure
205
-    #@throw LodelFatalError if no Client child instance found
213
+    #@throw LodelFatalError if no Client child instance is found
206 214
     @classmethod
207 215
     def authentication_failure(cls):
208 216
         cls._generic_error(ClientAuthenticationFailure)
209
-    
210
-    ##@brief Method to call on authentication error
217
+
218
+    # @brief Method to be called on authentication error
211 219
     #@throw ClientAuthenticationError
212
-    #@throw LodelFatalError if no Client child instance found
220
+    #@throw LodelFatalError if no Client child instance is found
213 221
     @classmethod
214
-    def authentication_error(cls, msg = "Unknow error"):
222
+    def authentication_error(cls, msg="Unknow error"):
215 223
         cls._generic_error(ClientAuthenticationError, msg)
216 224
 
217
-    ##@brief Method to call on permission denied error
225
+    # @brief Method to be called on permission denied error
218 226
     #@throw ClientPermissionDenied
219
-    #@throw LodelFatalError if no Client child instance found
227
+    #@throw LodelFatalError if no Client child instance is found
220 228
     @classmethod
221
-    def permission_denied_error(cls, msg = ""):
229
+    def permission_denied_error(cls, msg=""):
222 230
         cls._generic_error(ClientPermissionDenied, msg)
223
-    
224
-    ##@brief Generic error method
231
+
232
+    # @brief Generic error method
225 233
     #@see Client::authentication_failure() Client::authentication_error()
226
-    #Client::permission_denied_error()
227
-    #@throw LodelFatalError if no Client child instance found
234
+    # Client::permission_denied_error()
235
+    #@throw LodelFatalError if no Client child instance is found
228 236
     @classmethod
229
-    def _generic_error(cls, expt, msg = ""):
237
+    def _generic_error(cls, expt, msg=""):
230 238
         cls._assert_instance()
231 239
         raise expt(Client._instance, msg)
232
-    
233
-    ##@brief Assert that an instance of Client child class exists
234
-    #@throw LodelFataError if no instance of Client child class found
240
+
241
+    # @brief Asserts that an instance of Client child class exists
242
+    #@throw LodelFataError if no instance of Client child class is found
235 243
     @classmethod
236 244
     def _assert_instance(cls):
237 245
         if Client._instance is None:
238 246
             raise LodelFatalError("No client instance found. Abording.")
239 247
 
240
-    ##@brief Class method that fetches conf
248
+    # @brief Class method that fetches conf
241 249
     #
242
-    #This method populates Client._infos_fields . This attribute stores
243
-    #informations on login and password location (LeApi object & field)
250
+    # This method populates Client._infos_fields . This attribute stores
251
+    # informations on login and password location (LeApi object & field)
244 252
     @classmethod
245 253
     def fetch_settings(cls):
246 254
         LodelContext.expose_dyncode(globals(), 'dyncode')
247 255
         if cls._infos_fields is None:
248 256
             cls._infos_fields = list()
249 257
         else:
250
-            #Allready fetched
258
+            # Already fetched
251 259
             return
252 260
         infos = (
253 261
             Settings.auth.login_classfield,
@@ -266,21 +274,21 @@ a session is allready started !!!")
266 274
                 if fdh.is_reference() and res_infos[1][0] in fdh.linked_classes():
267 275
                     link_field = fname
268 276
             if link_field is None:
269
-                #Unable to find link between login & password EmClasses
277
+                # Unable to find link between login & password EmClass
270 278
                 raise AuthenticationError("Unable to find a link between \
271 279
 login EmClass '%s' and password EmClass '%s'. Abording..." % (
272 280
                     res_infos[0][0], res_infos[1][0]))
273 281
         res_infos[0] = (res_infos[0][0], res_infos[0][1], link_field)
274 282
         cls._infos_fields.append(
275
-            {'login':res_infos[0], 'password':res_infos[1]})
283
+            {'login': res_infos[0], 'password': res_infos[1]})
276 284
 
277
-    ##@brief Set a user as authenticated and start a new session
285
+    # @brief Sets a user as authenticated and starts a new session
278 286
     #@param leo LeObject child class : the LeObject the user is stored in
279 287
     #@param uid str : uniq id (in leo)
280 288
     #@return None
281 289
     @classmethod
282 290
     def __set_authenticated(cls, leo, uid):
283 291
         cls._instance.__user = {'classname': leo.__name__, 'uid': uid, 'leoclass': leo}
284
-        #Store auth infos in session
285
-        cls._instance.__datas[cls._instance.__class__._AUTH_DATANAME] = copy.copy(cls._instance.__user)
286
-
292
+        # Store auth infos in session
293
+        cls._instance.__data[cls._instance.__class__._AUTH_DATANAME] = copy.copy(
294
+            cls._instance.__user)

+ 34
- 29
lodel/editorial_model/components.py View File

@@ -36,11 +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 40
     def __str__(self):
40 41
         if self.display_name is None:
41 42
             return str(self.uid)
42 43
         return str(self.display_name)
43 44
 
45
+    # @brief Returns a hash code for the component
44 46
     def d_hash(self):
45 47
         m = hashlib.md5()
46 48
         for data in (
@@ -57,7 +59,7 @@ class EmComponent(MlNamedObject):
57 59
 #@ingroup lodel2_em
58 60
 class EmClass(EmComponent):
59 61
 
60
-    # @brief Instanciate a new EmClass
62
+    # @brief Instanciates a new EmClass
61 63
     #@param uid str : uniq identifier
62 64
     #@param display_name MlString|str|dict : component display_name
63 65
     #@param abstract bool : set the class as asbtract if True
@@ -78,7 +80,7 @@ class EmClass(EmComponent):
78 80
         self.pure_abstract = bool(pure_abstract)
79 81
         self.__datasource = datasources
80 82
         if not isinstance(datasources, str) and len(datasources) != 2:
81
-            raise ValueError("datasources arguement can be a single datasource\
83
+            raise ValueError("datasources argument can be a single datasource\
82 84
  name or two names in a tuple or a list")
83 85
         if self.pure_abstract:
84 86
             self.abtract = True
@@ -115,8 +117,9 @@ class EmClass(EmComponent):
115 117
                 internal=True,
116 118
                 group=group)
117 119
 
118
-    # @brief Property that represent a dict of all fields (the EmField defined in this class and all its parents)
119
-    # @todo use Settings.editorialmodel.groups to determine wich fields should be returned
120
+    # @brief Property that represents a dict of all fields 
121
+    # (the EmField objects defined in this class and all their parents)
122
+    # @todo use Settings.editorialmodel.groups to determine which fields should be returned
120 123
     @property
121 124
     def __all_fields(self):
122 125
         res = dict()
@@ -130,9 +133,9 @@ class EmClass(EmComponent):
130 133
     def datasource(self):
131 134
         return self.__datasource
132 135
 
133
-    # @brief Return the list of all dependencies
136
+    # @brief Returns the list of all dependencies
134 137
     #
135
-    # Reccursive parents listing
138
+    # Recursive parents listing
136 139
     @property
137 140
     def parents_recc(self):
138 141
         if len(self.parents) == 0:
@@ -155,7 +158,7 @@ class EmClass(EmComponent):
155 158
         except KeyError:
156 159
             raise EditorialModelError("No such EmField '%s'" % uid)
157 160
 
158
-    # @brief Keep in __fields only fields contained in active groups
161
+    # @brief Keeps in __fields only fields contained in active groups
159 162
     def _set_active_fields(self, active_groups):
160 163
         if not Settings.editorialmodel.editormode:
161 164
             active_fields = []
@@ -165,10 +168,10 @@ class EmClass(EmComponent):
165 168
             self.__fields = {fname: fdh for fname, fdh in self.__fields.items()
166 169
                              if fdh in active_fields}
167 170
 
168
-    # @brief Add a field to the EmClass
171
+    # @brief Adds a field to the EmClass
169 172
     # @param emfield EmField : an EmField instance
170
-    # @warning do not add an EmField allready in another class !
171
-    # @throw EditorialModelException if an EmField with same uid allready in this EmClass (overwritting allowed from parents)
173
+    # @warning do not add an EmField already in another class !
174
+    # @throw EditorialModelException if an EmField with same uid already in this EmClass (overwriting allowed from parents)
172 175
     # @todo End the override checks (needs methods in data_handlers)
173 176
     def add_field(self, emfield):
174 177
         assert_edit()
@@ -180,11 +183,11 @@ class EmClass(EmComponent):
180 183
             parent_field = self.__all_fields[emfield.uid]
181 184
             if not emfield.data_handler_instance.can_override(parent_field.data_handler_instance):
182 185
                 raise AttributeError(
183
-                    "'%s' field override a parent field, but data_handles are not compatible" % emfield.uid)
186
+                    "'%s' field overrides a parent field, but data_handlers are not compatible" % emfield.uid)
184 187
         self.__fields[emfield.uid] = emfield
185 188
         return emfield
186 189
 
187
-    # @brief Create a new EmField and add it to the EmClass
190
+    # @brief Creates a new EmField and adds it to the EmClass
188 191
     # @param data_handler str : A DataHandler name
189 192
     # @param uid str : the EmField uniq id
190 193
     # @param **field_kwargs :  EmField constructor parameters ( see @ref EmField.__init__() )
@@ -221,7 +224,7 @@ class EmClass(EmComponent):
221 224
 #@ingroup lodel2_em
222 225
 class EmField(EmComponent):
223 226
 
224
-    # @brief Instanciate a new EmField
227
+    # @brief Instanciates a new EmField
225 228
     # @param uid str : uniq identifier
226 229
     # @param display_name MlString|str|dict : field display_name
227 230
     # @param data_handler str : A DataHandler name
@@ -256,7 +259,7 @@ class EmField(EmComponent):
256 259
     def get_data_handler_cls(self):
257 260
         return copy.copy(self.data_handler_cls)
258 261
 
259
-    ##@brief Returne the uid of the emclass which contains this field
262
+    ##@brief Returns the uid of the emclass which contains this field
260 263
     def get_emclass_uid(self):
261 264
         return self._emclass.uid
262 265
 
@@ -277,7 +280,7 @@ class EmField(EmComponent):
277 280
 
278 281
 class EmGroup(MlNamedObject):
279 282
 
280
-    # @brief Create a new EmGroup
283
+    # @brief Creates a new EmGroup
281 284
     # @note you should NEVER call the constructor yourself. Use Model.add_group instead
282 285
     # @param uid str : Uniq identifier
283 286
     # @param depends list : A list of EmGroup dependencies
@@ -297,10 +300,10 @@ class EmGroup(MlNamedObject):
297 300
             for grp in depends:
298 301
                 if not isinstance(grp, EmGroup):
299 302
                     raise ValueError("EmGroup expected in depends argument but %s found" % grp)
300
-                self.add_dependencie(grp)
303
+                self.add_dependency(grp)
301 304
 
302
-    # @brief Returns EmGroup dependencie
303
-    # @param recursive bool : if True return all dependencies and their dependencies
305
+    # @brief Returns EmGroup dependencies
306
+    # @param recursive bool : if True returns all dependencies and their own dependencies
304 307
     # @return a dict of EmGroup identified by uid
305 308
     def dependencies(self, recursive=False):
306 309
         res = copy.copy(self.require)
@@ -316,7 +319,7 @@ class EmGroup(MlNamedObject):
316 319
         return res
317 320
 
318 321
     # @brief Returns EmGroup applicants
319
-    # @param recursive bool : if True return all dependencies and their dependencies
322
+    # @param recursive bool : if True returns all dependencies and their dependencies
320 323
     # @returns a dict of EmGroup identified by uid
321 324
     def applicants(self, recursive=False):
322 325
         res = copy.copy(self.required_by)
@@ -337,7 +340,7 @@ class EmGroup(MlNamedObject):
337 340
         return (self.__components).copy()
338 341
 
339 342
     # @brief Returns EmGroup display_name
340
-    #  @param lang str | None : If None return default lang translation
343
+    #  @param lang str | None : If None returns default lang translation
341 344
     #  @returns None if display_name is None, a str for display_name else
342 345
     def get_display_name(self, lang=None):
343 346
         name = self.display_name
@@ -346,7 +349,7 @@ class EmGroup(MlNamedObject):
346 349
         return name.get(lang)
347 350
 
348 351
     # @brief Returns EmGroup help_text
349
-    #  @param lang str | None : If None return default lang translation
352
+    #  @param lang str | None : If None returns default lang translation
350 353
     #  @returns None if display_name is None, a str for display_name else
351 354
     def get_help_text(self, lang=None):
352 355
         help = self.help_text
@@ -354,7 +357,7 @@ class EmGroup(MlNamedObject):
354 357
             return None
355 358
         return help.get(lang)
356 359
 
357
-    # @brief Add components in a group
360
+    # @brief Adds components in a group
358 361
     # @param components list : EmComponent instances list
359 362
     def add_components(self, components):
360 363
         assert_edit()
@@ -369,20 +372,20 @@ class EmGroup(MlNamedObject):
369 372
                     "Expecting components to be a list of EmComponent, but %s found in the list" % type(component))
370 373
         self.__components |= set(components)
371 374
 
372
-    # @brief Add a dependencie
373
-    # @param em_group EmGroup|iterable : an EmGroup instance or list of instance
374
-    def add_dependencie(self, grp):
375
+    # @brief Add a dependency
376
+    # @param em_group EmGroup|iterable : an EmGroup instance or list of instances
377
+    def add_dependency(self, grp):
375 378
         assert_edit()
376 379
         try:
377 380
             for group in grp:
378
-                self.add_dependencie(group)
381
+                self.add_dependency(group)
379 382
             return
380 383
         except TypeError:
381 384
             pass
382 385
 
383 386
         if grp.uid in self.require:
384 387
             return
385
-        if self.__circular_dependencie(grp):
388
+        if self.__circular_dependency(grp):
386 389
             raise EditorialModelError("Circular dependencie detected, cannot add dependencie")
387 390
         self.require[grp.uid] = grp
388 391
         grp.required_by[self.uid] = self
@@ -406,9 +409,9 @@ class EmGroup(MlNamedObject):
406 409
         self.required_by[grp.uid] = grp
407 410
         grp.require[self.uid] = self
408 411
 
409
-    # @brief Search for circular dependencie
412
+    # @brief Search for circular dependency
410 413
     # @return True if circular dep found else False
411
-    def __circular_dependencie(self, new_dep):
414
+    def __circular_dependency(self, new_dep):
412 415
         return self.uid in new_dep.dependencies(True)
413 416
 
414 417
     # @brief Search for circular applicant
@@ -424,6 +427,8 @@ class EmGroup(MlNamedObject):
424 427
         else:
425 428
             return self.display_name.get()
426 429
 
430
+    # @brief Computes a d-hash code for the EmGroup
431
+    # @return a string
427 432
     def d_hash(self):
428 433
 
429 434
         payload = "%s%s%s" % (

+ 12
- 6
lodel/editorial_model/model.py View File

@@ -42,7 +42,8 @@ class EditorialModel(MlNamedObject):
42 42
         super().__init__(display_name, help_text)
43 43
 
44 44
     # @brief EmClass uids accessor
45
-    #@return a dict of emclasses
45
+    #@return a copy of the dict containing all emclasses of the model if uid is None
46
+    # else a copy the class with uid uid
46 47
     def all_classes(self, uid=None):
47 48
         if uid is None:
48 49
             return copy.copy(self.__classes)
@@ -52,6 +53,9 @@ class EditorialModel(MlNamedObject):
52 53
             except KeyError:
53 54
                 raise EditorialModelException("EmClass not found : '%s'" % uid)
54 55
 
56
+    # @brief EmClass uids accessor
57
+    #@return the dict containing all emclasses of the model if uid is None
58
+    # else the class with uid uid
55 59
     def all_classes_ref(self, uid=None):
56 60
         if uid is None:
57 61
             return self.__classes
@@ -62,12 +66,13 @@ class EditorialModel(MlNamedObject):
62 66
                 raise EditorialModelException("EmGroup not found : '%s'" % uid)
63 67
 
64 68
     # @brief active EmClass uids accessor
65
-    #@return a list of class uids
69
+    #@return a list of active class uids
66 70
     def active_classes_uids(self):
67 71
         return list(self.__active_classes.keys())
68 72
 
69 73
     # @brief EmGroups accessor
70
-    #@return a dict of groups
74
+    #@return a copy of the dict of the model's group if uid is None
75
+    # else a copy of the group with uniq id uid
71 76
     def all_groups(self, uid=None):
72 77
         if uid is None:
73 78
             return copy.copy(self.__groups)
@@ -78,7 +83,8 @@ class EditorialModel(MlNamedObject):
78 83
                 raise EditorialModelException("EmGroup not found : '%s'" % uid)
79 84
 
80 85
     # @brief EmGroups accessor
81
-    #@return a dict of groups
86
+    #@return the dict of the model's group if uid is None
87
+    # else the group with uniq id uid
82 88
     def all_groups_ref(self, uid=None):
83 89
         if uid is None:
84 90
             return self.__groups
@@ -89,7 +95,7 @@ class EditorialModel(MlNamedObject):
89 95
                 raise EditorialModelException("EmGroup not found : '%s'" % uid)
90 96
 
91 97
     # @brief active EmClass uids accessor
92
-    #@return a list of class uids
98
+    #@return a list of active group uids
93 99
     def active_groups_uids(self):
94 100
         return list(self.__active_groups.keys())
95 101
 
@@ -97,7 +103,7 @@ class EditorialModel(MlNamedObject):
97 103
     #@param uid None | str : give this argument to get a specific EmClass
98 104
     #@return if uid is given returns an EmClass else returns an EmClass
99 105
     # iterator
100
-    #@todo use Settings.editorialmodel.groups to determine wich classes should
106
+    #@todo use Settings.editorialmodel.groups to determine which classes should
101 107
     # be returned
102 108
     def classes(self, uid=None):
103 109
         try:

+ 1
- 1
lodel/editorial_model/translator/xmlfile.py View File

@@ -460,7 +460,7 @@ def load_group_xml(model, elem):
460 460
         group = model.all_groups_ref(uid.text)
461 461
         group.display_name = name
462 462
         group.help_text = help_text
463
-        group.add_dependencie(requires)
463
+        group.add_dependency(requires)
464 464
     else:
465 465
         group = EmGroup(uid.text, requires, name, help_text)
466 466
 

+ 2
- 0
lodel/leapi/datahandlers/exceptions.py View File

@@ -1,3 +1,5 @@
1
+## @brief Exception classes for datahandlers
2
+
1 3
 class LodelDataHandlerException(Exception):
2 4
     pass
3 5
 

+ 6
- 2
lodel/leapi/datahandlers/references.py View File

@@ -9,12 +9,13 @@ LodelContext.expose_modules(globals(), {
9 9
                          'LodelFatalError', 'DataNoneValid',
10 10
                          'FieldValidationError']})
11 11
 
12
-
12
+## @brief Child class of SingleRef. The object referenced must exist
13 13
 class Link(SingleRef):
14 14
     pass
15 15
 
16 16
 
17 17
 ## @brief Child class of MultipleRef where references are represented in the form of a python list
18
+# All the objects referenced must exist
18 19
 class List(MultipleRef):
19 20
 
20 21
     ## @brief instanciates a list reference
@@ -97,13 +98,16 @@ class Map(MultipleRef):
97 98
 
98 99
 ## @brief This Reference class is designed to handler hierarchy with some constraint
99 100
 class Hierarch(MultipleRef):
100
-    
101
+
101 102
     directly_editable = False
102 103
 
103 104
     ## @brief Instanciate a data handler handling hierarchical relation with constraints
104 105
     # @param back_reference tuple : Here it is mandatory to have a back ref (like a parent field)
105 106
     # @param max_depth int | None :  limit of depth
106 107
     # @param max_childs int | Nine : maximum number of childs by nodes
108
+    # @param kwargs : 
109
+    #   - allowed_classes list | None : list of allowed em classes if None no restriction
110
+    #   - internal bool : if False, the field is not internal
107 111
     def __init__(self, back_reference, max_depth=None, max_childs=None, **kwargs):
108 112
         super().__init__(back_reference=back_reference,
109 113
                          max_depth=max_depth,

+ 5
- 4
lodel/leapi/exceptions.py View File

@@ -4,6 +4,7 @@ from lodel.context import LodelContext
4 4
 LodelContext.expose_modules(globals(), {
5 5
     'lodel.exceptions': ['LodelExceptions', 'LodelException']})
6 6
 
7
+##@brief Handles LeApi error
7 8
 class LeApiError(LodelException):
8 9
     pass
9 10
 
@@ -13,20 +14,20 @@ class LeApiErrors(LodelExceptions, LeApiError):
13 14
     pass
14 15
 
15 16
 
16
-##@brief When an error concerns a datas
17
+##@brief When an error concerns a data
17 18
 class LeApiDataCheckError(LeApiError):
18 19
     pass
19 20
 
20
-
21
+##@brief Handles LeApi data errors
21 22
 class LeApiDataCheckErrors(LodelExceptions, LeApiError):
22 23
     pass
23 24
 
24 25
 
26
+##@brief Handles leapi query errors
25 27
 class LeApiQueryError(LeApiError):
26 28
     pass
27 29
 
28 30
 
29
-##@brief Handles mulitple query errors
31
+##@brief Handles multiple query errors
30 32
 class LeApiQueryErrors(LodelExceptions, LeApiQueryError):
31 33
     pass
32
-

+ 83
- 64
lodel/leapi/lefactory.py View File

@@ -1,22 +1,25 @@
1 1
 #-*- coding: utf-8 -*-
2 2
 
3
-import os, os.path
3
+import os
4
+import os.path
4 5
 import functools
5 6
 
6 7
 from lodel.context import LodelContext
7 8
 LodelContext.expose_modules(globals(), {
8 9
     'lodel.editorial_model.components': ['EmComponent', 'EmClass', 'EmField',
9
-        'EmGroup'],
10
+                                         'EmGroup'],
10 11
     'lodel.leapi.leobject': ['LeObject'],
11 12
     'lodel.leapi.datahandlers.base_classes': ['DataHandler'],
12 13
     'lodel.logger': 'logger'})
13 14
 
14
-##@brief Generate python module code from a given model
15
+# @brief Generates python module code from a given model
15 16
 # @param model lodel.editorial_model.model.EditorialModel
17
+
18
+
16 19
 def dyncode_from_em(model):
17
-    
20
+
18 21
     # Generation of LeObject child classes code
19
-    cls_code, modules, bootstrap_instr = generate_classes(model)
22
+    cls_code, bootstrap_instr = generate_classes(model)
20 23
 
21 24
     # Header
22 25
     imports = """from lodel.context import LodelContext
@@ -25,10 +28,8 @@ LodelContext.expose_modules(globals(), {
25 28
     'lodel.leapi.datahandlers.base_classes': ['DataField'],
26 29
     'lodel.plugin.hooks': ['LodelHook']})
27 30
 """
28
-    for module in modules:
29
-        imports += "import %s\n" % module
30
-    
31
-    class_list = [ LeObject.name2objname(cls.uid) for cls in get_classes(model) ]
31
+    # generates the list of all classes in the editorial model
32
+    class_list = [LeObject.name2objname(cls.uid) for cls in get_classes(model)]
32 33
 
33 34
     # formating all components of output
34 35
     res_code = """#-*- coding: utf-8 -*-
@@ -41,17 +42,21 @@ dynclasses = {class_list}
41 42
 dynclasses_dict = {class_dict}
42 43
 {common_code}
43 44
 """.format(
44
-            imports = imports,
45
-            classes = cls_code,
46
-            bootstrap_instr = bootstrap_instr,
47
-            class_list = '[' + (', '.join([cls for cls in class_list]))+']',
48
-            class_dict = '{' + (', '.join([ "'%s': %s" % (cls, cls)
49
-                for cls in class_list]))+'}',
50
-            common_code = common_code(),
45
+        imports=imports,
46
+        classes=cls_code,
47
+        bootstrap_instr=bootstrap_instr,
48
+        class_list='[' + (', '.join([cls for cls in class_list])) + ']',
49
+        class_dict='{' + (', '.join(["'%s': %s" % (cls, cls)
50
+                                     for cls in class_list])) + '}',
51
+        common_code=common_code(),
51 52
     )
52 53
     return res_code
53 54
 
54
-##@brief Return the content of lodel.leapi.lefactory_common
55
+# @brief Returns the content of lodel.leapi.lefactory_common
56
+#
57
+# @return a string
58
+
59
+
55 60
 def common_code():
56 61
     res = ""
57 62
     fname = os.path.dirname(__file__)
@@ -61,23 +66,32 @@ def common_code():
61 66
             if not line.startswith('#-'):
62 67
                 res += line
63 68
     return res
64
-    
65 69
 
66
-##@brief return A list of EmClass sorted by dependencies
70
+
71
+# @brief return A list of EmClass sorted by dependencies
67 72
 #
68
-# The first elts in the list depends on nothing, etc.
73
+# The first elts in the list depend on nothing, etc.
74
+# @param a list of Emclass instances to be sorted
69 75
 # @return a list of EmClass instances
70 76
 def emclass_sorted_by_deps(emclass_list):
71 77
     def emclass_deps_cmp(cls_a, cls_b):
72 78
         return len(cls_a.parents_recc) - len(cls_b.parents_recc)
73
-    ret = sorted(emclass_list, key = functools.cmp_to_key(emclass_deps_cmp))
79
+    ret = sorted(emclass_list, key=functools.cmp_to_key(emclass_deps_cmp))
74 80
     return ret
75 81
 
76
-##@brief Returns a list of EmClass 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
+# @param model : an EditorialModel instance
84
+# @return a list of EmClass instances
85
+
86
+
77 87
 def get_classes(model):
78
-    return [ cls for cls in emclass_sorted_by_deps(model.classes()) if not cls.pure_abstract ]
88
+    return [cls for cls in emclass_sorted_by_deps(model.classes()) if not cls.pure_abstract]
89
+
90
+# @brief Given an EmField returns the data_handler constructor suitable for dynamic code
91
+# @param a EmField instance
92
+# @return a string
93
+
79 94
 
80
-##@brief Given an EmField returns the data_handler constructor suitable for dynamic code
81 95
 def data_handler_constructor(emfield):
82 96
     #dh_module_name = DataHandler.module_name(emfield.data_handler_name)+'.DataHandler'
83 97
     get_handler_class_instr = 'DataField.from_name(%s)' % repr(emfield.data_handler_name)
@@ -85,60 +99,65 @@ def data_handler_constructor(emfield):
85 99
     for name, val in emfield.data_handler_options.items():
86 100
         if name == 'back_reference' and isinstance(val, tuple):
87 101
             options.append('{optname}: ({leo_name}, {fieldname})'.format(
88
-                optname = repr(name),
89
-                leo_name = LeObject.name2objname(val[0]),
90
-                fieldname = repr(val[1]),))
102
+                optname=repr(name),
103
+                leo_name=LeObject.name2objname(val[0]),
104
+                fieldname=repr(val[1]),))
91 105
         else:
92
-            options.append(repr(name)+': '+forge_optval(val))
106
+            options.append(repr(name) + ': ' + forge_optval(val))
93 107
 
94 108
     return '{handler_instr}(**{{ {options} }})'.format(
95
-                                                        handler_instr = get_handler_class_instr,
96
-                                                        options = ', '.join(options))
97
-            
98
-##@brief Return a python repr of option values
109
+        handler_instr=get_handler_class_instr,
110
+        options=', '.join(options))
111
+
112
+# @brief Return a python repr of option values
113
+# @param A value of any type which represents option
114
+# @return a string
115
+
116
+
99 117
 def forge_optval(optval):
100 118
     if isinstance(optval, dict):
101
-        return '{' + (', '.join( [ '%s: %s' % (repr(name), forge_optval(val)) for name, val in optval.items()])) + '}'
119
+        return '{' + (', '.join(['%s: %s' % (repr(name), forge_optval(val)) for name, val in optval.items()])) + '}'
102 120
 
103 121
     if isinstance(optval, (set, list, tuple)):
104 122
         return '[' + (', '.join([forge_optval(val) for val in optval])) + ']'
105
-        
123
+
106 124
     if isinstance(optval, EmField):
107 125
         return "{leobject}.data_handler({fieldname})".format(
108
-                leobject = LeObject.name2objname(optval._emclass.uid),
109
-                fieldname = repr(optval.uid)
110
-            )
111
-    elif isinstance(optval, EmClass):
126
+            leobject=LeObject.name2objname(optval._emclass.uid),
127
+            fieldname=repr(optval.uid)
128
+        )
129
+    if isinstance(optval, EmClass):
112 130
         return LeObject.name2objname(optval.uid)
113
-    else:
114
-        return repr(optval)
115 131
 
116
-##@brief Generate dyncode from an EmClass
117
-# @param model EditorialModel : 
118
-# @todo delete imports. It is never use, consequently changed return parameters.
132
+    return repr(optval)
133
+
134
+# @brief Generate dyncode from an EmClass
135
+# @param model EditorialModel :
119 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
+
138
+
120 139
 def generate_classes(model):
121 140
     res = ""
122
-    imports = list()
141
+
123 142
     bootstrap = ""
124 143
     # Generating field list for LeObjects generated from EmClass
125 144
     for em_class in get_classes(model):
126 145
         logger.info("Generating a dynamic class for %s" % em_class.uid)
127
-        uid = list()        # List of fieldnames that are part of the EmClass primary key
128
-        parents = list()    # List of parents EmClass
129
-        # Determine pk
146
+        uid = list()        # List for fieldnames that are part of the EmClass primary key
147
+        parents = list()    # List for em_class's parents
148
+        # Determines primary key
130 149
         for field in em_class.fields():
131 150
             if field.data_handler_instance.is_primary_key():
132 151
                 uid.append(field.uid)
133
-        # Determine parent for inheritance
152
+        # Determines parentsfor inheritance
134 153
         if len(em_class.parents) > 0:
135 154
             for parent in em_class.parents:
136
-               parents.append(LeObject.name2objname(parent.uid))
155
+                parents.append(LeObject.name2objname(parent.uid))
137 156
         else:
138 157
             parents.append('LeObject')
139 158
         datasource_name = em_class.datasource
140
-        
141
-        # Dynamic code generation for LeObject childs classes
159
+
160
+        # Dynamic code generation for LeObject child classes
142 161
         em_cls_code = """
143 162
 class {clsname}({parents}):
144 163
     _abstract = {abstract}
@@ -150,12 +169,12 @@ class {clsname}({parents}):
150 169
     _child_classes = None
151 170
 
152 171
 """.format(
153
-    clsname = LeObject.name2objname(em_class.uid),
154
-    parents = ', '.join(parents),
155
-    abstract = 'True' if em_class.abstract else 'False',
156
-    uid_list = repr(uid),
157
-    datasource_name = repr(datasource_name),
158
-)
172
+            clsname=LeObject.name2objname(em_class.uid),
173
+            parents=', '.join(parents),
174
+            abstract='True' if em_class.abstract else 'False',
175
+            uid_list=repr(uid),
176
+            datasource_name=repr(datasource_name),
177
+        )
159 178
         res += em_cls_code
160 179
         # Dyncode fields bootstrap instructions
161 180
         child_classes = model.get_class_childs(em_class.uid)
@@ -163,14 +182,14 @@ class {clsname}({parents}):
163 182
             child_classes = 'tuple()'
164 183
         else:
165 184
             child_classes = '(%s,)' % (', '.join(
166
-                [ LeObject.name2objname(emcls.uid) for emcls in child_classes]))
185
+                [LeObject.name2objname(emcls.uid) for emcls in child_classes]))
167 186
         bootstrap += """{classname}._set__fields({fields})
168 187
 {classname}._child_classes = {child_classes}
169 188
 """.format(
170
-    classname = LeObject.name2objname(em_class.uid),
171
-    fields = '{' + (', '.join(['\n\t%s: %s' % (repr(emfield.uid),data_handler_constructor(emfield)) for emfield in em_class.fields()])) + '}',
172
-    child_classes = child_classes,
173
-)
189
+            classname=LeObject.name2objname(em_class.uid),
190
+            fields='{' + (', '.join(['\n\t%s: %s' % (repr(emfield.uid),
191
+                                                     data_handler_constructor(emfield)) for emfield in em_class.fields()])) + '}',
192
+            child_classes=child_classes,
193
+        )
174 194
     bootstrap += "\n"
175
-    return res, set(imports), bootstrap
176
-    
195
+    return res, bootstrap

+ 3
- 4
lodel/leapi/lefactory_common.py View File

@@ -5,7 +5,7 @@
5 5
 #- All lines that begins with #- will be deleted from dynamically generated
6 6
 #- code...
7 7
 
8
-##@brief Return a dynamically generated class given it's name
8
+##@brief Returns a dynamically generated class given its name
9 9
 #@param name str : The dynamic class name
10 10
 #@return False or a child class of LeObject
11 11
 def name2class(name):
@@ -14,7 +14,7 @@ def name2class(name):
14 14
     return dynclasses_dict[name]
15 15
 
16 16
 
17
-##@brief Return a dynamically generated class given it's name
17
+##@brief Returns a dynamically generated class given its name
18 18
 #@note Case insensitive version of name2class
19 19
 #@param name str
20 20
 #@return False or a child class of LeObject
@@ -26,11 +26,10 @@ def lowername2class(name):
26 26
     return new_dict[name]
27 27
 
28 28
 
29
-##@brief Trigger dynclasses datasources initialisation
29
+##@brief Triggers dynclasses datasources initialisation
30 30
 @LodelHook("lodel2_plugins_loaded")
31 31
 def lodel2_dyncode_datasources_init(self, caller, payload):
32 32
     for cls in dynclasses:
33 33
         cls._init_datasources()
34 34
     LodelContext.expose_modules(globals(), {'lodel.plugin.hooks': ['LodelHook']})
35 35
     LodelHook.call_hook("lodel2_dyncode_loaded", __name__, dynclasses)
36
-

+ 194
- 188
lodel/leapi/query.py View File

@@ -8,20 +8,22 @@ import warnings
8 8
 from lodel.context import LodelContext
9 9
 LodelContext.expose_modules(globals(), {
10 10
     'lodel.leapi.exceptions': ['LeApiError', 'LeApiErrors',
11
-        'LeApiDataCheckError', 'LeApiDataCheckErrors', 'LeApiQueryError',
12
-        'LeApiQueryErrors'],
11
+                               'LeApiDataCheckError', 'LeApiDataCheckErrors', 'LeApiQueryError',
12
+                               'LeApiQueryErrors'],
13 13
     'lodel.plugin.hooks': ['LodelHook'],
14 14
     'lodel.logger': ['logger']})
15 15
 
16
-##@todo check datas when running query
16
+# @todo check data when running query
17
+
18
+
17 19
 class LeQuery(object):
18 20
 
19
-    ##@brief Hookname prefix
21
+    # @brief Hookname prefix
20 22
     _hook_prefix = None
21
-    ##@brief arguments for the LeObject.check_data_value()
23
+    # @brief arguments for the LeObject.check_data_value()
22 24
     _data_check_args = {'complete': False, 'allow_internal': False}
23 25
 
24
-    ##@brief Abstract constructor
26
+    # @brief Abstract constructor
25 27
     # @param target_class LeObject : class of object the query is about
26 28
     def __init__(self, target_class):
27 29
         from .leobject import LeObject
@@ -29,77 +31,80 @@ class LeQuery(object):
29 31
             raise NotImplementedError("Abstract class")
30 32
         if not inspect.isclass(target_class) or \
31 33
            not issubclass(target_class, LeObject):
32
-            raise TypeError("target class has to be a child class of LeObject but %s given"% target_class)
34
+            raise TypeError(
35
+                "target class has to be a child class of LeObject but %s given" % target_class)
33 36
         self._target_class = target_class
34 37
         self._ro_datasource = target_class._ro_datasource
35 38
         self._rw_datasource = target_class._rw_datasource
36 39
 
37
-    ##@brief Execute a query and return the result
38
-    #@param **datas
40
+    # @brief Executes a query and returns the result
41
+    #@param **data
39 42
     #@return the query result
40 43
     #@see LeQuery._query()
41 44
     #@todo check that the check_datas_value is not duplicated/useless
42
-    def execute(self, datas):
43
-        if not datas is None:
45
+    def execute(self, data):
46
+        if data is not None:
44 47
             self._target_class.check_datas_value(
45
-                                                    datas,
46
-                                                    **self._data_check_args)
47
-            self._target_class.prepare_datas(datas) #not yet implemented
48
+                data,
49
+                **self._data_check_args)
50
+            self._target_class.prepare_datas(data)  # not yet implemented
48 51
         if self._hook_prefix is None:
49 52
             raise NotImplementedError("Abstract method")
50
-        LodelHook.call_hook(self._hook_prefix+'pre',
51
-                                self._target_class,
52
-                                datas)
53
-        ret = self._query(datas=datas)
54
-        ret = LodelHook.call_hook(self._hook_prefix+'post',
55
-                                    self._target_class,
56
-                                    ret)
53
+        LodelHook.call_hook(self._hook_prefix + 'pre',
54
+                            self._target_class,
55
+                            data)
56
+        ret = self._query(data=data)
57
+        ret = LodelHook.call_hook(self._hook_prefix + 'post',
58
+                                  self._target_class,
59
+                                  ret)
57 60
         return ret
58 61
 
59
-    ##@brief Childs classes implements this method to execute the query
60
-    #@param **datas
62
+    # @brief Child classes implement this method to execute the query
63
+    #@param **data
61 64
     #@return query result
62
-    def _query(self, **datas):
65
+    def _query(self, **data):
63 66
         raise NotImplementedError("Asbtract method")
64 67
 
65
-    ##@return a dict with query infos
68
+    # @return a dict with query infos
66 69
     def dump_infos(self):
67 70
         return {'target_class': self._target_class}
68 71
 
69 72
     def __repr__(self):
70 73
         ret = "<{classname} target={target_class}>"
71 74
         return ret.format(
72
-                            classname=self.__class__.__name__,
73
-                            target_class = self._target_class)
75
+            classname=self.__class__.__name__,
76
+            target_class=self._target_class)
77
+
78
+# @brief Abstract class handling query with filters
79
+
74 80
 
75
-##@brief Abstract class handling query with filters
76 81
 class LeFilteredQuery(LeQuery):
77
-    ##@brief The available operators used in query definitions
82
+    # @brief The available operators used in query definitions
78 83
     _query_operators = [
79
-                        ' = ',
80
-                        ' <= ',
81
-                        ' >= ',
82
-                        ' != ',
83
-                        ' < ',
84
-                        ' > ',
85
-                        ' in ',
86
-                        ' not in ',
87
-                        ' like ',
88
-                        ' not like ']
89
-
90
-    ##@brief Regular expression to process filters
84
+        ' = ',
85
+        ' <= ',
86
+        ' >= ',
87
+        ' != ',
88
+        ' < ',
89
+        ' > ',
90
+        ' in ',
91
+        ' not in ',
92
+        ' like ',
93
+        ' not like ']
94
+
95
+    # @brief Regular expression to process filters
91 96
     _query_re = None
92 97
 
93
-    ##@brief Abtract constructor for queries with filter
98
+    # @brief Abtract constructor for queries with filter
94 99
     #@param target_class LeObject : class of object the query is about
95 100
     #@param query_filters list : with a tuple (only one filter) or a list of
96 101
     # tuple or a dict: {OP,list(filters)} with OP = 'OR' or 'AND for tuple
97 102
     # (FIELD,OPERATOR,VALUE)
98 103
     def __init__(self, target_class, query_filters=None):
99 104
         super().__init__(target_class)
100
-        ##@brief The query filter tuple(std_filter, relational_filters)
105
+        # @brief The query filter tuple(std_filter, relational_filters)
101 106
         self._query_filter = None
102
-        ##@brief Stores potential subqueries (used when a query implies
107
+        # @brief Stores potential subqueries (used when a query implies
103 108
         # more than one datasource.
104 109
         #
105 110
         # Subqueries are tuple(target_class_ref_field, LeGetQuery)
@@ -107,11 +112,11 @@ class LeFilteredQuery(LeQuery):
107 112
         query_filters = [] if query_filters is None else query_filters
108 113
         self.set_query_filter(query_filters)
109 114
 
110
-    ##@brief Abstract FilteredQuery execution method
115
+    # @brief Abstract FilteredQuery execution method
111 116
     #
112 117
     # This method takes care to execute subqueries before calling super execute
113
-    def execute(self, datas=None):
114
-        #copy originals filters
118
+    def execute(self, data=None):
119
+        # copy originals filters
115 120
         orig_filters = copy.copy(self._query_filter)
116 121
         std_filters, rel_filters = self._query_filter
117 122
 
@@ -123,17 +128,17 @@ class LeFilteredQuery(LeQuery):
123 128
         try:
124 129
 
125 130
             filters, rel_filters = self._query_filter
126
-            res = super().execute(datas)
131
+            res = super().execute(data)
127 132
         except Exception as e:
128
-            #restoring filters even if an exception is raised
133
+            # restoring filters even if an exception is raised
129 134
             self.__query_filter = orig_filters
130 135
 
131
-            raise e #reraise
132
-        #restoring filters
136
+            raise e  # reraise
137
+        # restoring filters
133 138
         self._query_filter = orig_filters
134 139
         return res
135 140
 
136
-    ##@brief Add filter(s) to the query
141
+    # @brief Add filter(s) to the query
137 142
     #
138 143
     # This method is also able to slice query if different datasources are
139 144
     # implied in the request
@@ -144,39 +149,39 @@ class LeFilteredQuery(LeQuery):
144 149
     def set_query_filter(self, query_filter):
145 150
         if isinstance(query_filter, str):
146 151
             query_filter = [query_filter]
147
-        #Query filter prepration
152
+        # Query filter prepration
148 153
         filters_orig, rel_filters = self._prepare_filters(query_filter)
149 154
         # Here we now that each relational filter concern only one datasource
150 155
         # thank's to _prepare_relational_fields
151 156
 
152
-        #Multiple datasources detection
157
+        # Multiple datasources detection
153 158
         self_ds_name = self._target_class._datasource_name
154
-        result_rel_filters = list() # The filters that will stay in the query
159
+        result_rel_filters = list()  # The filters that will stay in the query
155 160
         other_ds_filters = dict()
156 161
         for rfilter in rel_filters:
157 162
             (rfield, ref_dict), op, value = rfilter
158
-            #rfield : the field in self._target_class
159
-            tmp_rel_filter = dict() #designed to stores rel_field of same DS
163
+            # rfield : the field in self._target_class
164
+            tmp_rel_filter = dict()  # designed to stores rel_field of same DS
160 165
             # First step : simplification
161 166
             # Trying to delete relational filters done on referenced class uid
162 167
             for tclass, tfield in copy.copy(ref_dict).items():
163
-                #tclass : reference target class
164
-                #tfield : referenced field from target class
168
+                # tclass : reference target class
169
+                # tfield : referenced field from target class
165 170
                 #
166 171
                 #   !!!WARNING!!!
167 172
                 # The line below brake multi UID support
168 173
                 #
169 174
                 if tfield == tclass.uid_fieldname()[0]:
170
-                    #This relational filter can be simplified as
175
+                    # This relational filter can be simplified as
171 176
                     # ref_field, op, value
172 177
                     # Note : we will have to dedup filters_orig
173 178
                     filters_orig.append((rfield, op, value))
174 179
                     del(ref_dict[tclass])
175 180
             if len(ref_dict) == 0:
176 181
                 continue
177
-            #Determine what to do with other relational filters given
182
+            # Determine what to do with other relational filters given
178 183
             # referenced class datasource
179
-            #Remember : each class in a relational filter has the same
184
+            # Remember : each class in a relational filter has the same
180 185
             # datasource
181 186
             tclass = list(ref_dict.keys())[0]
182 187
             cur_ds = tclass._datasource_name
@@ -189,23 +194,23 @@ class LeFilteredQuery(LeQuery):
189 194
                     other_ds_filters[cur_ds] = list()
190 195
                 other_ds_filters[cur_ds].append(
191 196
                     ((rfield, ref_dict), op, value))
192
-        #deduplication of std filters
197
+        # deduplication of std filters
193 198
         filters_cp = set()
194 199
         if not isinstance(filters_orig, set):
195 200
             for i, cfilt in enumerate(filters_orig):
196 201
                 a, b, c = cfilt
197
-                if isinstance(c, list): #list are not hashable
202
+                if isinstance(c, list):  # list are not hashable
198 203
                     newc = tuple(c)
199 204
                 else:
200 205
                     newc = c
201 206
                 old_len = len(filters_cp)
202
-                filters_cp |= set((a,b,newc))
207
+                filters_cp |= set((a, b, newc))
203 208
                 if len(filters_cp) == old_len:
204 209
                     del(filters_orig[i])
205 210
         # Sets _query_filter attribute of self query
206 211
         self._query_filter = (filters_orig, result_rel_filters)
207 212
 
208
-        #Sub queries creation
213
+        # Sub queries creation
209 214
         subq = list()
210 215
         for ds, rfilters in other_ds_filters.items():
211 216
             for rfilter in rfilters:
@@ -218,7 +223,7 @@ class LeFilteredQuery(LeQuery):
218 223
                     subq.append((rfield, query))
219 224
         self.subqueries = subq
220 225
 
221
-    ##@return informations
226
+    # @return informations
222 227
     def dump_infos(self):
223 228
         ret = super().dump_infos()
224 229
         ret['query_filter'] = self._query_filter
@@ -238,16 +243,16 @@ class LeFilteredQuery(LeQuery):
238 243
         res += '>'
239 244
         return res
240 245
 
241
-    ## @brief Prepare filters for datasource
246
+    # @brief Prepare filters for datasource
242 247
     #
243
-    #A filter can be a string or a tuple with len = 3.
248
+    # A filter can be a string or a tuple with len = 3.
244 249
     #
245
-    #This method divide filters in two categories :
250
+    # This method divide filters in two categories :
246 251
     #
247 252
     #@par Simple filters
248 253
     #
249
-    #Those filters concerns fields that represent object values (a title,
250
-    #the content, etc.) They are composed of three elements : FIELDNAME OP
254
+    # Those filters concerns fields that represent object values (a title,
255
+    # the content, etc.) They are composed of three elements : FIELDNAME OP
251 256
     # VALUE . Where :
252 257
     #- FIELDNAME is the name of the field
253 258
     #- OP is one of the authorized comparison operands (see
@@ -256,14 +261,14 @@ class LeFilteredQuery(LeQuery):
256 261
     #
257 262
     #@par Relational filters
258 263
     #
259
-    #Those filters concerns on reference fields (see the corresponding
260
-    #abstract datahandler @ref lodel.leapi.datahandlers.base_classes.Reference)
261
-    #The filter as quite the same composition than simple filters :
264
+    # Those filters concerns on reference fields (see the corresponding
265
+    # abstract datahandler @ref lodel.leapi.datahandlers.base_classes.Reference)
266
+    # The filter as quite the same composition than simple filters :
262 267
     # FIELDNAME[.REF_FIELD] OP VALUE . Where :
263 268
     #- FIELDNAME is the name of the reference field
264 269
     #- REF_FIELD is an optionnal addon to the base field. It indicate on wich
265
-    #field of the referenced object the comparison as to be done. If no
266
-    #REF_FIELD is indicated the comparison will be done on identifier.
270
+    # field of the referenced object the comparison as to be done. If no
271
+    # REF_FIELD is indicated the comparison will be done on identifier.
267 272
     #
268 273
     #@param cls
269 274
     #@param filters_l list : This list of str or tuple (or both)
@@ -271,11 +276,11 @@ class LeFilteredQuery(LeQuery):
271 276
     #@todo move this doc in another place (a dedicated page ?)
272 277
     #@warning Does not supports multiple UID for an EmClass
273 278
     def _prepare_filters(self, filters_l):
274
-        filters=list()
279
+        filters = list()
275 280
         res_filters = list()
276 281
         rel_filters = list()
277 282
         err_l = dict()
278
-        #Splitting in tuple if necessary
283
+        # Splitting in tuple if necessary
279 284
         for i, fil in enumerate(filters_l):
280 285
             if len(fil) == 3 and not isinstance(fil, str):
281 286
                 filters.append(tuple(fil))
@@ -286,7 +291,7 @@ class LeFilteredQuery(LeQuery):
286 291
                     err_l["filter %d" % i] = e
287 292
 
288 293
         for field, operator, value in filters:
289
-            err_key = "%s %s %s" % (field, operator, value) #to push in err_l
294
+            err_key = "%s %s %s" % (field, operator, value)  # to push in err_l
290 295
             # Spliting field name to be able to detect a relational field
291 296
             field_spl = field.split('.')
292 297
             if len(field_spl) == 2:
@@ -310,12 +315,12 @@ field name" % field)
310 315
                 # inconsistency
311 316
                 err_l[field] = NameError("The field '%s' in %s is not \
312 317
 a relational field, but %s.%s was present in the filter"
313
-                                            % (field,
314
-                                                self._target_class.__name__,
315
-                                                field,
316
-                                                ref_field))
318
+                                         % (field,
319
+                                            self._target_class.__name__,
320
+                                            field,
321
+                                            ref_field))
317 322
             if field_datahandler.is_reference():
318
-                #Relationnal field
323
+                # Relationnal field
319 324
                 if ref_field is None:
320 325
                     # ref_field default value
321 326
                     #
@@ -350,14 +355,14 @@ field to use for the relational filter"
350 355
                 value, error = field_datahandler.check_data_value(value)
351 356
                 if isinstance(error, Exception):
352 357
                     value = value_orig
353
-                res_filters.append((field,operator, value))
358
+                res_filters.append((field, operator, value))
354 359
         if len(err_l) > 0:
355 360
             raise LeApiDataCheckErrors(
356
-                                        "Error while preparing filters : ",
357
-                                        err_l)
361
+                "Error while preparing filters : ",
362
+                err_l)
358 363
         return (res_filters, rel_filters)
359 364
 
360
-    ## @brief Check and split a query filter
365
+    # @brief Check and split a query filter
361 366
     # @note The query_filter format is "FIELD OPERATOR VALUE"
362 367
     # @param query_filter str : A query_filter string
363 368
     # @param cls
@@ -382,18 +387,18 @@ field to use for the relational filter"
382 387
                 raise ValueError(msg % query_filter)
383 388
         return result
384 389
 
385
-    ## @brief Compile the regex for query_filter processing
390
+    # @brief Compile the regex for query_filter processing
386 391
     # @note Set _LeObject._query_re
387 392
     @classmethod
388 393
     def __compile_query_re(cls):
389 394
         op_re_piece = '(?P<operator>(%s)'
390 395
         op_re_piece %= cls._query_operators[0].replace(' ', '\s')
391 396
         for operator in cls._query_operators[1:]:
392
-            op_re_piece += '|(%s)'%operator.replace(' ', '\s')
397
+            op_re_piece += '|(%s)' % operator.replace(' ', '\s')
393 398
         op_re_piece += ')'
394 399
 
395 400
         re_full = '^\s*(?P<field>([a-z_][a-z0-9\-_]*\.)?[a-z_][a-z0-9\-_]*)\s*'
396
-        re_full += op_re_piece+'\s*(?P<value>.*)\s*$'
401
+        re_full += op_re_piece + '\s*(?P<value>.*)\s*$'
397 402
 
398 403
         cls._query_re = re.compile(re_full, flags=re.IGNORECASE)
399 404
         pass
@@ -407,10 +412,10 @@ field to use for the relational filter"
407 412
             msg %= (fieldname, target_class.__name__)
408 413
             return NameError(msg)
409 414
 
410
-    ##@brief Prepare a relational filter
415
+    # @brief Prepare a relational filter
411 416
     #
412
-    #Relational filters are composed of a tuple like the simple filters
413
-    #but the first element of this tuple is a tuple to :
417
+    # Relational filters are composed of a tuple like the simple filters
418
+    # but the first element of this tuple is a tuple to :
414 419
     #
415 420
     #<code>((FIELDNAME, {REF_CLASS: REF_FIELD}), OP, VALUE)</code>
416 421
     # Where :
@@ -419,9 +424,9 @@ field to use for the relational filter"
419 424
     # - REF_CLASS as key. It's a LeObject child class
420 425
     # - REF_FIELD as value. The name of the referenced field in the REF_CLASS
421 426
     #
422
-    #Visibly the REF_FIELD value of the dict will vary only when
423
-    #no REF_FIELD is explicitly given in the filter string notation
424
-    #and REF_CLASSES has differents uid
427
+    # Visibly the REF_FIELD value of the dict will vary only when
428
+    # no REF_FIELD is explicitly given in the filter string notation
429
+    # and REF_CLASSES has differents uid
425 430
     #
426 431
     #@par String notation examples
427 432
     #<pre>contributeur IN (1,2,3,5)</pre> will be transformed into :
@@ -439,7 +444,7 @@ field to use for the relational filter"
439 444
     #
440 445
     #@param fieldname str : The relational field name
441 446
     #@param ref_field str|None : The referenced field name (if None use
442
-    #uniq identifiers as referenced field
447
+    # uniq identifiers as referenced field
443 448
     #@return a well formed relational filter tuple or an Exception instance
444 449
     def _prepare_relational_fields(self, fieldname, ref_field=None):
445 450
         datahandler = self._target_class.field(fieldname)
@@ -467,12 +472,12 @@ the relational filter %s"
467 472
                     logger.debug(msg)
468 473
         if len(ref_dict) == 0:
469 474
             return NameError("No field named '%s' in referenced objects [%s]"
470
-                                % (ref_field,
471
-                                    ','.join([rc.__name__ for rc in ref_classes])))
475
+                             % (ref_field,
476
+                                ','.join([rc.__name__ for rc in ref_classes])))
472 477
         return (fieldname, ref_dict)
473 478
 
474 479
 
475
-##@brief A query to insert a new object
480
+# @brief A query to insert a new object
476 481
 class LeInsertQuery(LeQuery):
477 482
     _hook_prefix = 'leapi_insert_'
478 483
     _data_check_args = {'complete': True, 'allow_internal': False}
@@ -483,49 +488,49 @@ class LeInsertQuery(LeQuery):
483 488
 abstract LeObject : %s" % target_class)
484 489
         super().__init__(target_class)
485 490
 
486
-    ## @brief Implements an insert query operation, with only one insertion
487
-    # @param datas : datas to be inserted
488
-    def _query(self, datas):
489
-        datas = self._target_class.prepare_datas(datas, True, False)
490
-        id_inserted = self._rw_datasource.insert(self._target_class, datas)
491
+    #  @brief Implements an insert query operation, with only one insertion
492
+    # @param data : data to be inserted
493
+    def _query(self, data):
494
+        data = self._target_class.prepare_datas(data, True, False)
495
+        id_inserted = self._rw_datasource.insert(self._target_class, data)
491 496
         return id_inserted
492 497
     """
493 498
     ## @brief Implements an insert query operation, with multiple insertions
494
-    # @param datas : list of **datas to be inserted
495
-    def _query(self, datas):
499
+    # @param data : list of **data to be inserted
500
+    def _query(self, data):
496 501
         nb_inserted = self._datasource.insert_multi(
497
-            self._target_class,datas_list)
502
+            self._target_class,data_list)
498 503
         if nb_inserted < 0:
499 504
             raise LeApiQueryError("Multiple insertions error")
500 505
         return nb_inserted
501 506
     """
502 507
 
503
-    ## @brief Execute the insert query
504
-    def execute(self, datas):
505
-        return super().execute(datas=datas)
508
+    #  @brief Execute the insert query
509
+    def execute(self, data):
510
+        return super().execute(data=data)
506 511
 
507 512
 
508
-##@brief A query to update datas for a given object
513
+# @brief A query to update data for a given object
509 514
 #
510 515
 #@todo Change behavior, Huge optimization problem when updating using filters
511
-#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 1 update by fecthed object...
512 517
 class LeUpdateQuery(LeFilteredQuery):
513 518
     _hook_prefix = 'leapi_update_'
514 519
     _data_check_args = {'complete': False, 'allow_internal': False}
515 520
 
516
-    ##@brief Instanciate an update query
521
+    # @brief Instanciate an update query
517 522
     #
518
-    #If a class and not an instance is given, no query_filters are expected
519
-    #and the update will be fast and simple. Else we have to run a get query
520
-    #before updating (to fetch datas, update them and then, construct them
521
-    #and check their consistency)
523
+    # If a class and not an instance is given, no query_filters are expected
524
+    # and the update will be fast and simple. Else we have to run a get query
525
+    # before updating (to fetch data, update them and then, construct them
526
+    # and check their consistency)
522 527
     #@param target LeObject clas or instance
523 528
     #@param query_filters list|None
524
-    #@todo change strategy with instance update. We have to accept datas for
525
-    #the execute method
529
+    #@todo change strategy with instance update. We have to accept data for
530
+    # the execute method
526 531
     def __init__(self, target, query_filters=None):
527
-        ##@brief This attr is set only if the target argument is an
528
-        #instance of a LeObject subclass
532
+        # @brief This attr is set only if the target argument is an
533
+        # instance of a LeObject subclass
529 534
         self.__leobject_instance_datas = None
530 535
         target_class = target
531 536
 
@@ -542,16 +547,16 @@ target to LeUpdateQuery constructor"
542 547
 
543 548
         super().__init__(target_class, query_filters)
544 549
 
545
-    ##@brief Implements an update query
546
-    #@param datas dict : datas to update
550
+    # @brief Implements an update query
551
+    #@param data dict : data to be updated
547 552
     #@returns the number of updated items
548
-    #@todo change stategy for instance update. Datas should be allowed
549
-    #for execute method (and query)
550
-    def _query(self, datas):
553
+    #@todo change stategy for instance update. Data should be allowed
554
+    # for execute method (and query)
555
+    def _query(self, data):
551 556
         uid_name = self._target_class._uid[0]
552 557
         if self.__leobject_instance_datas is not None:
553
-            #Instance update
554
-            #Building query_filter
558
+            # Instance update
559
+            # Building query_filter
555 560
             filters = [(
556 561
                 uid_name,
557 562
                 '=',
@@ -560,59 +565,60 @@ target to LeUpdateQuery constructor"
560 565
                 self._target_class, filters, [],
561 566
                 self.__leobject_instance_datas)
562 567
         else:
563
-            #Update by filters, we have to fetch datas before updating
568
+            # Update by filters, we have to fetch data before updating
564 569
             res = self._ro_datasource.select(
565 570
                 self._target_class, self._target_class.fieldnames(True),
566 571
                 self._query_filter[0],
567 572
                 self._query_filter[1])
568
-            #Checking and constructing datas
569
-            upd_datas = dict()
573
+            # Checking and constructing data
574
+            upd_data = dict()
570 575
             for res_data in res:
571
-                res_data.update(datas)
572
-                res_datas = self._target_class.prepare_datas(
576
+                res_data.update(data)
577
+                res_data = self._target_class.prepare_datas(
573 578
                     res_data, True, True)
574 579
                 filters = [(uid_name, '=', res_data[uid_name])]
575 580
                 res = self._rw_datasource.update(
576 581
                     self._target_class, filters, [],
577
-                    res_datas)
582
+                    res_data)
578 583
         return res
579 584
 
580
-    ## @brief Execute the update query
581
-    def execute(self, datas=None):
582
-        if self.__leobject_instance_datas is not None and datas is not None:
583
-            raise LeApiQueryError("No datas expected when running an update \
585
+    #  @brief Execute the update query
586
+    def execute(self, data=None):
587
+        if self.__leobject_instance_datas is not None and data is not None:
588
+            raise LeApiQueryError("No data expected when running an update \
584 589
 query on an instance")
585
-        if self.__leobject_instance_datas is None and datas is None:
586
-            raise LeApiQueryError("Datas are mandatory when running an update \
590
+        if self.__leobject_instance_datas is None and data is None:
591
+            raise LeApiQueryError("Data are mandatory when running an update \
587 592
 query on a class with filters")
588
-        return super().execute(datas=datas)
593
+        return super().execute(data=data)
589 594
 
590 595
 
591
-##@brief A query to delete an object
596
+# @brief A query to delete an object
592 597
 class LeDeleteQuery(LeFilteredQuery):
593 598
     _hook_prefix = 'leapi_delete_'
594 599
 
595 600
     def __init__(self, target_class, query_filter):
596 601
         super().__init__(target_class, query_filter)
597 602
 
598
-    ## @brief Execute the delete query
599
-    # @param datas
600
-    def execute(self, datas=None):
603
+    #  @brief Execute the delete query
604
+    # @param data
605
+    def execute(self, data=None):
601 606
         return super().execute()
602 607
 
603
-    ##@brief Implements delete query operations
604
-    # @param datas
608
+    # @brief Implements delete query operations
609
+    # @param data
605 610
     #@returns the number of deleted items
606
-    def _query(self, datas=None):
611
+    def _query(self, data=None):
607 612
         filters, rel_filters = self._query_filter
608 613
         nb_deleted = self._rw_datasource.delete(
609 614
             self._target_class, filters, rel_filters)
610 615
         return nb_deleted
611 616
 
617
+
612 618
 class LeGetQuery(LeFilteredQuery):
613 619
     _hook_prefix = 'leapi_get_'
614 620
 
615
-    ##@brief Instanciate a new get query
621
+    # @brief Instanciate a new get query
616 622
     #@param target_class LeObject : class of object the query is about
617 623
     #@param query_filters dict : {OP, list of query filters}
618 624
     # or tuple (FIELD, OPERATOR, VALUE) )
@@ -624,33 +630,33 @@ class LeGetQuery(LeFilteredQuery):
624 630
     #   - offset int : offset
625 631
     def __init__(self, target_class, query_filters, **kwargs):
626 632
         super().__init__(target_class, query_filters)
627
-        ##@brief The fields to get
633
+        # @brief The fields to get
628 634
         self._field_list = None
629
-        ##@brief An equivalent to the SQL ORDER BY
635
+        # @brief An equivalent to the SQL ORDER BY
630 636
         self._order = None
631
-        ##@brief An equivalent to the SQL GROUP BY
637
+        # @brief An equivalent to the SQL GROUP BY
632 638
         self._group = None
633
-        ##@brief An equivalent to the SQL LIMIT x
639
+        # @brief An equivalent to the SQL LIMIT x
634 640
         self._limit = None
635
-        ##@brief An equivalent to the SQL LIMIT x, OFFSET
641
+        # @brief An equivalent to the SQL LIMIT x, OFFSET
636 642
         self._offset = 0
637 643
 
638 644
         # Checking kwargs and assigning default values if there is some
639 645
         for argname in kwargs:
640 646
             if argname not in (
641
-                'field_list', 'order', 'group', 'limit', 'offset'):
647
+                    'field_list', 'order', 'group', 'limit', 'offset'):
642 648
                 raise TypeError("Unexpected argument '%s'" % argname)
643 649
 
644 650
         if 'field_list' not in kwargs:
645
-            self.set_field_list(target_class.fieldnames(include_ro = True))
651
+            self.set_field_list(target_class.fieldnames(include_ro=True))
646 652
         else:
647 653
             self.set_field_list(kwargs['field_list'])
648 654
 
649 655
         if 'order' in kwargs:
650
-            #check kwargs['order']
656
+            # check kwargs['order']
651 657
             self._order = kwargs['order']
652 658
         if 'group' in kwargs:
653
-            #check kwargs['group']
659
+            # check kwargs['group']
654 660
             self._group = kwargs['group']
655 661
         if 'limit' in kwargs and kwargs['limit'] is not None:
656 662
             try:
@@ -669,7 +675,7 @@ class LeGetQuery(LeFilteredQuery):
669 675
                 msg = "offset argument expected to be an integer >= 0"
670 676
                 raise ValueError(msg)
671 677
 
672
-    ##@brief Set the field list
678
+    # @brief Set the field list
673 679
     # @param field_list list | None : If None use all fields
674 680
     # @return None
675 681
     # @throw LeApiQueryError if unknown field given
@@ -682,41 +688,41 @@ class LeGetQuery(LeFilteredQuery):
682 688
                     msg = "No field named '%s' in %s"
683 689
                     msg %= (fieldname, self._target_class.__name__)
684 690
                     expt = NameError(msg)
685
-                    err_l[fieldname] =  expt
691
+                    err_l[fieldname] = expt
686 692
             if len(err_l) > 0:
687 693
                 msg = "Error while setting field_list in a get query"
688
-                raise LeApiQueryErrors(msg = msg, exceptions = err_l)
694
+                raise LeApiQueryErrors(msg=msg, exceptions=err_l)
689 695
             self._field_list = list(set(field_list))
690 696
 
691
-    ##@brief Execute the get query
692
-    def execute(self, datas=None):
697
+    # @brief Execute the get query
698
+    def execute(self, data=None):
693 699
         return super().execute()
694 700
 
695
-    ##@brief Implements select query operations
701
+    # @brief Implements select query operations
696 702
     # @returns a list containing the item(s)
697
-    def _query(self, datas=None):
698
-        # select datas corresponding to query_filter
703
+    def _query(self, data=None):
704
+        # select data corresponding to query_filter
699 705
         fl = list(self._field_list) if self._field_list is not None else None
700
-        l_datas=self._ro_datasource.select(
701
-            target = self._target_class,
702
-            field_list = fl,
703
-            filters = self._query_filter[0],
704
-            relational_filters = self._query_filter[1],
705
-            order = self._order,
706
-            group = self._group,
707
-            limit = self._limit,
708
-            offset = self._offset)
709
-        return l_datas
710
-
711
-    ##@return a dict with query infos
706
+        l_data = self._ro_datasource.select(
707
+            target=self._target_class,
708
+            field_list=fl,
709
+            filters=self._query_filter[0],
710
+            relational_filters=self._query_filter[1],
711
+            order=self._order,
712
+            group=self._group,
713
+            limit=self._limit,
714
+            offset=self._offset)
715
+        return l_data
716
+
717
+    # @return a dict with query infos
712 718
     def dump_infos(self):
713 719
         ret = super().dump_infos()
714
-        ret.update({  'field_list' : self._field_list,
715
-                        'order' : self._order,
716
-                        'group' : self._group,
717
-                        'limit' : self._limit,
718
-                        'offset': self._offset,
719
-       })
720
+        ret.update({'field_list': self._field_list,
721
+                    'order': self._order,
722
+                    'group': self._group,
723
+                    'limit': self._limit,
724
+                    'offset': self._offset,
725
+                    })
720 726
         return ret
721 727
 
722 728
     def __repr__(self):
@@ -725,7 +731,7 @@ field_list={field_list} order={order} group={group} limit={limit} \
725 731
 offset={offset}"
726 732
         res = res.format(**self.dump_infos())
727 733
         if len(self.subqueries) > 0:
728
-            for n,subq in enumerate(self.subqueries):
734
+            for n, subq in enumerate(self.subqueries):
729 735
                 res += "\n\tSubquerie %d : %s"
730 736
                 res %= (n, subq)
731 737
         res += ">"

+ 27
- 37
lodel/plugins/mongodb_datasource/datasource.py View File

@@ -84,9 +84,9 @@ class MongoDbDatasource(AbstractDatasource):
84 84
         target = emcomp.uid_source()
85 85
         tuid = target._uid[0] # Multiple UID broken here
86 86
         results = self.select(
87
-            target, field_list = [tuid], filters = [], 
87
+            target, field_list = [tuid], filters = [],
88 88
             order=[(tuid, 'DESC')], limit = 1)
89
-        if len(results) == 0: 
89
+        if len(results) == 0:
90 90
             return 1
91 91
         return results[0][tuid]+1
92 92
 
@@ -95,23 +95,23 @@ class MongoDbDatasource(AbstractDatasource):
95 95
     #@param field_list list
96 96
     #@param filters list : List of filters
97 97
     #@param relational_filters list : List of relational filters
98
-    #@param order list : List of column to order. ex: order = 
98
+    #@param order list : List of column to order. ex: order =
99 99
     #[('title', 'ASC'),]
100
-    #@param group list : List of tupple representing the column used as 
100
+    #@param group list : List of tupple representing the column used as
101 101
     #"group by" fields. ex: group = [('title', 'ASC'),]
102 102
     #@param limit int : Number of records to be returned
103 103
     #@param offset int: used with limit to choose the start record
104 104
     #@return list
105 105
     #@todo Implement group for abstract LeObject childs
106
-    def select(self, target, field_list, filters = None, 
107
-            relational_filters=None, order=None, group=None, limit=None, 
106
+    def select(self, target, field_list, filters = None,
107
+            relational_filters=None, order=None, group=None, limit=None,
108 108
             offset=0):
109 109
         if target.is_abstract():
110 110
             #Reccursiv calls for abstract LeObject child
111 111
             results =  self.__act_on_abstract(target, filters,
112 112
                 relational_filters, self.select, field_list = field_list,
113 113
                 order = order, group = group, limit = limit)
114
-            
114
+
115 115
             #Here we may implement the group
116 116
             #If sorted query we have to sort again
117 117
             if order is not None:
@@ -138,11 +138,11 @@ class MongoDbDatasource(AbstractDatasource):
138 138
 
139 139
         query_filters = self.__process_filters(
140 140
             target, filters, relational_filters)
141
-        
141
+
142 142
         query_result_ordering = None
143 143
         if order is not None:
144 144
             query_result_ordering = utils.parse_query_order(order)
145
-        
145
+
146 146
         if group is None:
147 147
             if field_list is None:
148 148
                 field_list = dict()
@@ -189,7 +189,7 @@ class MongoDbDatasource(AbstractDatasource):
189 189
         results = list()
190 190
         for document in cursor:
191 191
             results.append(document)
192
-        
192
+
193 193
         return results
194 194
 
195 195
     ##@brief Deletes records according to given filters
@@ -236,7 +236,7 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
236 236
         self.__update_backref_filtered(target, filters, relational_filters,
237 237
             upd_datas, old_datas_l)
238 238
         return res
239
-    
239
+
240 240
     ##@brief Designed to be called by backref update in order to avoid
241 241
     #infinite updates between back references
242 242
     #@see update()
@@ -269,7 +269,7 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
269 269
             raise MongoDataSourceError("Missing UID data will inserting a new \
270 270
 %s" % target.__class__)
271 271
         res = self.__collection(target).insert(new_datas)
272
-        self.__update_backref(target, new_datas[uidname], None, new_datas) 
272
+        self.__update_backref(target, new_datas[uidname], None, new_datas)
273 273
         return str(res)
274 274
 
275 275
     ## @brief Inserts a list of records in a given collection
@@ -281,10 +281,10 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
281 281
             self._data_cast(datas)
282 282
         res = self.__collection(target).insert_many(datas_list)
283 283
         for new_datas in datas_list:
284
-            self.__update_backref(target, None, new_datas) 
284
+            self.__update_backref(target, None, new_datas)
285 285
             target.make_consistency(datas=new_datas)
286 286
         return list(res.inserted_ids)
287
-    
287
+
288 288
     ##@brief Update backref giving an action
289 289
     #@param target leObject child class
290 290
     #@param filters
@@ -303,7 +303,7 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
303 303
             old_datas_l = self.__collection(target).find(
304 304
                 mongo_filters)
305 305
             old_datas_l = list(old_datas_l)
306
-        
306
+
307 307
         uidname = target.uid_fieldname()[0] #MULTIPLE UID BROKEN HERE
308 308
         for old_datas in old_datas_l:
309 309
             self.__update_backref(
@@ -312,7 +312,7 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
312 312
     ##@brief Update back references of an object
313 313
     #@ingroup plugin_mongodb_bref_op
314 314
     #
315
-    #old_datas and new_datas arguments are set to None to indicate 
315
+    #old_datas and new_datas arguments are set to None to indicate
316 316
     #insertion or deletion. Calls examples :
317 317
     #@par LeObject insert __update backref call
318 318
     #<pre>
@@ -441,8 +441,8 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
441 441
                 self.__update_no_backref(
442 442
                     leo.__class__, [(leo.uid_fieldname()[0], '=', uidval)],
443 443
                     [], datas)
444
-    
445
-    ##@brief Utility function designed to handle the upd_dict of 
444
+
445
+    ##@brief Utility function designed to handle the upd_dict of
446 446
     #__update_backref()
447 447
     #
448 448
     #Basically checks if a key exists at some level, if not create it with
@@ -453,7 +453,7 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
453 453
     #@param uid_val mixed : the UID of the referenced object
454 454
     #@return the updated version of upd_dict
455 455
     @staticmethod
456
-    def __update_backref_upd_dict_prepare(upd_dict,bref_infos, bref_fname, 
456
+    def __update_backref_upd_dict_prepare(upd_dict,bref_infos, bref_fname,
457 457
             uid_val):
458 458
         bref_cls, bref_leo, bref_dh, bref_value = bref_infos
459 459
         if bref_cls not in upd_dict:
@@ -463,8 +463,8 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
463 463
         if bref_fname not in upd_dict[bref_cls][uid_val]:
464 464
             upd_dict[bref_cls][uid_val][1][bref_fname] = bref_value
465 465
         return upd_dict
466
-        
467
-        
466
+
467
+
468 468
     ##@brief Prepare a one value back reference update
469 469
     #@param fname str : the source Reference field name
470 470
     #@param fdh DataHandler : the source Reference DataHandler
@@ -520,7 +520,7 @@ have expected value. Expected was %s but found %s in %s" % (
520 520
                 return bref_val
521 521
             elif oldd and not newdd:
522 522
                 #deletion
523
-                if not hasattr(bref_dh, "default"): 
523
+                if not hasattr(bref_dh, "default"):
524 524
                     raise MongoDbConsistencyError("Unable to delete a \
525 525
 value for a back reference update. The concerned field don't have a default \
526 526
 value : in %s field %s" % (bref_leo,fname))
@@ -528,7 +528,7 @@ value : in %s field %s" % (bref_leo,fname))
528 528
             elif not oldd and newdd:
529 529
                 bref_val = tuid
530 530
         return bref_val
531
-    
531
+
532 532
     ##@brief Fetch back reference informations
533 533
     #@warning thank's to __update_backref_act() this method is useless
534 534
     #@param bref_cls LeObject child class : __back_reference[0]
@@ -608,7 +608,7 @@ on non abstract childs" % act.__name__)
608 608
             port = self.__db_infos['port'],
609 609
             db_name = db_name,
610 610
             ro = ro)
611
-        
611
+
612 612
         self.__conn_hash = conn_h = hash(conn_string)
613 613
         if conn_h in self._connections:
614 614
             self._connections[conn_h]['conn_count'] += 1
@@ -619,7 +619,7 @@ on non abstract childs" % act.__name__)
619 619
                 'conn_count': 1,
620 620
                 'db': utils.connect(conn_string)}
621 621
             return self._connections[conn_h]['db'][self.__db_infos['db_name']]
622
-                    
622
+
623 623
 
624 624
     ##@brief Return a pymongo collection given a LeObject child class
625 625
     #@param leobject LeObject child class (no instance)
@@ -760,7 +760,7 @@ on non abstract childs" % act.__name__)
760 760
                     rfilters[fname][repr_leo][rfield] = list()
761 761
                 rfilters[fname][repr_leo][rfield].append((op, value))
762 762
         return rfilters
763
-    
763
+
764 764
     ##@brief Convert lodel2 filters to pymongo conditions
765 765
     #@param filters list : list of lodel filters
766 766
     #@return dict representing pymongo conditions
@@ -859,7 +859,7 @@ field/operator couple in a query. We will keep only the first one")
859 859
             1 if (a[fname]>b[fname] if cmpdir == 'ASC' else a[fname]<b[fname])\
860 860
             else -1)
861 861
 
862
-    
862
+
863 863
     ##@brief Correct some datas before giving them to pymongo
864 864
     #
865 865
     #For example sets has to be casted to lise
@@ -874,13 +874,3 @@ field/operator couple in a query. We will keep only the first one")
874 874
                 #with sets
875 875
                 datas[dname] = list(datas[dname])
876 876
         return datas
877
-
878
-    ##@brief Tool to check if a record with unique id uid is set in the target_class representation
879
-    #@param target_class : class to check in 
880
-    #@param uid : a unique id in target_class
881
-    #@returns true if a record with unique id uid exists in the target_class representation, false if not
882
-    def is_exist(self, target_class, uid):
883
-    # retrouver la table qui correspond à target_class
884
-    # vérifier qu'il existe, ou pas, un enregistrement contenant uid
885
-        result = self.select(self, target_class, [target_class.uid_fieldname], filters = [(target_class.uid_fieldname, '=', uid)])
886
-        return len(result) == 1

+ 13
- 13
tests/editorial_model/test_model.py View File

@@ -23,7 +23,7 @@ class EditorialModelTestCase(unittest.TestCase):
23 23
         grp1.add_components((cls1, c1f1))
24 24
         grp2 = model.new_group('testgroup2')
25 25
         grp2.add_components((cls2, c1f2, c2f1, c2f2))
26
-        grp2.add_dependencie(grp1)
26
+        grp2.add_dependency(grp1)
27 27
         e_hash = 0x250eab75e782e51bbf212f47c6159571
28 28
         self.assertEqual(model.d_hash(), e_hash)
29 29
 
@@ -181,10 +181,10 @@ class EmGroupTestCase(unittest.TestCase):
181 181
         grp3 = EmGroup('grp3')
182 182
         grp4 = EmGroup('grp4')
183 183
 
184
-        grp2.add_dependencie(grp1)
185
-        grp3.add_dependencie(grp2)
186
-        grp4.add_dependencie(grp2)
187
-        grp4.add_dependencie(grp1)
184
+        grp2.add_dependency(grp1)
185
+        grp3.add_dependency(grp2)
186
+        grp4.add_dependency(grp2)
187
+        grp4.add_dependency(grp1)
188 188
 
189 189
         self.assertEqual(set(grp1.dependencies().values()), set())
190 190
         self.assertEqual(set(grp2.dependencies().values()), set([grp1]))
@@ -261,10 +261,10 @@ class EmGroupTestCase(unittest.TestCase):
261 261
     def test_deps_complex(self):
262 262
         """ More complex dependencies handling test """
263 263
         grps = [ EmGroup('group%d' % i) for i in range(6) ]
264
-        grps[5].add_dependencie( (grps[1], grps[2], grps[4]) )
265
-        grps[4].add_dependencie( (grps[1], grps[3]) )
266
-        grps[3].add_dependencie( (grps[0],) )
267
-        grps[1].add_dependencie( (grps[2], grps[0]) )
264
+        grps[5].add_dependency( (grps[1], grps[2], grps[4]) )
265
+        grps[4].add_dependency( (grps[1], grps[3]) )
266
+        grps[3].add_dependency( (grps[0],) )
267
+        grps[1].add_dependency( (grps[2], grps[0]) )
268 268
         self.assertEqual(
269 269
                             set(grps[5].dependencies(True).values()),
270 270
                             set( grps[i] for i in range(5))
@@ -273,7 +273,7 @@ class EmGroupTestCase(unittest.TestCase):
273 273
                             set(grps[4].dependencies(True).values()),
274 274
                             set( grps[i] for i in range(4))
275 275
         )
276
-        grps[2].add_dependencie(grps[0])
276
+        grps[2].add_dependency(grps[0])
277 277
         self.assertEqual(
278 278
                             set(grps[5].dependencies(True).values()),
279 279
                             set( grps[i] for i in range(5))
@@ -284,18 +284,18 @@ class EmGroupTestCase(unittest.TestCase):
284 284
         )
285 285
         # Inserting circular deps
286 286
         with self.assertRaises(EditorialModelError):
287
-            grps[0].add_dependencie(grps[5])
287
+            grps[0].add_dependency(grps[5])
288 288
 
289 289
     def test_circular_dep(self):
290 290
         """ Test circular dependencies detection """
291 291
         grps = [ EmGroup('group%d' % i) for i in range(10) ]
292 292
         for i in range(1,10):
293
-            grps[i].add_dependencie(grps[i-1])
293
+            grps[i].add_dependency(grps[i-1])
294 294
 
295 295
         for i in range(1,10):
296 296
             for j in range(i+1,10):
297 297
                 with self.assertRaises(EditorialModelError):
298
-                    grps[i].add_dependencie(grps[j])
298
+                    grps[i].add_dependency(grps[j])
299 299
 
300 300
     def test_d_hash(self):
301 301
         """ Test the deterministic hash method """

+ 1
- 1
tests/editorial_model/test_translator_picklefile.py View File

@@ -26,7 +26,7 @@ class PickleFileTestCase(unittest.TestCase):
26 26
         grp2 = model.new_group('testgroup2')
27 27
         grp2.add_components((cls2, c1f2, c2f1, c2f2))
28 28
 
29
-        grp2.add_dependencie(grp1)
29
+        grp2.add_dependency(grp1)
30 30
         
31 31
         tmpfd, temp_file = tempfile.mkstemp()
32 32
         os.close(tmpfd)

+ 1
- 1
tests/editorial_model/test_translator_xmlfile.py View File

@@ -44,7 +44,7 @@ class XmlFileTestCase(unittest.TestCase):
44 44
         grp2 = emmodel.new_group('testgroup2')
45 45
         grp2.add_components((cls2, c1f2, c2f1, c2f2))
46 46
 
47
-        grp2.add_dependencie(grp1)
47
+        grp2.add_dependency(grp1)
48 48
         
49 49
         f_tmp, file_name = tempfile.mkstemp()
50 50
         os.close(f_tmp)

+ 3
- 3
tests/leapi/query/test_datasource.py View File

@@ -105,7 +105,7 @@ class LeQueryDatasourceTestCase(unittest.TestCase):
105 105
             [(('alias', {cls: 'firstname'}), '=', 'foo')])
106 106
         self.check_nocall(read = False, exclude = ['delete'])
107 107
         self.check_nocall(read = True)
108
-    
108
+
109 109
     @unittest.skip("Waiting references checks stack implementation")
110 110
     def test_insert(self):
111 111
         """ Testing LeInsertQuery mocking datasource """
@@ -145,8 +145,8 @@ class LeQueryDatasourceTestCase(unittest.TestCase):
145 145
         query = LeUpdateQuery(inst)
146 146
 
147 147
         with self.assertRaises(LeApiQueryError):
148
-            # Bad call, giving datas while an instance was given to __init__
149
-            query.execute(datas = {'firstname': 'ooba'})
148
+            # Bad call, giving data while an instance was given to __init__
149
+            query.execute(data = {'firstname': 'ooba'})
150 150
 
151 151
         query.execute()
152 152
         self.mockwrite.update.assert_called_once_with(

Loading…
Cancel
Save