[Checkins] SVN: z3c.batching/trunk/ Moved the advanced batching of z3c.table into a helper function of z3c.batching

Christophe Combelles ccomb at free.fr
Sat Oct 11 07:24:17 EDT 2008


Log message for revision 92031:
  Moved the advanced batching of z3c.table into a helper function of z3c.batching
  

Changed:
  U   z3c.batching/trunk/CHANGES.txt
  U   z3c.batching/trunk/setup.py
  U   z3c.batching/trunk/src/z3c/batching/README.txt
  U   z3c.batching/trunk/src/z3c/batching/batch.py

-=-
Modified: z3c.batching/trunk/CHANGES.txt
===================================================================
--- z3c.batching/trunk/CHANGES.txt	2008-10-10 23:25:42 UTC (rev 92030)
+++ z3c.batching/trunk/CHANGES.txt	2008-10-11 11:24:15 UTC (rev 92031)
@@ -2,6 +2,12 @@
 CHANGES
 =======
 
+1.1.0 (unreleased)
+------------------
+
+- Added a function to build a small neighbourhood list of the current batch,
+  from a large batch list. (extracted from z3c.table)
+
 1.0.1 (2008-09-09)
 ------------------
 

Modified: z3c.batching/trunk/setup.py
===================================================================
--- z3c.batching/trunk/setup.py	2008-10-10 23:25:42 UTC (rev 92030)
+++ z3c.batching/trunk/setup.py	2008-10-11 11:24:15 UTC (rev 92031)
@@ -28,13 +28,14 @@
       description='Batching',
       long_description=(
           read('README.txt')
-          + '\n\n' +
-          'Detailed Dcoumentation\n' +
-          '======================\n'
-          + '\n\n' +
-          read('src', 'z3c', 'batching', 'README.txt')
-          + '\n\n' +
-          read('CHANGES.txt')
+          + '\n\n'
+          + '======================\n'
+          + 'Detailed Documentation\n'
+          + '======================\n'
+          + '\n\n'
+          + read('src', 'z3c', 'batching', 'README.txt')
+          + '\n\n'
+          + read('CHANGES.txt')
           ),
       keywords = "zope3 batching",
       classifiers = [

Modified: z3c.batching/trunk/src/z3c/batching/README.txt
===================================================================
--- z3c.batching/trunk/src/z3c/batching/README.txt	2008-10-10 23:25:42 UTC (rev 92030)
+++ z3c.batching/trunk/src/z3c/batching/README.txt	2008-10-11 11:24:15 UTC (rev 92031)
@@ -1,12 +1,14 @@
-===============
+
+.. contents::
+
 Simple Batching
-===============
+---------------
 
 This module implements a simple batching mechanism that allows you to split a
 large sequence into smaller batches. Let's start by creating a simple list,
 which will be our full sequence:
 
-Batch on empty root
+Batch on empty root::
 
   >>> from z3c.batching.batch import Batch
   >>> batch = Batch([], size=3)
@@ -37,24 +39,24 @@
   >>> sequence = ['one', 'two', 'three', 'four', 'five', 'six', 'seven',
   ...             'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen']
 
-We can now create a batch for this sequence. Let's make our batch size 3:
+We can now create a batch for this sequence. Let's make our batch size 3::
 
   >>> batch = Batch(sequence, size=3)
 
 The first argument to the batch is always the full sequence. If no start
-element is specified, the batch starts at the first element:
+element is specified, the batch starts at the first element::
 
   >>> list(batch)
   ['one', 'two', 'three']
 
-The start index is commonly specified in the constructor though:
+The start index is commonly specified in the constructor though::
 
   >>> batch = Batch(sequence, start=6, size=3)
   >>> list(batch)
   ['seven', 'eight', 'nine']
 
 Note that the start is an index and starts at zero. If the start index is
-greater than the largest index of the sequence, an index error is raised:
+greater than the largest index of the sequence, an index error is raised::
 
   >>> Batch(sequence, start=15, size=3)
   Traceback (most recent call last):
@@ -62,18 +64,18 @@
   IndexError: start index key out of range
 
 A batch implements the finite sequence interface and thus supports some
-standard methods. For example, you can ask the batch for its length:
+standard methods. For example, you can ask the batch for its length::
 
   >>> len(batch)
   3
 
 Note that the length returns the true size of the batch, not the size we asked
-for:
+for::
 
   >>> len(Batch(sequence, start=12, size=3))
   1
 
-You can also get an element by index, which is relative to the batch:
+You can also get an element by index, which is relative to the batch::
 
   >>> batch[0]
   'seven'
@@ -82,7 +84,7 @@
   >>> batch[2]
   'nine'
 
-Slicing 
+Slicing::
 
   >>> batch[:1]
   ['seven']
@@ -100,14 +102,14 @@
   []
   
 
-If you ask for index that is out of range, an index error is raised:
+If you ask for index that is out of range, an index error is raised::
 
   >>> batch[3]
   Traceback (most recent call last):
   ...
   IndexError: batch index out of range
 
-You can also iterate through the batch:
+You can also iterate through the batch::
 
   >>> iterator = iter(batch)
   >>> iterator.next()
@@ -117,7 +119,7 @@
   >>> iterator.next()
   'nine'
 
-Batch also implement some of IReadSequence interface
+Batch also implement some of IReadSequence interface::
 
   >>> 'eight' in batch
   True
@@ -135,48 +137,48 @@
   True
 
 Besides all of those common API methods, there are several properties that were
-designed to make your life simpler. The start and size are specified:
+designed to make your life simpler. The start and size are specified::
 
   >>> batch.start
   6
   >>> batch.size
   3
 
-The end index of the batch is immediately computed:
+The end index of the batch is immediately computed::
 
   >>> batch.end
   8
 
-The UI often requires that the number of the btach and the total number of
-batches is computed:
+The UI often requires that the number of the batch and the total number of
+batches is computed::
 
   >>> batch.number
   3
   >>> batch.total
   5
 
-You can also ask for the next batch:
+You can also ask for the next batch::
 
   >>> batch.next
   <Batch start=9, size=3>
 
-If the current batch is the last one, the next batch is None:
+If the current batch is the last one, the next batch is None::
 
   >>> Batch(sequence, start=12, size=3).next is None
   True
 
-The previous batch shows the previous batch:
+The previous batch shows the previous batch::
 
   >>> batch.previous
   <Batch start=3, size=3>
 
-If the current batch is the first one, the previous batch is None:
+If the current batch is the first one, the previous batch is None::
 
   >>> Batch(sequence, start=0, size=3).previous is None
   True
 
 The final two properties deal with the elements within the batch. They ask for
-the first and last element of the batch:
+the first and last element of the batch::
 
   >>> batch.firstElement
   'seven'
@@ -185,13 +187,13 @@
   'nine'
 
 
-Total batches
+Total batches::
 
   >>> batch = Batch(sequence[:-1], size=3)
   >>> batch.total
   4
 
-We can get access to all batches
+We can get access to all batches::
 
   >>> len(batch.batches)
   4
@@ -213,19 +215,40 @@
   >>> batch.batches[-2]
   <Batch start=6, size=3>
 
-Slicing
+Slicing::
 
   >>> batch.batches[:1]
   [<Batch start=0, size=3>]
-	
+
   >>> batch.batches[:]
   [<Batch start=0, size=3>, <Batch start=3, size=3>, <Batch start=6, size=3>, <Batch start=9, size=3>]
-	
+
   >>> batch.batches[1:2]
   [<Batch start=3, size=3>]
-	
+
   >>> batch.batches[1:]
   [<Batch start=3, size=3>, <Batch start=6, size=3>, <Batch start=9, size=3>]
 
   >>> batch.batches[10:]
   []
+
+Batch neighbourhood of a large batch list
+-----------------------------------------
+
+When the full list of batches is too large to be displayed in a user interface,
+we want to display only a subset of all the batches.
+A helper function is provided for that purpose:
+
+First build a large sequence of batches (or anything else)::
+
+  >>> batches = range(100)
+
+Then extract only the first and last items, as well as the neighbourhood of the
+46th item (index = 45). We want 3 neighbours at the left, 5 at the right::
+
+  >>> from z3c.batching.batch import first_neighbours_last
+  >>> first_neighbours_last(batches, 45, 3, 5)
+  [0, None, 42, 43, 44, 45, 46, 47, 48, 49, 50, None, 99]
+
+'None' can be used to display a separator in a user interface (see z3c.table) 
+

Modified: z3c.batching/trunk/src/z3c/batching/batch.py
===================================================================
--- z3c.batching/trunk/src/z3c/batching/batch.py	2008-10-10 23:25:42 UTC (rev 92030)
+++ z3c.batching/trunk/src/z3c/batching/batch.py	2008-10-11 11:24:15 UTC (rev 92031)
@@ -25,6 +25,8 @@
 
 
 class Batch(object):
+    """Batch implementation. See IBatch"""
+    
     zope.interface.implements(interfaces.IBatch)
 
     start = FieldProperty(interfaces.IBatch['start'])
@@ -146,6 +148,10 @@
 
 
 class Batches(object):
+    """A sequence object representing all the batches.
+       Used by a Batch.
+    """
+    
     zope.interface.implements(IFiniteSequence)
     
     def __init__(self, batch):
@@ -177,3 +183,126 @@
             j = self.total-1
 
         return [self[idx] for idx in range(i, j)]
+
+
+def first_neighbours_last(batches, currentBatchIdx, nb_left, nb_right):
+    """Build a sublist from a large batch list.
+
+    This is used to display batch links for a large table.
+
+    arguments:
+     * batches: a large sequence (may be a batches as well)
+     * currentBatchIdx: index of the current batch or item
+     * nb_left: number of neighbours before the current batch
+     * nb_right: number of neighbours after the current batch
+
+    The returned list gives:
+     * the first batch
+     * a None separator if necessary
+     * left neighbours of the current batch
+     * the current batch
+     * right neighbours of the current batch
+     * a None separator if necessary
+     * the last batch
+
+    Example::
+
+      >>> from z3c.batching.batch import first_neighbours_last as f_n_l
+      >>> batches = range(100) # it works with real batches as well
+
+    We try to get subsets at different levels::
+
+      >>> for i in range(0,6):
+      ...    f_n_l(batches, i, 2, 2)
+      [0, 1, 2, None, 99]
+      [0, 1, 2, 3, None, 99]
+      [0, 1, 2, 3, 4, None, 99]
+      [0, 1, 2, 3, 4, 5, None, 99]
+      [0, None, 2, 3, 4, 5, 6, None, 99]
+      [0, None, 3, 4, 5, 6, 7, None, 99]
+  
+      >>> for i in range(93, 99):
+      ...    f_n_l(batches, i, 2, 2)
+      [0, None, 91, 92, 93, 94, 95, None, 99]
+      [0, None, 92, 93, 94, 95, 96, None, 99]
+      [0, None, 93, 94, 95, 96, 97, None, 99]
+      [0, None, 94, 95, 96, 97, 98, 99]
+      [0, None, 95, 96, 97, 98, 99]
+      [0, None, 96, 97, 98, 99]
+
+    Try with no previous and no next batch::
+
+      >>> f_n_l(batches, 0, 0, 0)
+      [0, None, 99]
+      >>> f_n_l(batches, 1, 0, 0)
+      [0, 1, None, 99]
+      >>> f_n_l(batches, 2, 0, 0)
+      [0, None, 2, None, 99]
+
+    Try with only 1 previous and 1 next batch::
+
+      >>> f_n_l(batches, 0, 1, 1)
+      [0, 1, None, 99]
+      >>> f_n_l(batches, 1, 1, 1)
+      [0, 1, 2, None, 99]
+      >>> f_n_l(batches, 2, 1, 1)
+      [0, 1, 2, 3, None, 99]
+      >>> f_n_l(batches, 3, 1, 1)
+      [0, None, 2, 3, 4, None, 99]
+
+    Try with incoherent values::
+
+      >>> f_n_l(batches, 0, -4, -10)
+      Traceback (most recent call last):
+      ...
+      AssertionError
+      >>> f_n_l(batches, 2000, 3, 3)
+      Traceback (most recent call last):
+      ...
+      AssertionError
+    """
+    sublist = []
+    # setup some batches and indexes
+    firstIdx = 0
+    lastIdx = len(batches) - 1
+    assert(currentBatchIdx >= 0 and currentBatchIdx <= lastIdx)
+    assert(nb_left >= 0 and nb_right >= 0)
+    prevIdx = currentBatchIdx - nb_left
+    nextIdx = currentBatchIdx + 1
+    firstBatch = batches[0]
+    lastBatch = batches[len(batches)-1]
+
+    # add first batch
+    if firstIdx < currentBatchIdx:
+        sublist.append(firstBatch)
+
+    # there must probably be space
+    if firstIdx + 1 < prevIdx:
+        # we skip batches between first batch and first previous batch
+        sublist.append(None)
+
+    # add previous batches
+    for i in range(prevIdx, prevIdx + nb_left):
+        if firstIdx < i:
+            # append previous batches
+            sublist.append(batches[i])
+
+    # add current batch
+    sublist.append(batches[currentBatchIdx])
+
+    # add next batches
+    for i in range(nextIdx, nextIdx + nb_right):
+        if i < lastIdx:
+            # append previous batch
+            sublist.append(batches[i])
+
+    # there must probably be space
+    if nextIdx + nb_right < lastIdx:
+        # we skip batches between last batch and last next batch
+        sublist.append(None)
+
+    # add last batch
+    if currentBatchIdx < lastIdx:
+        sublist.append(lastBatch)
+    return sublist
+



More information about the Checkins mailing list