[Erp5-report] r14618 - in /erp5/trunk/products/CMFCategory: ./ tests/

nobody at svn.erp5.org nobody at svn.erp5.org
Fri May 25 16:32:52 CEST 2007


Author: jerome
Date: Fri May 25 16:32:52 2007
New Revision: 14618

URL: http://svn.erp5.org?rev=14618&view=rev
Log:
Support new arguments to getCategoryChild*List to easily sort items of the same
level. Look at the test for more info


Modified:
    erp5/trunk/products/CMFCategory/Category.py
    erp5/trunk/products/CMFCategory/tests/testCMFCategory.py

Modified: erp5/trunk/products/CMFCategory/Category.py
URL: http://svn.erp5.org/erp5/trunk/products/CMFCategory/Category.py?rev=14618&r1=14617&r2=14618&view=diff
==============================================================================
--- erp5/trunk/products/CMFCategory/Category.py (original)
+++ erp5/trunk/products/CMFCategory/Category.py Fri May 25 16:32:52 2007
@@ -215,40 +215,63 @@
                                                     'getCategoryChildValueList')
     def getCategoryChildValueList(self, recursive=1, include_if_child=1,
                                   is_self_excluded=1, sort_on=None,
-                                  sort_order=None, **kw):
+                                  sort_order=None, local_sort_method=None,
+                                  local_sort_id=None, **kw):
       """
           List the child objects of this category and all its subcategories.
 
-          recursive - if set to 1, list recursively
-
-          include_if_child - if set to 1, categories having child categories
-                             are not included
+          recursive         - if set to 1, list recursively
+
+          include_if_child  - if set to 1, categories having child categories
+                              are not included
           
-          is_self_excluded - if set to 1, exclude this category from the list
+          is_self_excluded  - if set to 1, exclude this category from the list
 
           sort_on, sort_order - the same semantics as ZSQLCatalog
-                                sort_on specifies properties used for sorting
-                                sort_order specifies how categories are sorted
-
-                                WARNING: using these parameters can slow down
-                                significantly, because this is written in
-                                Python
+                              sort_on specifies properties used for sorting
+                              sort_order specifies how categories are sorted.
+                              The default is to do a preorder tree traversal on
+                              all sub-objects.
+
+                              WARNING: using these parameters can slow down
+                              significantly, because this is written in Python
+          
+          local_sort_method - When using the default preorder traversal, use
+                              this function to sort objects of the same depth.
+          
+          local_sort_id     - When using the default preorder traversal, sort
+                              objects of the same depth by comparing their
+                              'local_sort_id' property.
+          
+          Renderer parameter are also supported here.
       """
       if is_self_excluded or (
                     not(include_if_child) and
-                    len(self.objectValues(self.allowed_types)) > 0):
+                    len(self.objectIds(self.allowed_types)) > 0):
         value_list = []
       else:
         value_list = [self]
+      
+      child_value_list = self.objectValues(self.allowed_types)
+      if local_sort_id:
+        local_sort_method = lambda a, b: cmp(a.getProperty(local_sort_id),
+                                             b.getProperty(local_sort_id))
+      if local_sort_method:
+        # sort objects at the current level
+        child_value_list = list(child_value_list)
+        child_value_list.sort(local_sort_method)
+
       if recursive:
-        for c in self.objectValues(self.allowed_types):
-          # Do not pass sort parameters intentionally, because sorting
+        for c in child_value_list:
+          # Do not global pass sort parameters intentionally, because sorting
           # needs to be done only at the end of recursive calls.
           value_list.extend(c.getCategoryChildValueList(recursive=1,
                                        is_self_excluded=0,
-                                       include_if_child=include_if_child))
+                                       include_if_child=include_if_child,
+                                       local_sort_method=local_sort_method,
+                                       local_sort_id=local_sort_id))
       else:
-        for c in self.objectValues(self.allowed_types):
+        for c in child_value_list:
           value_list.append(c)
 
       return sortValueList(value_list, sort_on, sort_order, **kw)
@@ -390,6 +413,9 @@
       display_id -- method called to build the couple
 
       recursive -- if set to 0 do not apply recursively
+
+      All parameter supported by getCategoryChildValueList and Render are
+      supported here.
       """
       def _renderCategoryChildItemList(recursive=1, base=0, **kw):
         value_list = self.getCategoryChildValueList(recursive=recursive,**kw)
@@ -650,7 +676,8 @@
     security.declareProtected(Permissions.AccessContentsInformation,
                                                  'getCategoryChildValueList')
     def getCategoryChildValueList(self, is_self_excluded=1, recursive=1,
-                     include_if_child=1, sort_on=None, sort_order=None, **kw):
+                     include_if_child=1, sort_on=None, sort_order=None,
+                     local_sort_method=None, local_sort_id=None, **kw):
       """
           List the child objects of this category and all its subcategories.
 
@@ -667,28 +694,50 @@
                         region/europe/france
                         region/europe/germany
                         ...
