[migration cw3.9, cw3.10] add an ITree adapter for Keyword
authorKatia Saurfelt <katia.saurfelt@logilab.fr>
Tue, 25 Jan 2011 13:27:44 +0100
changeset 115 4e3061d723fd
parent 114 0df3c717f5eb
child 116 0f5d9e769d63
[migration cw3.9, cw3.10] add an ITree adapter for Keyword
entities.py
hooks.py
test/unittest_classification.py
test/unittest_descendant_of.py
test/unittest_security.py
views.py
--- a/entities.py	Mon Dec 06 11:14:21 2010 +0100
+++ b/entities.py	Tue Jan 25 13:27:44 2011 +0100
@@ -9,7 +9,7 @@
 from logilab.common.deprecation import  deprecated
 
 from cubicweb.mixins import MI_REL_TRIGGERS, TreeMixIn
-from cubicweb.entities import AnyEntity, fetch_config
+from cubicweb.entities import AnyEntity, fetch_config, adapters
 from cubicweb.interfaces import ITree
 from cubicweb.view import EntityAdapter
 from cubicweb.selectors import is_instance
@@ -58,22 +58,25 @@
                                 'C eid %(x)s', {'x': self.eid})
 
 
-class Keyword(TreeMixIn, AnyEntity):
+class Keyword(AnyEntity):
     __regid__ = 'Keyword'
     fetch_attrs, fetch_order = fetch_config(['name'])
-    __implements__ = AnyEntity.__implements__ + (ITree,)
-    tree_attribute = 'subkeyword_of'
+
+
+class KeywordITreeAdapter(adapters.ITreeAdapter):
+    __select__ = is_instance('Keyword', 'CodeKeyword')
+    tree_relation = 'subkeyword_of'
 
     @property
     def classification(self):
-        if self.included_in:
-            return self.included_in[0]
+        if self.entity.included_in:
+            return self.entity.included_in[0]
         return None
 
     def parent(self):
         """ITree + IBreadcrumbs implementation"""
         try:
-            return self.related(self.tree_attribute, self.parent_target,
+            return self.entity.related(self.tree_relation, self.child_role,
                                 entities=True)[0]
         except (KeyError, IndexError):
             return self.classification
@@ -82,8 +85,8 @@
         """returns parent keyword entities,
            without the root classification
         """
-        if self.subkeyword_of:
-            parent = self.subkeyword_of[0]
+        if self.entity.subkeyword_of:
+            parent = self.entity.subkeyword_of[0]
             while parent is not None:
                 yield parent
                 if parent.subkeyword_of:
@@ -104,15 +107,15 @@
 
     def recurse_children(self, _done=None):
         """returns strict descendents"""
-        if _done is not None and self.eid in _done:
+        if _done is not None and self.entity.eid in _done:
             return
         if _done is not None:
-            _done.add(self.eid)
-            yield self
+            _done.add(self.entity.eid)
+            yield self.entity
         else:
             _done = set()
         for child in self.children():
-            for entity in child.recurse_children(_done):
+            for entity in child.cw_adapt_to('ITree').recurse_children(_done):
                 yield entity
 
 class CodeKeyword(Keyword):
--- a/hooks.py	Mon Dec 06 11:14:21 2010 +0100
+++ b/hooks.py	Tue Jan 25 13:27:44 2011 +0100
@@ -21,8 +21,8 @@
     def __call__(self):
         entity = self._cw.entity_from_eid(self.eidfrom)
         parent = self._cw.entity_from_eid(self.eidto)
-        parents = set([x.eid for x in chain([parent,], parent.iterparents())])
-        children = set([x.eid for x in chain([entity], entity.recurse_children())])
+        parents = set([x.eid for x in chain([parent,], parent.cw_adapt_to('ITree').iterparents())])
+        children = set([x.eid for x in chain([entity], entity.cw_adapt_to('ITree').recurse_children())])
         if children & parents:
             msg = _('detected descendant_of cycle')
             raise ValidationError(self.eidfrom, {role_name(self.rtype, 'subject'): msg})
@@ -68,7 +68,7 @@
 
     def __call__(self):
         parent = self._cw.entity_from_eid(self.eidto)
-        for parent in chain([parent], parent.iterparents()):
+        for parent in chain([parent], parent.cw_adapt_to('ITree').iterparents()):
             self._cw.execute('DELETE K descendant_of P WHERE K eid %(k)s, '
                             'P eid %(p)s', {'p':parent.eid, 'k': self.eidfrom})
 
@@ -92,7 +92,7 @@
         else:
             session.execute('SET SK included_in C WHERE SK eid %(x)s, '
                             'SK subkeyword_of K, K included_in C',
-                            {'x': subkw.eid}, 'x')
+                            {'x': subkw.eid})
 
     def check_cycle(self):
         parents = set([self.eidto])
