mirror of
https://github.com/yweber/lodel2.git
synced 2025-11-30 08:36:53 +01:00
Implements handling of relation_name field in relation common fields
This commit is contained in:
parent
da89046c33
commit
37edad7b1f
9 changed files with 55 additions and 38 deletions
|
|
@ -112,8 +112,8 @@ class _LeCrud(object):
|
|||
# @param name str : The name
|
||||
# @return name.title()
|
||||
@staticmethod
|
||||
def name2rel2type(class_name, type_name):
|
||||
cls_name = "Rel_%s2%s"%(_LeCrud.name2classname(class_name), _LeCrud.name2classname(type_name))
|
||||
def name2rel2type(class_name, type_name, relation_name):
|
||||
cls_name = "Rel%s%s%s"%(_LeCrud.name2classname(class_name), _LeCrud.name2classname(type_name), relation_name.title())
|
||||
return cls_name
|
||||
|
||||
## @brief Given a dynamically generated class name return the corresponding python Class
|
||||
|
|
@ -412,10 +412,9 @@ class _LeCrud(object):
|
|||
def insert(cls, datas, classname=None):
|
||||
callcls = cls if classname is None else cls.name2class(classname)
|
||||
if not callcls:
|
||||
raise LeApiErrors("Error when inserting",[ValueError("The class '%s' was not found"%classname)])
|
||||
raise LeApiErrors("Error when inserting",{'error':ValueError("The class '%s' was not found"%classname)})
|
||||
if not callcls.implements_letype() and not callcls.implements_lerelation():
|
||||
raise ValueError("You can only insert relations and LeTypes objects but tying to insert a '%s'"%callcls.__name__)
|
||||
|
||||
insert_datas = callcls.prepare_datas(datas, complete = True, allow_internal = False)
|
||||
return callcls._datasource.insert(callcls, **insert_datas)
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ class LeFactory(object):
|
|||
for field in [ f for f in model.components('EmField') if f.fieldtype == 'rel2type']:
|
||||
related = model.component(field.rel_to_type_id)
|
||||
src = field.em_class
|
||||
cls_name = _LeCrud.name2rel2type(src.name, related.name)
|
||||
cls_name = _LeCrud.name2rel2type(src.name, related.name, field.name)
|
||||
relation_name = field.name
|
||||
|
||||
attr_l = dict()
|
||||
for attr in [ f for f in model.components('EmField') if f.rel_field_id == field.uid]:
|
||||
|
|
@ -87,12 +88,14 @@ class {classname}(LeRel2Type):
|
|||
_rel_attr_fieldtypes = {attr_dict}
|
||||
_superior_cls = {supcls}
|
||||
_subordinate_cls = {subcls}
|
||||
_relation_name = {relation_name}
|
||||
|
||||
""".format(
|
||||
classname = cls_name,
|
||||
attr_dict = "{" + (','.join(['\n %s: %s' % (repr(f), v) for f,v in attr_l.items()])) + "\n}",
|
||||
supcls = _LeCrud.name2classname(src.name),
|
||||
subcls = _LeCrud.name2classname(related.name),
|
||||
relation_name = repr(relation_name),
|
||||
)
|
||||
res_code += rel_code
|
||||
return res_code
|
||||
|
|
@ -104,11 +107,11 @@ class {classname}(LeRel2Type):
|
|||
def emclass_pycode(self, model, emclass):
|
||||
|
||||
cls_fields = dict()
|
||||
cls_linked_types = list() #Stores authorized LeObject for rel2type
|
||||
cls_linked_types = dict() # Stores rel2type referenced by fieldname
|
||||
#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(_LeCrud.name2classname(model.component(fti.rel_to_type_id).name))
|
||||
cls_linked_types[rfield.name] = _LeCrud.name2classname(model.component(fti.rel_to_type_id).name)
|
||||
# Populating fieldtype attr
|
||||
for field in emclass.fields(relational = False):
|
||||
self.needed_fieldtypes |= set([field.fieldtype])
|
||||
|
|
@ -123,8 +126,8 @@ class {classname}(LeRel2Type):
|
|||
""".format(
|
||||
name = _LeCrud.name2classname(emclass.name),
|
||||
ftypes = "{" + (','.join(['\n %s: %s' % (repr(f), v) for f, v in cls_fields.items()])) + "\n}",
|
||||
ltypes = "{" + (','.join(['\n %s: %s' % (repr(f), v) for f, v in cls_linked_types.items()])) + "\n}",
|
||||
|
||||
ltypes = "[" + (','.join(cls_linked_types))+"]",
|
||||
classtype = repr(emclass.classtype)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ class _LeHierarch(_LeRelation):
|
|||
@classmethod
|
||||
def insert(cls, datas):
|
||||
# Checks if the relation exists
|
||||
datas[EditorialModel.classtypes.relation_name] = None
|
||||
res = cls.get(
|
||||
[(cls._subordinate_field_name, '=', datas['subordinate']), ('nature', '=', datas['nature'])],
|
||||
[ cls.uidname() ]
|
||||
|
|
@ -201,8 +202,10 @@ class _LeRel2Type(_LeRelation):
|
|||
|
||||
## @brief Stores the LeClass child class used as superior
|
||||
_superior_cls = None
|
||||
## @biref Stores the LeType child class used as subordinate
|
||||
## @brief Stores the LeType child class used as subordinate
|
||||
_subordinate_cls = None
|
||||
## @brief Stores the relation name for a rel2type
|
||||
_relation_name = None
|
||||
|
||||
## @brief Delete current instance from DB
|
||||
def delete(self):
|
||||
|
|
@ -232,21 +235,31 @@ class _LeRel2Type(_LeRelation):
|
|||
#Set the nature
|
||||
if 'nature' not in datas:
|
||||
datas['nature'] = None
|
||||
if cls == cls.name2class('LeRel2Type') and classname is None:
|
||||
# autodetect the rel2type child class
|
||||
classname = relname(datas[self._superior_field_name], datas[self._subordinate_field_name])
|
||||
if cls.__name__ == 'LeRel2Type' and classname is None:
|
||||
if EditorialModel.classtypes.relation_name not in datas:
|
||||
raise RuntimeError("Unable to autodetect rel2type. No relation_name given")
|
||||
# autodetect the rel2type child class (BROKEN)
|
||||
classname = relname(datas[self._superior_field_name], datas[self._subordinate_field_name], datas[EditorialModel.classtypes.relation_name])
|
||||
else:
|
||||
if classname != None:
|
||||
ccls = cls.name2class(classname)
|
||||
if ccls == False:
|
||||
raise lecrud.LeApiErrors("Bad classname given")
|
||||
relation_name = ccls._relation_name
|
||||
else:
|
||||
relation_name = cls._relation_name
|
||||
datas[EditorialModel.classtypes.relation_name] = relation_name
|
||||
return super().insert(datas, classname)
|
||||
|
||||
## @brief Given a superior and a subordinate, returns the classname of the give rel2type
|
||||
# @param lesupclass LeClass : LeClass child class (not an instance) (can be a LeType or a LeClass child)
|
||||
# @param lesubclass LeType : A LeType child class (not an instance)
|
||||
# @return a name as string
|
||||
@staticmethod
|
||||
def relname(lesupclass, lesubclass):
|
||||
@classmethod
|
||||
def relname(cls, lesupclass, lesubclass, relation_name):
|
||||
supname = lesupclass._leclass.__name__ if lesupclass.implements_letype() else lesupclass.__name__
|
||||
subname = lesubclass.__name__
|
||||
|
||||
return "Rel_%s2%s" % (supname, subname)
|
||||
return cls.name2rel2type(supname, subname, relation_name)
|
||||
|
||||
## @brief instanciate the relevant lodel object using a dict of datas
|
||||
@classmethod
|
||||
|
|
@ -254,7 +267,7 @@ class _LeRel2Type(_LeRelation):
|
|||
le_object = cls.name2class('LeObject')
|
||||
class_name = le_object._me_uid[datas['class_id']].__name__
|
||||
type_name = le_object._me_uid[datas['type_id']].__name__
|
||||
relation_classname = lecrud._LeCrud.name2rel2type(class_name, type_name)
|
||||
relation_classname = lecrud._LeCrud.name2rel2type(class_name, type_name, EditorialModel.classtypes.relation_name)
|
||||
|
||||
del(datas['class_id'], datas['type_id'])
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
# @note LeObject will be generated by leapi.lefactory.LeFactory
|
||||
|
||||
import leapi
|
||||
import EditorialModel.classtypes as lodel2const
|
||||
from leapi.lecrud import _LeCrud, LeApiDataCheckError, LeApiQueryError
|
||||
from leapi.leclass import _LeClass
|
||||
from leapi.leobject import LeObjectError
|
||||
|
|
@ -90,15 +91,17 @@ class _LeType(_LeClass):
|
|||
# @note This methods asser that self is the superior and leo_tolink the subordinate
|
||||
#
|
||||
# @param leo_tolink LeObject : LeObject child instance to link with
|
||||
# @param **datas : Relation attributes (if any)
|
||||
# @param relation_name str : Name of the relation (the fieldname of the rel2type in the EmClass)
|
||||
# @param datas dict : Relation attributes (if any)
|
||||
# @return a relation id if success
|
||||
def link_with(self, leo_tolink, datas):
|
||||
def link_with(self, leo_tolink, relation_name, datas):
|
||||
# Fetch rel2type leapi class
|
||||
r2t = self.name2class('LeRel2Type')
|
||||
class_name = r2t.relname(self, leo_tolink.__class__)
|
||||
class_name = r2t.relname(self, leo_tolink.__class__, relation_name)
|
||||
r2tcls = self.name2class(class_name)
|
||||
if not r2tcls:
|
||||
raise ValueError("No rel2type possible between a '%s' as superior and a '%s' as subordinate" % (self._leclass.__name__, leo_tolink.__class__.__name__))
|
||||
datas['superior'] = self
|
||||
datas['subordinate'] = leo_tolink
|
||||
datas[lodel2const.relation_name] = relation_name
|
||||
return r2tcls.insert(datas, class_name)
|
||||
|
|
|
|||
|
|
@ -416,8 +416,8 @@ class LeCrudTestCase(TestCase):
|
|||
r2t_lst = list()
|
||||
for leo in leo_lst:
|
||||
if leo.is_leclass() and hasattr(leo, '_linked_types'):
|
||||
for relleo in leo._linked_types:
|
||||
r2t_lst.append(LeRel2Type.relname(leo, relleo))
|
||||
for relation_name, relleo in leo._linked_types.items():
|
||||
r2t_lst.append(LeRel2Type.relname(leo, relleo, relation_name))
|
||||
leo_lst = [cls.__name__ for cls in leo_lst]
|
||||
|
||||
# Begin test
|
||||
|
|
@ -454,6 +454,6 @@ class LeCrudTestCase(TestCase):
|
|||
|
||||
def test_typeasserts(self):
|
||||
""" Tests te implements_le* and is_le* methods """
|
||||
from dyncode import LeObject, LeCrud, LeRelation, LeHierarch, LeRel2Type, Article, Textes, Rel_Textes2Personne
|
||||
from dyncode import LeObject, LeCrud, LeRelation, LeHierarch, LeRel2Type, Article, Textes, RelTextesPersonneAuteur
|
||||
|
||||
self.assertTrue(LeObject.is_leobject())
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class TestLeFactory(TestCase):
|
|||
#Testing _linked_types attr
|
||||
self.assertEqual(
|
||||
set([ LeCrud.name2classname(lt.name) for lt in emclass.linked_types()]),
|
||||
set([ t.__name__ for t in leclass._linked_types ])
|
||||
set([ t.__name__ for t in leclass._linked_types.values() ])
|
||||
)
|
||||
|
||||
#Testing fieldtypes
|
||||
|
|
|
|||
|
|
@ -117,7 +117,6 @@ class LeHierarch(LeRelationTestCase):
|
|||
self.assertEqual(len(cargs), 2)
|
||||
cargs=cargs[1]
|
||||
self.assertEqual(cargs['target_cls'], target, "%s != %s"%(cargs, eargs))
|
||||
print("FUCK : ", cargs['field_list'])
|
||||
self.assertEqual(set(cargs['field_list']), set(field_ds), "%s != %s"%(cargs, eargs))
|
||||
self.assertEqual(cargs['filters'], filters_ds, "%s != %s"%(cargs, eargs))
|
||||
self.assertEqual(cargs['rel_filters'], rfilters_ds, "%s != %s"%(cargs, eargs))
|
||||
|
|
@ -219,7 +218,7 @@ class LeRel2TypeTestCase(LeRelationTestCase):
|
|||
@patch('DataSource.dummy.leapidatasource.DummyDatasource.insert')
|
||||
def test_insert(self, dsmock):
|
||||
""" test LeHierach update method"""
|
||||
from dyncode import LeObject, Article, Textes, Personne, Personnes, LeHierarch, LeRel2Type, Rel_Textes2Personne
|
||||
from dyncode import LeObject, Article, Textes, Personne, Personnes, LeHierarch, LeRel2Type, RelTextesPersonneAuteur
|
||||
|
||||
queries = [
|
||||
{
|
||||
|
|
@ -245,7 +244,7 @@ class LeRel2TypeTestCase(LeRelationTestCase):
|
|||
]
|
||||
|
||||
for query in queries:
|
||||
Rel_Textes2Personne.insert(query)
|
||||
RelTextesPersonneAuteur.insert(query)
|
||||
|
||||
eres = {
|
||||
'nature': None,
|
||||
|
|
@ -258,18 +257,19 @@ class LeRel2TypeTestCase(LeRelationTestCase):
|
|||
if isinstance(eres[fname], int):
|
||||
eres[fname] = LeObject(eres[fname])
|
||||
|
||||
dsmock.assert_called_once_with(Rel_Textes2Personne, **eres)
|
||||
dsmock.assert_called_once_with(RelTextesPersonneAuteur, **eres)
|
||||
dsmock.reset_mock()
|
||||
|
||||
LeRel2Type.insert(query, "Rel_Textes2Personne")
|
||||
|
||||
dsmock.assert_called_once_with(Rel_Textes2Personne, **eres)
|
||||
|
||||
query[EditorialModel.classtypes.relation_name] = 'auteur'
|
||||
LeRel2Type.insert(query, "RelTextesPersonneAuteur")
|
||||
|
||||
dsmock.assert_called_once_with(RelTextesPersonneAuteur, **eres)
|
||||
dsmock.reset_mock()
|
||||
|
||||
@patch('DataSource.dummy.leapidatasource.DummyDatasource.insert')
|
||||
def test_insert_fails(self, dsmock):
|
||||
""" test LeHierach update method"""
|
||||
from dyncode import LeObject, Rubrique, Numero, Article, Textes, Personne, Personnes, LeHierarch, LeRel2Type, Rel_Textes2Personne
|
||||
from dyncode import LeObject, Rubrique, Numero, Article, Textes, Personne, Personnes, LeHierarch, LeRel2Type, RelTextesPersonneAuteur
|
||||
|
||||
queries = [
|
||||
{
|
||||
|
|
@ -304,10 +304,10 @@ class LeRel2TypeTestCase(LeRelationTestCase):
|
|||
self.fail("No exception raised")
|
||||
except Exception as e:
|
||||
if not isinstance(e, lecrud.LeApiErrors) and not isinstance(e, lecrud.LeApiDataCheckError):
|
||||
self.fail("Bad exception raised : ", e)
|
||||
self.fail("Bad exception raised : "+str(e))
|
||||
|
||||
try:
|
||||
Rel_Textes2Personne.insert(query)
|
||||
RelTextesPersonneAuteur.insert(query)
|
||||
self.fail("No exception raised")
|
||||
except Exception as e:
|
||||
if not isinstance(e, lecrud.LeApiErrors) and not isinstance(e, lecrud.LeApiDataCheckError):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue