[entity vocab] fix bug introduced in 3.12 vs/ entity vocabulary, leading to some unexpected empty vocabulary. Fix test accordingly.
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 05 Apr 2011 12:48:53 +0200
changeset 7177 0f2905cbe443
parent 7176 f2a976cf7dac
child 7180 c031ea58d5f1
[entity vocab] fix bug introduced in 3.12 vs/ entity vocabulary, leading to some unexpected empty vocabulary. Fix test accordingly.
entity.py
test/unittest_entity.py
--- a/entity.py	Tue Apr 05 12:47:18 2011 +0200
+++ b/entity.py	Tue Apr 05 12:48:53 2011 +0200
@@ -28,7 +28,7 @@
 
 from rql.utils import rqlvar_maker
 
-from cubicweb import Unauthorized, typed_eid
+from cubicweb import Unauthorized, typed_eid, neg_role
 from cubicweb.rset import ResultSet
 from cubicweb.selectors import yes
 from cubicweb.appobject import AppObject
@@ -778,11 +778,21 @@
             searchedvar, evar = 'S', 'O'
             objtype, subjtype = self.e_schema, targettype
         # initialize some variables according to `self` existance
-        if self.has_eid():
+        if rdef.role_cardinality(neg_role(role)) in '?1':
+            # if cardinality in '1?', we want a target entity which isn't
+            # already linked using this relation
+            if searchedvar == 'S':
+                restriction = ['NOT S %s ZZ' % rtype]
+            else:
+                restriction = ['NOT ZZ %s O' % rtype]
+        elif self.has_eid():
+            # elif we have an eid, we don't want a target entity which is
+            # already linked to ourself through this relation
             restriction = ['NOT S %s O' % rtype]
-            if rdef.role_cardinality(role) not in '?1':
-                # if cardinality in '1?', don't add restriction on eid
-                restriction.append('%s eid %%(x)s' % evar)
+        else:
+            restriction = []
+        if self.has_eid():
+            restriction += ['%s eid %%(x)s' % evar]
             args = {'x': self.eid}
             if role == 'subject':
                 sec_check_args = {'fromeid': self.eid}
@@ -790,10 +800,6 @@
                 sec_check_args = {'toeid': self.eid}
             existant = None # instead of 'SO', improve perfs
         else:
-            if rdef.role_cardinality(role) in '?1':
-                restriction = ['NOT S %s O' % rtype]
-            else:
-                restriction = []
             args = {}
             sec_check_args = {}
             existant = searchedvar
--- a/test/unittest_entity.py	Tue Apr 05 12:47:18 2011 +0200
+++ b/test/unittest_entity.py	Tue Apr 05 12:48:53 2011 +0200
@@ -241,7 +241,7 @@
         user = self.request().user
         rql = user.cw_unrelated_rql('use_email', 'EmailAddress', 'subject')[0]
         self.assertEqual(rql, 'Any O,AA,AB,AC ORDERBY AC DESC '
-                         'WHERE NOT EXISTS(S use_email O), S eid %(x)s, '
+                         'WHERE NOT EXISTS(ZZ use_email O), S eid %(x)s, '
                          'O is EmailAddress, O address AA, O alias AB, O modification_date AC')
 
     def test_unrelated_rql_security_1_user(self):
@@ -250,35 +250,35 @@
         user = self.request().user
         rql = user.cw_unrelated_rql('use_email', 'EmailAddress', 'subject')[0]
         self.assertEqual(rql, 'Any O,AA,AB,AC ORDERBY AC DESC '
-                          'WHERE NOT EXISTS(S use_email O), S eid %(x)s, '
+                         'WHERE NOT EXISTS(ZZ use_email O), S eid %(x)s, '
                          'O is EmailAddress, O address AA, O alias AB, O modification_date AC')
         user = self.execute('Any X WHERE X login "admin"').get_entity(0, 0)
         rql = user.cw_unrelated_rql('use_email', 'EmailAddress', 'subject')[0]
