# HG changeset patch # User Sylvain Thénault # Date 1305274219 -7200 # Node ID d8083b2ae4d6f3d011087d846f3eae4ac4038d49 # Parent f1d9e3b9e51e47dbbe33ffbf3139d9aa3223a708# Parent 38524ca653e50264be1eb54b0d25bb5fe2bf80ef backport stable diff -r f1d9e3b9e51e -r d8083b2ae4d6 cwctl.py --- a/cwctl.py Wed May 11 13:41:21 2011 +0200 +++ b/cwctl.py Fri May 13 10:10:19 2011 +0200 @@ -905,6 +905,7 @@ scripts, args = self.cmdline_parser.largs[1:], self.cmdline_parser.rargs for script in scripts: mih.cmd_process_script(script, scriptargs=args) + mih.commit() else: mih.interactive_shell() finally: diff -r f1d9e3b9e51e -r d8083b2ae4d6 devtools/testlib.py --- a/devtools/testlib.py Wed May 11 13:41:21 2011 +0200 +++ b/devtools/testlib.py Fri May 13 10:10:19 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 f1d9e3b9e51e -r d8083b2ae4d6 entities/authobjs.py --- a/entities/authobjs.py Wed May 11 13:41:21 2011 +0200 +++ b/entities/authobjs.py Fri May 13 10:10:19 2011 +0200 @@ -29,9 +29,21 @@ fetch_attrs, fetch_order = fetch_config(['name']) fetch_unrelated_order = fetch_order - def db_key_name(self): - """XXX goa specific""" - return self.get('name') + def grant_permission(self, entity, pname, plabel=None): + """grant local `pname` permission on `entity` to this group using + :class:`CWPermission`. + + If a similar permission already exists, add the group to it, else create + a new one. + """ + if not self._cw.execute( + 'SET X require_group G WHERE E eid %(e)s, G eid %(g)s, ' + 'E require_permission X, X name %(name)s, X label %(label)s', + {'e': entity.eid, 'g': self.eid, + 'name': pname, 'label': plabel}): + self._cw.create_entity('CWPermission', name=pname, label=plabel, + require_group=self, + reverse_require_permission=entity) class CWUser(AnyEntity): @@ -156,10 +168,6 @@ dc_long_title = name - def db_key_name(self): - """XXX goa specific""" - return self.get('login') - from logilab.common.deprecation import class_renamed EUser = class_renamed('EUser', CWUser) EGroup = class_renamed('EGroup', CWGroup) diff -r f1d9e3b9e51e -r d8083b2ae4d6 entities/schemaobjs.py --- a/entities/schemaobjs.py Wed May 11 13:41:21 2011 +0200 +++ b/entities/schemaobjs.py Fri May 13 10:10:19 2011 +0200 @@ -45,10 +45,6 @@ return u'%s <<%s>>' % (self.dc_title(), ', '.join(stereotypes)) return self.dc_title() - def db_key_name(self): - """XXX goa specific""" - return self.get('name') - class CWRType(AnyEntity): __regid__ = 'CWRType' @@ -87,10 +83,6 @@ "has cardinality=%(card)s") raise ValidationError(self.eid, {qname: msg % locals()}) - def db_key_name(self): - """XXX goa specific""" - return self.get('name') - class CWRelation(AnyEntity): __regid__ = 'CWRelation' diff -r f1d9e3b9e51e -r d8083b2ae4d6 entity.py --- a/entity.py Wed May 11 13:41:21 2011 +0200 +++ b/entity.py Fri May 13 10:10:19 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 f1d9e3b9e51e -r d8083b2ae4d6 server/repository.py --- a/server/repository.py Wed May 11 13:41:21 2011 +0200 +++ b/server/repository.py Fri May 13 10:10:19 2011 +0200 @@ -59,13 +59,18 @@ security_enabled from cubicweb.server.ssplanner import EditedEntity +NO_CACHE_RELATIONS = set( [('require_permission', 'object'), + ('owned_by', 'object'), + ('created_by', 'object'), + ('cw_source', 'object'), + ]) def prefill_entity_caches(entity, relations): session = entity._cw # prefill entity relation caches for rschema in entity.e_schema.subject_relations(): rtype = str(rschema) - if rtype in schema.VIRTUAL_RTYPES: + if rtype in schema.VIRTUAL_RTYPES or (rtype, 'subject') in NO_CACHE_RELATIONS: continue if rschema.final: entity.cw_attr_cache.setdefault(rtype, None) @@ -74,7 +79,7 @@ session.empty_rset()) for rschema in entity.e_schema.object_relations(): rtype = str(rschema) - if rtype in schema.VIRTUAL_RTYPES: + if rtype in schema.VIRTUAL_RTYPES or (rtype, 'object') in NO_CACHE_RELATIONS: continue entity.cw_set_relation_cache(rtype, 'object', session.empty_rset()) # set inlined relation cache before call to after_add_entity diff -r f1d9e3b9e51e -r d8083b2ae4d6 test/unittest_entity.py --- a/test/unittest_entity.py Wed May 11 13:41:21 2011 +0200 +++ b/test/unittest_entity.py Fri May 13 10:10:19 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() diff -r f1d9e3b9e51e -r d8083b2ae4d6 web/data/cubicweb.ajax.js --- a/web/data/cubicweb.ajax.js Wed May 11 13:41:21 2011 +0200 +++ b/web/data/cubicweb.ajax.js Fri May 13 10:10:19 2011 +0200 @@ -1,4 +1,4 @@ -/* copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +/* copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. * contact http://www.logilab.fr/ -- mailto:contact@logilab.fr * * This file is part of CubicWeb. diff -r f1d9e3b9e51e -r d8083b2ae4d6 web/request.py --- a/web/request.py Wed May 11 13:41:21 2011 +0200 +++ b/web/request.py Fri May 13 10:10:19 2011 +0200 @@ -116,8 +116,8 @@ pid = self.form.get('pageid') if pid is None: pid = make_uid(id(self)) + self.html_headers.define_var('pageid', pid, override=False) self.pageid = pid - self.html_headers.define_var('pageid', pid, override=False) @property def authmode(self): diff -r f1d9e3b9e51e -r d8083b2ae4d6 web/views/basecontrollers.py --- a/web/views/basecontrollers.py Wed May 11 13:41:21 2011 +0200 +++ b/web/views/basecontrollers.py Fri May 13 10:10:19 2011 +0200 @@ -1,4 +1,4 @@ -# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This file is part of CubicWeb. diff -r f1d9e3b9e51e -r d8083b2ae4d6 web/views/cwsources.py --- a/web/views/cwsources.py Wed May 11 13:41:21 2011 +0200 +++ b/web/views/cwsources.py Fri May 13 10:10:19 2011 +0200 @@ -126,6 +126,8 @@ else: # CWAttribute/CWRelation self.srelations.setdefault(cwerschema.rtype.name, []).append( (cwerschema.stype.name, cwerschema.otype.name) ) + self.sentities.add(cwerschema.stype.name) + self.sentities.add(cwerschema.otype.name) def check(self): self.init() @@ -154,14 +156,15 @@ warning(_('relation %(rtype)s with %(etype)s as %(role)s is ' 'supported but no target type supported') % {'rtype': rschema, 'role': role, 'etype': etype}) - for rtype in self.srelations: - rschema = self.schema[rtype] - for subj, obj in rschema.rdefs: - if subj in self.sentities and obj in self.sentities: - break - else: - error(_('relation %s is supported but none if its definitions ' - 'matches supported entities') % rtype) + for rtype, rdefs in self.srelations.iteritems(): + if rdefs is None: + rschema = self.schema[rtype] + for subj, obj in rschema.rdefs: + if subj in self.sentities and obj in self.sentities: + break + else: + error(_('relation %s is supported but none of its definitions ' + 'matches supported entities') % rtype) self.custom_check() def custom_check(self):