@@ -111,8 +111,8 @@
         closure = set()
         entity = self.entity
         parent = self.parent
-        for parent in chain([parent, entity], parent.iterparents()):
-            for child in chain([entity], entity.recurse_children()):
+        for parent in chain([parent, entity], parent.cw_adapt_to('ITree').iterparents()):
+            for child in chain([entity], entity.cw_adapt_to('ITree').recurse_children()):
                 if child.eid != parent.eid:
                     closure.add((child, parent))
         for child, parent in closure:
--- a/test/unittest_classification.py	Mon Dec 06 11:14:21 2010 +0100
+++ b/test/unittest_classification.py	Tue Jan 25 13:27:44 2011 +0100
@@ -26,7 +26,7 @@
         kwgroup2 = req.create_entity('Keyword', name=u'kwgroup2', subkeyword_of=self.kwgroup)
         self.commit()
         rset = self.execute('Any N WHERE C name N, K included_in C, K eid %(k)s', {'k':kwgroup2.eid})
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
         self.assertEqual(rset[0][0], 'classif1')
 
 
--- a/test/unittest_descendant_of.py	Mon Dec 06 11:14:21 2010 +0100
+++ b/test/unittest_descendant_of.py	Tue Jan 25 13:27:44 2011 +0100
@@ -19,10 +19,10 @@
         self.commit()
         parent = kw1
         child = kw5
-        self.assertUnorderedIterableEquals([kw.name for kw in child.iterparents()], ['kw4', 'kw3', 'kw2', 'kw1'])
-        self.assertUnorderedIterableEquals([kw.name for kw in child.descendant_of], ['kw4', 'kw3', 'kw2', 'kw1'])
-        self.assertUnorderedIterableEquals([kw.name for kw in parent.reverse_descendant_of], ['kw5', 'kw4', 'kw3', 'kw2'])
-        self.assertUnorderedIterableEquals([kw.name for kw in parent.recurse_children()], ['kw5', 'kw4', 'kw3', 'kw2'])
+        self.assertItemsEqual([kw.name for kw in child.cw_adapt_to('ITree').iterparents()], ['kw4', 'kw3', 'kw2', 'kw1'])
+        self.assertItemsEqual([kw.name for kw in child.descendant_of], ['kw4', 'kw3', 'kw2', 'kw1'])
+        self.assertItemsEqual([kw.name for kw in parent.reverse_descendant_of], ['kw5', 'kw4', 'kw3', 'kw2'])
+        self.assertItemsEqual([kw.name for kw in parent.cw_adapt_to('ITree').recurse_children()], ['kw5', 'kw4', 'kw3', 'kw2'])
 
     def test_keyword_add2(self):
         req = self.request()
@@ -37,10 +37,10 @@
         self.commit()
         parent = kw1
         child = kw5