+          sort_on, sort_order - sort categories in 'sort_order' by comparing
+                  the 'sort_on' attribute. The default is to do a preorder tree
+                  traversal on all subobjects.
+
+          local_sort_method - When using the default preorder traversal, use
+                              this function to sort objects of the same depth.
+          
+          local_sort_id     - When using the default preorder traversal, sort
+                              objects of the same depth by comparing their
+                              'local_sort_id' property.
+          
+          Renderer parameter are also supported here.
 
       """
       if is_self_excluded:
         value_list = []
       else:
         value_list = [self]
+
+      child_value_list = self.objectValues(self.allowed_types)
+      if local_sort_id:
+        local_sort_method = lambda a, b: cmp(a.getProperty(local_sort_id),
+                                             b.getProperty(local_sort_id))
+      if local_sort_method:
+        # sort objects at the current level
+        child_value_list = list(child_value_list)
+        child_value_list.sort(local_sort_method)
+
       if recursive:
-        for c in self.objectValues(self.allowed_types):
+        for c in child_value_list:
           value_list.extend(c.getCategoryChildValueList(recursive=1,
                                         is_self_excluded=0,
                                         include_if_child=include_if_child))
       else:
-        for c in self.objectValues(self.allowed_types):
+        for c in child_value_list:
           if include_if_child:
             value_list.append(c)
           else:
-            if len(c.objectValues(self.allowed_types))==0:
+            if len(c.objectIds(self.allowed_types))==0:
               value_list.append(c)
       return sortValueList(value_list, sort_on, sort_order, **kw)
 
     # Alias for compatibility
-    security.declareProtected(Permissions.AccessContentsInformation, 
+    security.declareProtected(Permissions.AccessContentsInformation,
                               'getBaseCategory')
     getBaseCategory = getBaseCategoryValue
 

Modified: erp5/trunk/products/CMFCategory/tests/testCMFCategory.py
URL: http://svn.erp5.org/erp5/trunk/products/CMFCategory/tests/testCMFCategory.py?rev=14618&r1=14617&r2=14618&view=diff
==============================================================================
--- erp5/trunk/products/CMFCategory/tests/testCMFCategory.py (original)
+++ erp5/trunk/products/CMFCategory/tests/testCMFCategory.py Fri May 25 16:32:52 2007
@@ -834,6 +834,56 @@
     self.assertSameSet(c1.getCategoryChildValueList(is_self_excluded=0),
                                                     (c1, c11, c111))
 
+  def test_24_getCategoryChildValueListLocalSortMethod(self,
+                              quiet=quiet, run=run_all_test) :
+    if not run: return
+    if not quiet:
+      message = 'Test getCategoryChildValueList local sort method'
+      ZopeTestCase._print('\n '+message)
+      LOG('Testing... ', 0, message)
+
+    pc = self.getCategoriesTool()
+    bc = pc.newContent(portal_type='Base Category', id='child_test')
+    c1 = bc.newContent(portal_type='Category', id='1', int_index=10, title='C')
+    c11 = c1.newContent(portal_type='Category', id='1.1', int_index=5, title='X')
+    c111 = c11.newContent(portal_type='Category', id='1.1.1',
+                          int_index=2, title='C')
+    c12 = c1.newContent(portal_type='Category', id='1.2', int_index=3, title='Z')
+    c2 = bc.newContent(portal_type='Category', id='2', int_index=30, title='B')
+    c3 = bc.newContent(portal_type='Category', id='3', int_index=20, title='A')
+    
+    # the default ordering is preorder:
+    self.assertEquals(list(bc.getCategoryChildValueList()),
+                      [c1, c11, c111, c12, c2, c3])
+    self.assertEquals(list(c1.getCategoryChildValueList()), [c11, c111, c12])
+    
+    # but this order can be controlled for categories of the same depth, ie. we
+    # can sort each level independantly (this is different from sort_on /
+    # sort_order which sort the whole list regardless of the original
+    # structure).
+
+    # This can be done either with a function (like cmp argument to python
+    # list sort)
+    def sort_func(a, b):
+      return cmp(a.getTitle(), b.getTitle())
+    # here c1, c2, c3 are sorted by their titles
+    self.assertEquals(list(bc.getCategoryChildValueList(
+                                        local_sort_method=sort_func)),
+                      [c3, c2, c1, c11, c111, c12])
+    # here c11 & c12 are sorted by their titles
+    self.assertEquals(list(c1.getCategoryChildValueList(
+                              local_sort_method=sort_func)), [c11, c111, c12])
+
+    # This can also be done with a local_sort_id, then objects are sorted by
+    # comparing this 'sort_id' property (using getProperty())
+    # here c1, c2, c3 are sorted by their int_index
+    self.assertEquals(list(bc.getCategoryChildValueList(
+                                        local_sort_id='int_index')),
+                      [c1, c11, c111, c12, c3, c2])
+    # here c11 & c12 are sorted by their titles
+    self.assertEquals(list(c1.getCategoryChildValueList(
+                              local_sort_id='int_index')), [c12, c11, c111])
+
 
 if __name__ == '__main__':
     framework()




More information about the Erp5-report mailing list