Browse Source

The automatic UID creation by datasource implementation implies somes changes :

	The UniqID datahandler has to call the datasource
	LeObject has to be able to determine wich parent class define its UID datahandler
	[NOT IMPLEMENTED] the datasource should be able to select with an abstract LeObject as target ( see #92 )
Yann Weber 8 years ago
parent
commit
6e89fca151

+ 7
- 0
em_test.py View File

@@ -19,11 +19,18 @@ base_group = em.new_group(  'base_group',
19 19
 ####################
20 20
 #   Lodel Object   #
21 21
 ####################
22
+em_abstract = em.new_class( 'abstract_object',
23
+    display_name = 'Abstract lodel object',
24
+    help_text = 'For testing purpose',
25
+    group = base_group,
26
+    abstract = True)
27
+
22 28
 em_object = em.new_class(   'object',
23 29
                             display_name = 'Object',
24 30
                             help_text = 'Main class for all Em objects',
25 31
                             group = base_group,
26 32
                             abstract = True,
33
+                            parents = em_abstract,
27 34
 )
28 35
 em_object.new_field(    'lodel_id',
29 36
                         display_name = 'Lodel identifier',

BIN
examples/em_test.pickle View File


+ 6
- 0
lodel/leapi/datahandlers/datas.py View File

@@ -75,6 +75,12 @@ class UniqID(Integer):
75 75
     def _check_data_value(self, value):
76 76
         return value, None
77 77
 
78
+    def construct_data(self, emcomponent, fname, datas, cur_value):
79
+        if cur_value is None:
80
+            #Ask datasource to provide a new uniqID
81
+            return emcomponent._ro_datasource.new_numeric_id(emcomponent)
82
+        return cur_value
83
+
78 84
 class LeobjectSubclassIdentifier(Varchar):
79 85
     
80 86
     help = 'Datahandler designed to handle LeObject subclass identifier in DB'

+ 1
- 0
lodel/leapi/datahandlers/datas_base.py View File

@@ -93,6 +93,7 @@ class DateTime(DataField):
93 93
     def construct_data(self, emcomponent, fname, datas, cur_value):
94 94
         if (self.now_on_create and cur_value is None) or self.now_on_update:
95 95
             return datetime.datetime.now()
96
+        return cur_value
96 97
 
97 98
 ##@brief Data field designed to handle long string
98 99
 class Text(DataField):

+ 39
- 0
lodel/leapi/leobject.py View File

@@ -181,6 +181,45 @@ class LeObject(object):
181 181
     def fields(cls):
182 182
         return copy.copy(cls._fields)
183 183
     
184
+    ##@brief Return the list of parents classes
185
+    #
186
+    #@note the first item of the list is the current class, the second is it's
187
+    #parent etc...
188
+    #@param cls
189
+    #@warning multiple inheritance broken by this method
190
+    #@return a list of LeObject child classes
191
+    #@todo multiple parent capabilities implementation
192
+    @classmethod
193
+    def hierarch(cls):
194
+        res = [cls]
195
+        cur = cls
196
+        while True:
197
+            cur = cur.__bases__[0] # Multiple inheritance broken HERE
198
+            if cur in (LeObject, object):
199
+                break
200
+            else:
201
+                res.append(cur)
202
+        return res
203
+    
204
+    ##@brief Return the parent class that is the "source" of uid
205
+    #
206
+    #The method goal is to return the parent class that defines UID.
207
+    #@return a LeObject child class or false if no UID defined
208
+    @classmethod
209
+    def uid_source(cls):
210
+        if cls._uid is None or len(cls._uid) == 0:
211
+            return False
212
+        hierarch = cls.hierarch()
213
+        prev = hierarch[0]
214
+        uid_handlers = set( cls._fields[name] for name in cls._uid )
215
+        for pcls in cls.hierarch()[1:]:
216
+            puid_handlers = set(cls._fields[name] for name in pcls._uid)
217
+            if set(pcls._uid) != set(pcls._uid) \
218
+                or puid_handlers != uid_handlers:
219
+                break
220
+            prev = pcls
221
+        return prev
222
+    
184 223
     ##@brief Initialise both datasources (ro and rw)
185 224
     #
186 225
     #This method is used once at dyncode load to replace the datasource string

+ 18
- 11
plugins/dummy_datasource/datasource.py View File

@@ -5,18 +5,25 @@ class DummyDatasource(object):
5 5
     def __init__(self, *conn_args, **conn_kwargs):
6 6
         self.conn_args = conn_args
7 7
         self.conn_kwargs = conn_kwargs
8
+    
9
+    ##@brief Provide a new uniq numeric ID
10
+    #@param emcomp LeObject subclass (not instance) : To know on wich things we
11
+    #have to be uniq
12
+    #@return an integer
13
+    def new_numeric_id(self, emcomp):
14
+        pass
8 15
 
9
-    ## @brief returns a selection of documents from the datasource
10
-    # @param target_cls Emclass
11
-    # @param field_list list
12
-    # @param filters list : List of filters
13
-    # @param rel_filters list : List of relational filters
14
-    # @param order list : List of column to order. ex: order = [('title', 'ASC'),]
15
-    # @param group list : List of tupple representing the column to group together. ex: group = [('title', 'ASC'),]
16
-    # @param limit int : Number of records to be returned
17
-    # @param offset int: used with limit to choose the start record
18
-    # @param instanciate bool : If true, the records are returned as instances, else they are returned as dict
19
-    # @return list
16
+    ##@brief returns a selection of documents from the datasource
17
+    #@param target_cls Emclass
18
+    #@param field_list list
19
+    #@param filters list : List of filters
20
+    #@param rel_filters list : List of relational filters
21
+    #@param order list : List of column to order. ex: order = [('title', 'ASC'),]
22
+    #@param group list : List of tupple representing the column to group together. ex: group = [('title', 'ASC'),]
23
+    #@param limit int : Number of records to be returned
24
+    #@param offset int: used with limit to choose the start record
25
+    #@param instanciate bool : If true, the records are returned as instances, else they are returned as dict
26
+    #@return list
20 27
     def select(self, target_cls, field_list, filters, rel_filters=None, order=None, group=None, limit=None, offset=0,
21 28
                instanciate=True):
22 29
         pass

+ 17
- 1
plugins/mongodb_datasource/datasource.py View File

@@ -66,6 +66,18 @@ class MongoDbDatasource(object):
66 66
             del(self._connections[self.__conn_hash])
67 67
             logger.info("Closing connection to database")
68 68
 
69
+    ##@brief Provide a new uniq numeric ID
70
+    #@param emcomp LeObject subclass (not instance) : To know on wich things we
71
+    #have to be uniq
72
+    #@warning multiple UID broken by this method
73
+    #@return an integer
74
+    def new_numeric_id(self, emcomp):
75
+        target = emcomp.uid_source()
76
+        tuid = target._uid[0] # Multiple UID broken here
77
+        results = self.select(
78
+            target, [tuid], [], order=[(tuid, 'DESC')], limit = 1)
79
+        return results[0][tuid]+1
80
+
69 81
     ##@brief returns a selection of documents from the datasource
70 82
     #@param target Emclass
71 83
     #@param field_list list
@@ -78,7 +90,11 @@ class MongoDbDatasource(object):
78 90
     #@param instanciate bool : If true, the records are returned as instances, else they are returned as dict
79 91
     #@return list
80 92
     #@todo Implement the relations
81
-    def select(self, target, field_list, filters, rel_filters=None, order=None, group=None, limit=None, offset=0):
93
+    def select(self, target, field_list, filters = None, rel_filters=None, order=None, group=None, limit=None, offset=0):
94
+        # Default arg init
95
+        filters = [] if filters is None else filters
96
+        rel_filters = [] if rel_filters is None else rel_filters
97
+
82 98
         collection_name = object_collection_name(target)
83 99
         collection = self.database[collection_name]
84 100
         query_filters = self.__process_filters(

Loading…
Cancel
Save