-        self.assertUnorderedIterableEquals([kw.name for kw in child.iterparents()], ['kw4', 'kw3', 'kw2', 'kw1'])
-        self.assertUnorderedIterableEquals([kw.name for kw in child.descendant_of], ['kw4', 'kw3', 'kw2', 'kw1'])
-        self.assertUnorderedIterableEquals([kw.name for kw in parent.reverse_descendant_of], ['kw5', 'kw4', 'kw3', 'kw2'])
-        self.assertUnorderedIterableEquals([kw.name for kw in parent.recurse_children()], ['kw5', 'kw4', 'kw3', 'kw2'])
+        self.assertItemsEqual([kw.name for kw in child.cw_adapt_to('ITree').iterparents()], ['kw4', 'kw3', 'kw2', 'kw1'])
+        self.assertItemsEqual([kw.name for kw in child.descendant_of], ['kw4', 'kw3', 'kw2', 'kw1'])
+        self.assertItemsEqual([kw.name for kw in parent.reverse_descendant_of], ['kw5', 'kw4', 'kw3', 'kw2'])
+        self.assertItemsEqual([kw.name for kw in parent.cw_adapt_to('ITree').recurse_children()], ['kw5', 'kw4', 'kw3', 'kw2'])
 
     def test_keyword_add3(self):
         req = self.request()
@@ -57,11 +57,11 @@
         self.commit()
         child  = kw5
         parent = kw1
-        self.assertUnorderedIterableEquals([kw.name for kw in child.descendant_of], ['kw4', 'kw3', 'kw2', 'kw1'])
+        self.assertItemsEqual([kw.name for kw in child.descendant_of], ['kw4', 'kw3', 'kw2', 'kw1'])
         # XXX check the order of iterparents
-        self.assertUnorderedIterableEquals([kw.name for kw in child.iterparents()], ['kw4', 'kw3', 'kw2', 'kw1'])
-        self.assertUnorderedIterableEquals([kw.name for kw in parent.recurse_children()], ['kw2', 'kw3', 'kw4', 'kw5'])
-        self.assertUnorderedIterableEquals([kw.name for kw in parent.reverse_descendant_of], ['kw2', 'kw3', 'kw4', 'kw5'])
+        self.assertItemsEqual([kw.name for kw in child.cw_adapt_to('ITree').iterparents()], ['kw4', 'kw3', 'kw2', 'kw1'])
+        self.assertItemsEqual([kw.name for kw in parent.cw_adapt_to('ITree').recurse_children()], ['kw2', 'kw3', 'kw4', 'kw5'])
+        self.assertItemsEqual([kw.name for kw in parent.reverse_descendant_of], ['kw2', 'kw3', 'kw4', 'kw5'])
 
     def test_keyword_add4(self):
         req = self.request()
@@ -74,22 +74,22 @@
         self.execute('SET K3 subkeyword_of K2 WHERE K3 eid %(kw3)s, K2 eid %(kw2)s',
                      {'kw2': kw2.eid, 'kw3': kw3.eid})
         self.commit();
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.descendant_of], ['kw1', 'kw2'])
+        self.assertItemsEqual([kw.name for kw in kw3.descendant_of], ['kw1', 'kw2'])
         self.execute('SET K3 descendant_of K0 WHERE K3 eid %(kw3)s, K0 eid %(kw0)s',
                       {'kw3': kw3.eid, 'kw0': kw0.eid})
         self.commit()
         kw3.clear_all_caches()
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.descendant_of], ['kw0', 'kw1', 'kw2'])
+        self.assertItemsEqual([kw.name for kw in kw3.descendant_of], ['kw0', 'kw1', 'kw2'])
         self.execute('SET K3 descendant_of K4 WHERE K3 eid %(kw3)s, K4 eid %(kw4)s',
                       {'kw3': kw3.eid, 'kw4': kw4.eid})
         self.commit()
         kw3.clear_all_caches()
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.descendant_of], ['kw0', 'kw1', 'kw2', 'kw4'])
+        self.assertItemsEqual([kw.name for kw in kw3.descendant_of], ['kw0', 'kw1', 'kw2', 'kw4'])
         self.execute('SET K3 descendant_of K5 WHERE K3 eid %(kw3)s, K5 eid %(kw5)s',
                        {'kw3': kw3.eid, 'kw5': kw5.eid})
         self.commit()
         kw3.clear_all_caches()
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.descendant_of], ['kw0', 'kw1', 'kw2', 'kw4', 'kw5'])
+        self.assertItemsEqual([kw.name for kw in kw3.descendant_of], ['kw0', 'kw1', 'kw2', 'kw4', 'kw5'])
 
     def test_keyword_update1(self):
         req = self.request()