-        self.assertEqual(rql, 'Any O,AA,AB,AC ORDERBY AC DESC WHERE '
-                         'NOT EXISTS(S use_email O), S eid %(x)s, '
-                         'O is EmailAddress, O address AA, O alias AB, O modification_date AC, '
-                         'A eid %(B)s, EXISTS(S identity A, NOT A in_group C, C name "guests", C is CWGroup)')
+        self.assertEqual(rql, 'Any O,AA,AB,AC ORDERBY AC DESC '
+                         'WHERE NOT EXISTS(ZZ use_email O, ZZ is CWUser), S eid %(x)s, '
+                         'O is EmailAddress, O address AA, O alias AB, O modification_date AC, A eid %(B)s, '
+                         'EXISTS(S identity A, NOT A in_group C, C name "guests", C is CWGroup)')
 
     def test_unrelated_rql_security_1_anon(self):
         self.login('anon')
         user = self.request().user
         rql = user.cw_unrelated_rql('use_email', 'EmailAddress', 'subject')[0]
-        self.assertEqual(rql, 'Any O,AA,AB,AC ORDERBY AC DESC WHERE '
-                         'NOT EXISTS(S use_email O), S eid %(x)s, '
-                         'O is EmailAddress, O address AA, O alias AB, O modification_date AC, '
-                         'A eid %(B)s, EXISTS(S identity A, NOT A in_group C, C name "guests", C is CWGroup)')
+        self.assertEqual(rql, 'Any O,AA,AB,AC ORDERBY AC DESC '
+                         'WHERE NOT EXISTS(ZZ use_email O, ZZ is CWUser), S eid %(x)s, '
+                         'O is EmailAddress, O address AA, O alias AB, O modification_date AC, A eid %(B)s, '
+                         'EXISTS(S identity A, NOT A in_group C, C name "guests", C is CWGroup)')
 
     def test_unrelated_rql_security_2(self):
         email = self.execute('INSERT EmailAddress X: X address "hop"').get_entity(0, 0)
         rql = email.cw_unrelated_rql('use_email', 'CWUser', 'object')[0]
         self.assertEqual(rql, 'Any S,AA,AB,AC,AD ORDERBY AA '
-                         'WHERE NOT EXISTS(S use_email O), S is CWUser, '
+                         'WHERE NOT EXISTS(S use_email O), O eid %(x)s, S is CWUser, '
                          'S login AA, S firstname AB, S surname AC, S modification_date AD')
         self.login('anon')
         email = self.execute('Any X WHERE X eid %(x)s', {'x': email.eid}).get_entity(0, 0)
         rql = email.cw_unrelated_rql('use_email', 'CWUser', 'object')[0]
         self.assertEqual(rql, 'Any S,AA,AB,AC,AD ORDERBY AA '
-                         'WHERE NOT EXISTS(S use_email O, O is EmailAddress), S is CWUser, '
+                         'WHERE NOT EXISTS(S use_email O), O eid %(x)s, S is CWUser, '
                          'S login AA, S firstname AB, S surname AC, S modification_date AD, '
                          'A eid %(B)s, EXISTS(S identity A, NOT A in_group C, C name "guests", C is CWGroup)')
 
@@ -287,7 +287,7 @@
         email = self.vreg['etypes'].etype_class('EmailAddress')(self.request())
         rql = email.cw_unrelated_rql('use_email', 'CWUser', 'object')[0]
         self.assertEqual(rql, 'Any S,AA,AB,AC,AD ORDERBY AA '
-                         'WHERE NOT EXISTS(S use_email O, O is EmailAddress), S is CWUser, '
+                         'WHERE S is CWUser, '
                          'S login AA, S firstname AB, S surname AC, S modification_date AD, '
                          'A eid %(B)s, EXISTS(S identity A, NOT A in_group C, C name "guests", C is CWGroup)')