Browse Source

Implements _LeObject.hierarchy_add() method and instroduce the class LeRoot

LeRoot represents hierarchy root
Yann Weber 9 years ago
parent
commit
94a5afcdd7
4 changed files with 60 additions and 3 deletions
  1. 2
    0
      DataSource/MySQL/MySQL.py
  2. 2
    2
      leobject/datasources/dummy.py
  3. 1
    1
      leobject/lefactory.py
  4. 55
    0
      leobject/leobject.py

+ 2
- 0
DataSource/MySQL/MySQL.py View File

@@ -16,6 +16,8 @@ class MySQL(object):
16 16
     ## @brief indicates if we want ON DELETE CASCADE on foreign keys
17 17
     # @todo implementation in migration handler
18 18
     fk_on_delete_cascade = False
19
+    ## @brief Lodel_id for the hierachy root
20
+    leroot_lodel_id = 0
19 21
 
20 22
     @classmethod
21 23
     ## @brief gets the table name from class name

+ 2
- 2
leobject/datasources/dummy.py View File

@@ -74,8 +74,8 @@ class DummyDatasource(object):
74 74
     ## @brief Fetch a superiors list ordered by depth for a LeType
75 75
     # @param lesub LeType : subordinate LeType child class instance
76 76
     # @param nature str : A relation nature @ref EditorialModel.classtypes
77
-    # @return A list of LeType ordered by depth
78
-    def get_superiors(self, lesub, nature):
77
+    # @return A list of LeType ordered by depth (the first is the direct superior)
78
+    def get_superiors(self, lesub, nature = None):
79 79
         pass
80 80
 
81 81
     ## @brief Fetch the list of the subordinates given a nature

+ 1
- 1
leobject/lefactory.py View File

@@ -160,7 +160,7 @@ import %s
160 160
             leobj_me_uid[comp.uid] = LeFactory.name2classname(comp.name)
161 161
 
162 162
         result += """
163
-## @brief _LeObject concret clas
163
+## @brief _LeObject concret class
164 164
 # @see leobject::leobject::_LeObject
165 165
 class LeObject(_LeObject):
166 166
     _model = Model(backend=%s)

+ 55
- 0
leobject/leobject.py View File

@@ -67,6 +67,20 @@ class _LeObject(object):
67 67
             letype.check_datas_or_raise(data, complete = True)
68 68
         return cls._datasource.insert(letype, leclass, datas)
69 69
     
70
+    ## @brief Check if a LeType is a hierarchy root
71
+    @staticmethod
72
+    def is_root(leo):
73
+        if isinstance(leo, leobject.letype.LeType):
74
+            return False
75
+        elif isinstance(leo, LeRoot):
76
+            return True
77
+        raise ValueError("Invalid value for a LeType : %s"%leo)
78
+    
79
+    ## @brief Return a LeRoot instance
80
+    @staticmethod
81
+    def get_root():
82
+        return LeRoot()
83
+
70 84
     ## @brief Delete LeObjects given filters
71 85
     # @param cls
72 86
     # @param letype LeType|str : LeType child class or name
@@ -216,6 +230,42 @@ class _LeObject(object):
216 230
 
217 231
         return cls._datasource.del_related(lesup, lesub)
218 232
     
233
+    ## @brief Add a hierarchy relation between two LeObject
234
+    # @param lesup LeType|LeRoot : LeType child class instance
235
+    # @param lesub LeType : LeType child class instance
236
+    # @param nature str : The nature of the relation @ref EditorialModel.classtypes
237
+    # @param rank str|int :  The relation rank. Can be 'last', 'first' or an integer
238
+    # @param replace_if_exists bool : if True delete the old superior and set the new one. If False and there is a superior raise an LeObjectQueryError
239
+    # @return The relation ID or False if fails
240
+    # @throw LeObjectQueryError replace_if_exists == False and there is a superior
241
+    @classmethod
242
+    def hierarchy_add(cls, lesup, lesub, nature, rank = 'last', replace_if_exists = False):
243
+        #Arguments check
244
+        if nature not in EditorialModel.classtypes.EmClassType.natures(lesub._classtype):
245
+            raise ValueError("Invalid nature '%s' for %s"%(nature, lesup.__class__.__name__))
246
+
247
+        if not cls.leo_is_root(lesup):
248
+            if nature not in EditorialModel.classtypes.EmClassType.natures(lesup._classtype):
249
+                raise ValueError("Invalid nature '%s' for %s"%(nature, lesup.__class__.__name__))
250
+            if lesup.__class__ not in lesub._superiors[nature]:
251
+                raise ValueError("%s is not a valid superior for %s"%(lesup.__class__, lesub.__class__))
252
+        #else:
253
+        #   lesup is not a LeType but a hierarchy root
254
+
255
+        if rank not in ['first', 'last'] and not isinstance(rank, int):
256
+            raise ValueError("Allowed values for rank are integers and 'first' or 'last' but '%s' found"%rank)
257
+
258
+        superiors = cls.hierarchy_get(lesub, nature, leo_is_sup = False)
259
+        if lesup in len(superiors) > 0:
260
+            if not replace_if_exists:
261
+                raise LeObjectQueryError("The subordinate allready has a superior")
262
+            #remove existig superior
263
+            if not cls.hierarchy_del(superiors[0], lesub, nature):
264
+                raise RuntimeError("Unable to delete the previous superior")
265
+
266
+        return self._datasource.add_superior(lesup, lesub, nature, rank)
267
+        
268
+
219 269
     ## @brief Prepare a field_list
220 270
     # @param field_list list : List of string representing fields
221 271
     # @param letype LeType : LeType child class
@@ -385,6 +435,11 @@ class _LeObject(object):
385 435
         cls._query_re = re.compile('^\s*(?P<field>(((superior)|(subordinate))\.)?[a-z_][a-z0-9\-_]*)\s*'+op_re_piece+'\s*(?P<value>[^<>=!].*)\s*$', flags=re.IGNORECASE)
386 436
         pass
387 437
 
438
+## @brief Class designed to represent the hierarchy roots
439
+# @see _LeObject.get_root() _LeObject.is_root()
440
+class LeRoot(object):
441
+    pass
442
+
388 443
 class LeObjectError(Exception):
389 444
     pass
390 445
 

Loading…
Cancel
Save