diff --git a/leobject/lefactory.py b/leobject/lefactory.py index 012abf8..05a40d1 100644 --- a/leobject/lefactory.py +++ b/leobject/lefactory.py @@ -64,11 +64,13 @@ class LeFactory(object): @staticmethod def emclass_pycode(model, emclass): cls_fields = dict() - cls_linked_types = list() + cls_linked_types = dict() #keys are LeType classnames and values are tuples (attr_fieldname, attr_fieldtype) #Populating linked_type attr for rfield in [ f for f in emclass.fields() if f.fieldtype == 'rel2type']: fti = rfield.fieldtype_instance() - cls_linked_types.append(LeFactory.name2classname(model.component(fti.rel_to_type_id).name)) + cls_linked_types[LeFactory.name2classname(model.component(fti.rel_to_type_id).name)] = [ + (f.name, LeFactory.fieldtype_construct_from_field(f)) for f in model.components('EmField') if f.rel_field_id == rfield.uid + ] # Populating fieldtype attr for field in emclass.fields(relational = False): cls_fields[field.name] = LeFactory.fieldtype_construct_from_field(field) @@ -90,7 +92,16 @@ class LeFactory(object): """.format( name = LeFactory.name2classname(emclass.name), ftypes = "{" + (','.join(['\n\t%s:%s' % (repr(f), v) for f, v in cls_fields.items()])) + "\n}", - ltypes = "{" + (','.join(cls_linked_types)) + '}', + + ltypes = '{'+ (','.join( + [ + '\n\t{ltname}:{ltattr_list}'.format( + ltname = lt, + ltattr_list = '['+(','.join([ + '(%s,%s)'%(repr(ltname), ltftype) for ltname, ltftype in ltattr + ]))+']' + ) for lt, ltattr in cls_linked_types.items() + ]))+'}', fgroups = repr(cls_fieldgroup), classtype = repr(emclass.classtype) ) diff --git a/leobject/letype.py b/leobject/letype.py index 2beadb6..3483cf5 100644 --- a/leobject/letype.py +++ b/leobject/letype.py @@ -99,7 +99,7 @@ class LeType(object): def del_superior(self, leo, nature): if nature is None: raise ValueError('The argument nature cannot be None') - return self._datasource(leo.lodel_id, self.lodel_id, nature) + return self._datasource(leo, self, nature) ## @brief Get the linked objects lodel_id # @return an array of lodel_id linked with this object @@ -110,20 +110,28 @@ class LeType(object): ## @brief Link this object with a LeObject # @note rel2type # @param leo LeObject : The object to be linked with + # @param **rel_attr : keywords arguments for relations attributes # @return True if success False allready done # @throw A Leo exception if the link is not allowed # @todo unit tests # @todo find a value for depth and rank.... - def link_to(self, leo): - if leo.__class__ not in self._linked_types: + def link_to(self, leo, **rel_attr): + if leo.__class__ not in self._linked_types.keys(): raise leobject.leobject.LeObjectError("Constraint error : %s cannot be linked with %s"%(self.__class__.__name__, leo.__class__.__name__)) - return self._datasource.add_relation(self.lodel_id, leo.lodel_id) + + for attr_name in rel_attr.keys(): + if attr_name not in [ f for f,g in self._linked_types[leo.__class__] ]: + raise AttributeError("A rel2type between a %s and a %s doesn't have an attribute %s"%(self.__class__.__name__, leo.__class__.__name__, attr_name)) + if not self._linked_types[leo.__class__][1].check(rel_attr[attr_name]): + raise ValueError("Wrong value '%s' for attribute %s"%(rel_attr[attr_name], attr_name)) + + return self._datasource.add_relation(self, leo, nature=None, depth=None, rank=None, **rel_attr) ## @brief Remove a link bewteen this object and another # @param leo LeObject : A LeObject instance linked with self # @todo unit tests def unlink(self, leo): - return self._datasource.del_relation(self.lodel_id, leo.lodel_id) + return self._datasource.del_relation(self, leo) ## @brief Delete a LeType from the datasource # @param filters list : list of filters (see @ref leobject_filters)