backport stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 13 May 2011 10:10:19 +0200
changeset 7377 d8083b2ae4d6
parent 7368 f1d9e3b9e51e (current diff)
parent 7376 38524ca653e5 (diff)
child 7378 86a1ae289f05
backport stable
devtools/testlib.py
entity.py
test/unittest_entity.py
web/data/cubicweb.ajax.js
web/request.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:
--- 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 #######################################################
 
--- 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)
--- 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'
--- 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
 
--- 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
--- 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()
--- 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.
--- 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):
--- 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.
--- 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):