# HG changeset patch # User Sylvain Thénault # Date 1305274194 -7200 # Node ID 38524ca653e50264be1eb54b0d25bb5fe2bf80ef # Parent c8a8fb32733b1ce67b22d480d3709929a7622ab3 [entity] fix cw_instantiate w/ reverse_ relation crash when either multiple entities are given or an eid instead of an entity diff -r c8a8fb32733b -r 38524ca653e5 devtools/testlib.py --- a/devtools/testlib.py Fri May 13 10:09:52 2011 +0200 +++ b/devtools/testlib.py Fri May 13 10:09:54 2011 +0200 @@ -495,6 +495,10 @@ 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 ####################################################### diff -r c8a8fb32733b -r 38524ca653e5 entity.py --- a/entity.py Fri May 13 10:09:52 2011 +0200 +++ b/entity.py Fri May 13 10:09:54 2011 +0200 @@ -270,6 +270,7 @@ 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 @@ 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 @@ 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 diff -r c8a8fb32733b -r 38524ca653e5 test/unittest_entity.py --- a/test/unittest_entity.py Fri May 13 10:09:52 2011 +0200 +++ b/test/unittest_entity.py Fri May 13 10:09:54 2011 +0200 @@ -139,6 +139,27 @@ 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()