@@ -102,17 +102,17 @@
                       {'kw3': kw3.eid, 'kw2': kw2.eid})
         self.commit();
         kw3 =  req.entity_from_eid(kw3.eid)
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.descendant_of], ['kw1', 'kw2'])
+        self.assertItemsEqual([kw.name for kw in kw3.descendant_of], ['kw1', 'kw2'])
         self.execute('SET K3 subkeyword_of K4 WHERE K3 eid %(kw3)s, K4 eid %(kw4)s',
                       {'kw3': kw3.eid, 'kw4': kw4.eid})
         self.commit()
         kw3.clear_all_caches()
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.descendant_of], ['kw4'])
+        self.assertItemsEqual([kw.name for kw in kw3.descendant_of], ['kw4'])
         self.execute('SET K3 subkeyword_of K5 WHERE K3 eid %(kw3)s, K5 eid %(kw5)s',
                      {'kw3': kw3.eid, 'kw5': kw5.eid})
         self.commit()
         kw3.clear_all_caches()
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.descendant_of], ['kw4', 'kw5'])
+        self.assertItemsEqual([kw.name for kw in kw3.descendant_of], ['kw4', 'kw5'])
 
     def test_keyword_descendant_of(self):
         req = self.request()
@@ -120,10 +120,10 @@
         kw2 = req.create_entity('Keyword', name=u'kw2', subkeyword_of=kw1, included_in=self.classif1)
         kw3 = req.create_entity('Keyword', name=u'kw3', subkeyword_of=kw1, included_in=self.classif1)
         self.commit()
-        self.assertUnorderedIterableEquals([kw.name for kw in kw2.descendant_of], ['kw1', ])
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.descendant_of], ['kw1', ])
-        self.assertUnorderedIterableEquals([kw.name for kw in kw1.reverse_descendant_of], ['kw3', 'kw2'])
-        self.assertUnorderedIterableEquals([kw.name for kw in kw1.recurse_children()], ['kw2', 'kw3'])
+        self.assertItemsEqual([kw.name for kw in kw2.descendant_of], ['kw1', ])
+        self.assertItemsEqual([kw.name for kw in kw3.descendant_of], ['kw1', ])
+        self.assertItemsEqual([kw.name for kw in kw1.reverse_descendant_of], ['kw3', 'kw2'])
+        self.assertItemsEqual([kw.name for kw in kw1.cw_adapt_to('ITree').recurse_children()], ['kw2', 'kw3'])
         kw0 = req.create_entity('Keyword', name=u'kw0', included_in=self.classif1)
         self.execute('SET K1 subkeyword_of K0 WHERE K1 eid %(kw1)s, K0 eid %(kw0)s',
                       {'kw1': kw1.eid, 'kw0': kw0.eid})
@@ -131,11 +131,11 @@
         kw1.clear_all_caches()
         kw2.clear_all_caches()
         kw3.clear_all_caches()
-        self.assertUnorderedIterableEquals([kw.name for kw in kw0.recurse_children()], ['kw1', 'kw2', 'kw3'])
-        self.assertUnorderedIterableEquals([kw.name for kw in kw0.reverse_descendant_of], ['kw3', 'kw2', 'kw1'])
-        self.assertUnorderedIterableEquals([kw.name for kw in kw1.descendant_of], ['kw0',])
-        self.assertUnorderedIterableEquals([kw.name for kw in kw2.descendant_of], ['kw1', 'kw0'])
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.descendant_of], ['kw1', 'kw0'])
+        self.assertItemsEqual([kw.name for kw in kw0.cw_adapt_to('ITree').recurse_children()], ['kw1', 'kw2', 'kw3'])
+        self.assertItemsEqual([kw.name for kw in kw0.reverse_descendant_of], ['kw3', 'kw2', 'kw1'])
+        self.assertItemsEqual([kw.name for kw in kw1.descendant_of], ['kw0',])
+        self.assertItemsEqual([kw.name for kw in kw2.descendant_of], ['kw1', 'kw0'])
+        self.assertItemsEqual([kw.name for kw in kw3.descendant_of], ['kw1', 'kw0'])
 
 
     def test_keyword_delete(self):
@@ -151,10 +151,10 @@
         self.execute('DELETE K subkeyword_of K3 WHERE K is Keyword, K eid %(kw3)s',
                      {'kw3':kw3.eid})
         self.commit()
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.iterparents()], [])
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.descendant_of], [])
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.reverse_descendant_of], ['kw5', 'kw4'])
-        self.assertUnorderedIterableEquals([kw.name for kw in kw3.recurse_children()], ['kw5', 'kw4'])
+        self.assertItemsEqual([kw.name for kw in kw3.cw_adapt_to('ITree').iterparents()], [])
+        self.assertItemsEqual([kw.name for kw in kw3.descendant_of], [])
+        self.assertItemsEqual([kw.name for kw in kw3.reverse_descendant_of], ['kw5', 'kw4'])
+        self.assertItemsEqual([kw.name for kw in kw3.cw_adapt_to('ITree').recurse_children()], ['kw5', 'kw4'])
 
     def test_no_add_descendant_cycle(self):
         """no ``descendant_of`` cycle"""
@@ -165,12 +165,12 @@
         self.commit()
         rql = 'SET K1 descendant_of K3 WHERE K1 eid %(kw1)s, K3 eid %(kw3)s' % {'kw1':kw1.eid,  'kw3':kw3.eid}
         self.assertRaises(ValidationError, self.execute, rql)
+        self.rollback()
         kw4 = req.create_entity('Keyword', name=u'kw4', included_in=self.classif1)
         kw5 = req.create_entity('Keyword', name=u'kw4', subkeyword_of=kw4, included_in=self.classif1)
         self.commit()
-        rql = 'SET K4 descendant_of K5 WHERE K4 eid %(kw4)s, K5 eid %(kw5)s' % {'kw4':kw4.eid,  'kw5':kw5.eid}
-        self.assertRaises(ValidationError, self.execute, rql)
-
+        with self.assertRaises(ValidationError) as cm:
+            self.execute('SET K4 descendant_of K5 WHERE K4 eid %(kw4)s, K5 eid %(kw5)s' % {'kw4':kw4.eid,  'kw5':kw5.eid})
 
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
--- a/test/unittest_security.py	Mon Dec 06 11:14:21 2010 +0100
+++ b/test/unittest_security.py	Tue Jan 25 13:27:44 2011 +0100
@@ -9,7 +9,7 @@
 
     def test_nonregr_keyword_selection_as_guest(self):
         self.login('anon')
-        self.execute('Any X ORDERBY Z WHERE X modification_date Z, K eid %(k)s, K applied_to X', {'k':self.kw1.eid}, 'k')
+        self.execute('Any X ORDERBY Z WHERE X modification_date Z, K eid %(k)s, K applied_to X', {'k':self.kw1.eid})
 
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
--- a/views.py	Mon Dec 06 11:14:21 2010 +0100
+++ b/views.py	Tue Jan 25 13:27:44 2011 +0100
@@ -181,9 +181,11 @@
         vocab = []
         scheme = None
         for e in sorted(rset.entities(),
-                        key=lambda e: (e.classification.name, e.view('combobox'))):
-            if scheme != e.classification.name:
-                vocab.append( (_(e.classification.name), None) )
+                        key=lambda e: (e.cw_adapt_to('ITree').classification.name,
+                                       e.view('combobox'))):
+            classification_name = e.cw_adapt_to('ITree').classification.name
+            if scheme != classification_name:
+                vocab.append( (_(classification_name), None) )
             vocab.append( (e.view('combobox'), e.eid) )
         return vocab