backport stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 06 Aug 2010 17:49:20 +0200
changeset 6077 62011f82c386
parent 6069 d7cef08aad27 (current diff)
parent 6076 aa7402e998a1 (diff)
child 6081 ede33e6400ab
backport stable
server/session.py
web/views/primary.py
--- a/doc/book/en/devrepo/testing.rst	Wed Aug 04 11:16:40 2010 +0200
+++ b/doc/book/en/devrepo/testing.rst	Fri Aug 06 17:49:20 2010 +0200
@@ -145,7 +145,7 @@
    connection from another !
 
 Email notifications tests
--------------------------
+`````````````````````````
 
 When running tests potentially generated e-mails are not really sent
 but is found in the list `MAILBOX` of module
@@ -212,6 +212,21 @@
   auto_populate cannot guess by itself; these must yield resultsets
   against which views may be selected.
 
+Testing with other cubes
+------------------------
+
+Sometimes a small component cannot be tested all by itself, so one
+needs to specify other cubes to be used as part of the the unit test
+suite. This is handled by the ``bootstrap_cubes`` file located under
+``mycube\test\data``. One example from the `preview` cube::
+
+ card, file, preview
+
+The format is:
+
+* possibly several empy lines or lines starting with ``#`` (comment lines)
+* one line containing a coma separated list of cube names.
+
 
 Test APIS
 ---------
--- a/hooks/syncschema.py	Wed Aug 04 11:16:40 2010 +0200
+++ b/hooks/syncschema.py	Fri Aug 06 17:49:20 2010 +0200
@@ -104,6 +104,28 @@
     session.info('added index on %s(%s)', table, column)
 
 
+def insert_rdef_on_subclasses(session, eschema, rschema, rdefdef, props):
+    # XXX 'infered': True/False, not clear actually
+    props.update({'constraints': rdefdef.constraints,
+                  'description': rdefdef.description,
+                  'cardinality': rdefdef.cardinality,
+                  'permissions': rdefdef.get_permissions(),
+                  'order': rdefdef.order,
+                  'infered': False, 'eid': None
+                  })
+    cstrtypemap = ss.cstrtype_mapping(session)
+    groupmap = group_mapping(session)
+    object = rschema.schema.eschema(rdefdef.object)
+    for specialization in eschema.specialized_by(False):
+        if (specialization, rdefdef.object) in rschema.rdefs:
+            continue
+        print 'adding infered', specialization, rschema.type, object
+        sperdef = RelationDefinitionSchema(specialization, rschema,
+                                           object, props)
+        ss.execschemarql(session.execute, sperdef,
+                         ss.rdef2rql(sperdef, cstrtypemap, groupmap))
+
+
 def check_valid_changes(session, entity, ro_attrs=('name', 'final')):
     errors = {}
     # don't use getattr(entity, attr), we would get the modified value if any
@@ -454,25 +476,7 @@
         # if relation type has been inserted in the same transaction, its final
         # attribute is still set to False, so we've to ensure it's False
         rschema.final = True
-        # XXX 'infered': True/False, not clear actually
-        props.update({'constraints': rdefdef.constraints,
-                      'description': rdefdef.description,
-                      'cardinality': rdefdef.cardinality,
-                      'constraints': rdefdef.constraints,
-                      'permissions': rdefdef.get_permissions(),
-                      'order': rdefdef.order,
-                      'infered': False, 'eid': None
-                      })
-        cstrtypemap = ss.cstrtype_mapping(session)
-        groupmap = group_mapping(session)
-        object = schema.eschema(rdefdef.object)
-        for specialization in eschema.specialized_by(False):
-            if (specialization, rdefdef.object) in rschema.rdefs:
-                continue
-            sperdef = RelationDefinitionSchema(specialization, rschema,
-                                               object, props)
-            ss.execschemarql(session.execute, sperdef,
-                             ss.rdef2rql(sperdef, cstrtypemap, groupmap))
+        insert_rdef_on_subclasses(session, eschema, rschema, rdefdef, props)
         # set default value, using sql for performance and to avoid
         # modification_date update
         if default:
@@ -514,6 +518,9 @@
             # first occurence of "Subject relation Something" whatever Something
             if len(rschema.objects(rdefdef.subject)) == 1:
                 add_inline_relation_column(session, rdefdef.subject, rtype)
+            eschema = schema[rdefdef.subject]
+            insert_rdef_on_subclasses(session, eschema, rschema, rdefdef,
+                                      {'composite': entity.composite})
         else:
             # need to create the relation if no relation definition in the
             # schema and if it has not been added during other event of the same
--- a/server/migractions.py	Wed Aug 04 11:16:40 2010 +0200
+++ b/server/migractions.py	Fri Aug 06 17:49:20 2010 +0200
@@ -378,9 +378,13 @@
             for gname in newgroups:
                 if not confirm or self.confirm('Grant %s permission of %s to %s?'
                                                % (action, erschema, gname)):
-                    self.rqlexec('SET T %s G WHERE G eid %%(x)s, T eid %s'
-                                 % (perm, teid),
-                                 {'x': gm[gname]}, ask_confirm=False)
+                    try:
+                        self.rqlexec('SET T %s G WHERE G eid %%(x)s, T eid %s'
+                                     % (perm, teid),
+                                     {'x': gm[gname]}, ask_confirm=False)
+                    except KeyError:
+                        self.error('can grant %s perm to unexistant group %s',
+                                   action, gname)
             # handle rql expressions
             newexprs = dict((expr.expression, expr) for expr in erschema.get_rqlexprs(action))
             for expreid, expression in self.rqlexec('Any E, EX WHERE T %s E, E expression EX, '
@@ -876,7 +880,15 @@
                 self.sqlexec('UPDATE %s_relation SET eid_to=%s WHERE eid_to=%s'
                              % (rtype, new.eid, oldeid), ask_confirm=False)
             # delete relations using SQL to avoid relations content removal
-            # triggered by schema synchronization hooks
+            # triggered by schema synchronization hooks. Should add deleted eids
+            # into pending eids else we may get some validation error on commit
+            # since integrity hooks may think some required relation is
+            # missing...
+            pending = self.session.transaction_data.setdefault('pendingeids', set())
+            for eid, in self.sqlexec('SELECT cw_eid FROM cw_CWRelation '
+                                     'WHERE cw_from_entity=%(eid)s OR cw_to_entity=%(eid)s',
+                                     {'eid': oldeid}, ask_confirm=False):
+                pending.add(eid)
             self.sqlexec('DELETE FROM cw_CWRelation '
                          'WHERE cw_from_entity=%(eid)s OR cw_to_entity=%(eid)s',
                          {'eid': oldeid}, ask_confirm=False)
@@ -911,10 +923,15 @@
             self.commit()
             gmap = self.group_mapping()
             cmap = self.cstrtype_mapping()
+            done = set()
             for rdef in rschema.rdefs.itervalues():
                 if not (reposchema.has_entity(rdef.subject)
                         and reposchema.has_entity(rdef.object)):
                     continue
+                # symmetric relations appears twice
+                if (rdef.subject, rdef.object) in done:
+                    continue
+                done.add( (rdef.subject, rdef.object) )
                 self._set_rdef_eid(rdef)
                 ss.execschemarql(execute, rdef,
                                  ss.rdef2rql(rdef, cmap, gmap))
--- a/server/serverctl.py	Wed Aug 04 11:16:40 2010 +0200
+++ b/server/serverctl.py	Fri Aug 06 17:49:20 2010 +0200
@@ -71,13 +71,13 @@
                        'on the database:')
                 print special_privs
                 print
-        default_user = source.get('db-user', os.environ.get('USER', ''))
-        user = raw_input('Connect as user ? [%r]: ' % default_user)
-        user = user or default_user
-        if user == source.get('db-user') and source.get('db-password'):
-            password = source['db-password']
-        else:
-            password = getpass('password: ')
+            default_user = source.get('db-user', os.environ.get('USER', ''))
+            user = raw_input('Connect as user ? [%r]: ' % default_user)
+            user = user or default_user
+            if user == source.get('db-user') and source.get('db-password'):
+                password = source['db-password']
+            else:
+                password = getpass('password: ')
     else:
         user = password = None
     extra_args = source.get('db-extra-arguments')
--- a/server/session.py	Wed Aug 04 11:16:40 2010 +0200
+++ b/server/session.py	Fri Aug 06 17:49:20 2010 +0200
@@ -1025,7 +1025,7 @@
     def __init__(self, repo, cnxprops=None):
         super(InternalSession, self).__init__(InternalManager(), repo, cnxprops,
                                               _id='internal')
-        self.user.req = self # XXX remove when "vreg = user.req.vreg" hack in entity.py is gone
+        self.user._cw = self # XXX remove when "vreg = user._cw.vreg" hack in entity.py is gone
         self.cnxtype = 'inmemory'
         self.disable_hook_categories('integrity')
 
--- a/web/views/primary.py	Wed Aug 04 11:16:40 2010 +0200
+++ b/web/views/primary.py	Fri Aug 06 17:49:20 2010 +0200
@@ -130,7 +130,7 @@
         display_attributes = []
         for rschema, _, role, dispctrl in self._section_def(entity, 'attributes'):
             vid = dispctrl.get('vid', 'reledit')
-            if rschema.final or vid == 'reledit':
+            if rschema.final or vid == 'reledit' or dispctrl.get('rtypevid'):
                 value = entity.view(vid, rtype=rschema.type, role=role)
             else:
                 rset = self._relation_rset(entity, rschema, role, dispctrl)