Commit cbf48070 authored by Sylvain Thénault's avatar Sylvain Thénault
Browse files

[entity] fix cw_instantiate w/ reverse_ relation crash when either multiple...

[entity] fix cw_instantiate w/ reverse_ relation crash when either multiple entities are given or an eid instead of an entity

--HG--
branch : stable
parent c8a8fb32733b
......@@ -495,6 +495,10 @@ class CubicWebTC(TestCase):
entity.cw_attr_cache.pop('modification_date', None)
self.failUnless(entity.modification_date > olddate)
def assertItemsEqual(self, it1, it2, *args, **kwargs):
it1 = set(getattr(x, 'eid', x) for x in it1)
it2 = set(getattr(x, 'eid', x) for x in it2)
super(CubicWebTC, self).assertItemsEqual(it1, it2, *args, **kwargs)
# workflow utilities #######################################################
......
......@@ -270,6 +270,7 @@ class Entity(AppObject):
restrictions = set()
pending_relations = []
eschema = cls.e_schema
qargs = {}
for attr, value in kwargs.items():
if attr.startswith('reverse_'):
attr = attr[len('reverse_'):]
......@@ -283,10 +284,11 @@ class Entity(AppObject):
value = iter(value).next()
else:
# prepare IN clause
del kwargs[attr]
pending_relations.append( (attr, value) )
pending_relations.append( (attr, role, value) )
continue
if hasattr(value, 'eid'): # non final relation
if rschema.final: # attribute
relations.append('X %s %%(%s)s' % (attr, attr))
else:
rvar = attr.upper()
if role == 'object':
relations.append('%s %s X' % (rvar, attr))
......@@ -295,21 +297,21 @@ class Entity(AppObject):
restriction = '%s eid %%(%s)s' % (rvar, attr)
if not restriction in restrictions:
restrictions.add(restriction)
kwargs[attr] = value.eid
else: # attribute
relations.append('X %s %%(%s)s' % (attr, attr))
if hasattr(value, 'eid'):
value = value.eid
qargs[attr] = value
if relations:
rql = '%s: %s' % (rql, ', '.join(relations))
if restrictions:
rql = '%s WHERE %s' % (rql, ', '.join(restrictions))
created = execute(rql, kwargs).get_entity(0, 0)
for attr, values in pending_relations:
if attr.startswith('reverse_'):
restr = 'Y %s X' % attr[len('reverse_'):]
created = execute(rql, qargs).get_entity(0, 0)
for attr, role, values in pending_relations:
if role == 'object':
restr = 'Y %s X' % attr
else:
restr = 'X %s Y' % attr
execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % (
restr, ','.join(str(r.eid) for r in values)),
restr, ','.join(str(getattr(r, 'eid', r)) for r in values)),
{'x': created.eid}, build_descr=False)
return created
......
......@@ -139,6 +139,27 @@ class EntityTC(CubicWebTC):
self.assertEqual(len(p.related('tags', 'object', limit=2)), 2)
self.assertEqual(len(p.related('tags', 'object')), 4)
def test_cw_instantiate_relation(self):
req = self.request()
p1 = req.create_entity('Personne', nom=u'di')
p2 = req.create_entity('Personne', nom=u'mascio')
t = req.create_entity('Tag', name=u't1', tags=p1)
self.assertItemsEqual(t.tags, [p1])
t = req.create_entity('Tag', name=u't2', tags=p1.eid)
self.assertItemsEqual(t.tags, [p1])
t = req.create_entity('Tag', name=u't3', tags=[p1, p2.eid])
self.assertItemsEqual(t.tags, [p1, p2])
def test_cw_instantiate_reverse_relation(self):
req = self.request()
t1 = req.create_entity('Tag', name=u't1')
t2 = req.create_entity('Tag', name=u't2')
p = req.create_entity('Personne', nom=u'di mascio', reverse_tags=t1)
self.assertItemsEqual(p.reverse_tags, [t1])
p = req.create_entity('Personne', nom=u'di mascio', reverse_tags=t1.eid)
self.assertItemsEqual(p.reverse_tags, [t1])
p = req.create_entity('Personne', nom=u'di mascio', reverse_tags=[t1, t2.eid])
self.assertItemsEqual(p.reverse_tags, [t1, t2])
def test_fetch_rql(self):
user = self.user()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment