[Checkins] SVN: z3c.batching/trunk/ New feature: Subset batch.

Jean-Francois Roche jfroche at jfroche.be
Fri Aug 20 10:51:10 EDT 2010


Log message for revision 115844:
  New feature: Subset batch.
  Sometimes (for performance reasons), even though the user needs
  a batched UI, we want to limit the computation to the
  subset of values actually shown to the user.
  
  

Changed:
  U   z3c.batching/trunk/CHANGES.txt
  U   z3c.batching/trunk/setup.py
  A   z3c.batching/trunk/src/z3c/batching/subset.py
  A   z3c.batching/trunk/src/z3c/batching/subset.txt
  U   z3c.batching/trunk/src/z3c/batching/tests.py

-=-
Modified: z3c.batching/trunk/CHANGES.txt
===================================================================
--- z3c.batching/trunk/CHANGES.txt	2010-08-20 14:50:38 UTC (rev 115843)
+++ z3c.batching/trunk/CHANGES.txt	2010-08-20 14:51:10 UTC (rev 115844)
@@ -5,6 +5,11 @@
 1.2.0 (unreleased)
 ------------------
 
+- New feature: Subset batch.
+  Sometimes (for performance reasons), even though the user needs
+  a batched UI, we want to limit the computation to the
+  subset of values actually shown to the user.
+
 - Register `batch.Batch` as named (``"z3c.batching.batch"``) factory.
 
 1.1.0 (2008-11-12)

Modified: z3c.batching/trunk/setup.py
===================================================================
--- z3c.batching/trunk/setup.py	2010-08-20 14:50:38 UTC (rev 115843)
+++ z3c.batching/trunk/setup.py	2010-08-20 14:51:10 UTC (rev 115844)
@@ -37,6 +37,8 @@
           + '\n\n'
           + read('src', 'z3c', 'batching', 'README.txt')
           + '\n\n'
+          + read('src', 'z3c', 'batching', 'subset.txt')
+          + '\n\n'
           + read('CHANGES.txt')),
       keywords="zope3 batching",
       classifiers=[

Added: z3c.batching/trunk/src/z3c/batching/subset.py
===================================================================
--- z3c.batching/trunk/src/z3c/batching/subset.py	                        (rev 0)
+++ z3c.batching/trunk/src/z3c/batching/subset.py	2010-08-20 14:51:10 UTC (rev 115844)
@@ -0,0 +1,100 @@
+##############################################################################
+#
+# Copyright (c) 2010 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Batching Implementation for subsets. Sometimes subsets
+can have pre batched values"""
+from z3c.batching.batch import Batch, Batches
+
+
+class EmptyBatch(Batch):
+
+    def __init__(self, length, start, size, batches):
+        self.update(length, start, size)
+        self.batches = batches
+
+    def __eq__(self, other):
+        return ((self.size, self.start, self._length) ==
+                (other.size, other.start, other._length))
+
+    @property
+    def firstElement(self):
+        raise ValueError("EmptyBatch holds no item")
+
+    @property
+    def lastElement(self):
+        raise ValueError("EmptyBatch holds no item")
+
+    def __getitem__(self, key):
+        raise ValueError("EmptyBatch holds no item")
+
+    def __iter__(self):
+        raise ValueError("EmptyBatch holds no item")
+
+
+class SubsetBatches(Batches):
+
+    def __init__(self, batch):
+        super(SubsetBatches, self).__init__(batch)
+        self.length = batch._length
+
+    def __getitem__(self, key):
+        if key not in self._batches:
+            if key < 0:
+                key = self.total + key
+
+            batch = EmptyBatch(
+                self.length, key * self.size, self.size, self)
+            self._batches[batch.index] = batch
+
+        try:
+            return self._batches[key]
+        except KeyError:
+            raise IndexError(key)
+
+
+class SubsetBatch(Batch):
+
+    def __init__(self, sequence, length, start=0, size=20, batches=None):
+        self.sequence = sequence
+        self.update(length, start, size)
+        self.updateBatches(batches)
+
+    def updateBatches(self, batches):
+        if batches is None:
+            batches = SubsetBatches(self)
+
+        self.batches = batches
+
+    @property
+    def firstElement(self):
+        """See interfaces.IBatch"""
+        return self.sequence[0]
+
+    @property
+    def lastElement(self):
+        """See interfaces.IBatch"""
+        return self.sequence[-1]
+
+    def __getitem__(self, key):
+        """See zope.interface.common.sequence.IMinimalSequence"""
+        if key >= self._trueSize:
+            raise IndexError('batch index out of range')
+        return self.sequence[key]
+
+    def __iter__(self):
+        """See zope.interface.common.sequence.IMinimalSequence"""
+        return iter(self.sequence)
+
+    def __eq__(self, other):
+        return ((self.size, self.start, self._length) ==
+                (other.size, other.start, other._length))

Added: z3c.batching/trunk/src/z3c/batching/subset.txt
===================================================================
--- z3c.batching/trunk/src/z3c/batching/subset.txt	                        (rev 0)
+++ z3c.batching/trunk/src/z3c/batching/subset.txt	2010-08-20 14:51:10 UTC (rev 115844)
@@ -0,0 +1,76 @@
+Subset Batching
+---------------
+
+  >>> from z3c.batching.subset import SubsetBatch
+
+Sometimes (for performance reasons), even though the user needs
+a batched UI, we want to limit the computation to the
+subset of values actually shown to the user.
+
+Because we initialize the batch with a subset of data, we also
+need to provide explicitly the length of the full data set.
+
+Let's create a subset of data::
+
+  >>> data = range(20, 30)
+
+We use it as part of a longer data set::
+
+  >>> batch = SubsetBatch(data, length=50, start=20, size=10)
+
+Full API check::
+
+  >>> batch.firstElement
+  20
+  >>> batch.lastElement
+  29
+  >>> batch.index
+  2
+  >>> batch.number
+  3
+  >>> batch.total
+  5
+  >>> batch[2]
+  22
+  >>> len(batch)
+  10
+  >>> batch[-1] == batch.lastElement
+  True
+  >>> [item for item in batch]
+  [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
+
+  >>> batch.next
+  <EmptyBatch start=30, size=10>
+  >>> batch.previous
+  <EmptyBatch start=10, size=10>
+  >>> batch.next.previous == batch
+  True
+  >>> 22 in batch
+  True
+  >>> 10 in batch
+  False
+  >>> batch[5:8]
+  [25, 26, 27]
+
+You have seen above that the contiguous batches are instances of
+the ``EmptyBatch`` class. As those instances hold no data, we raise errors to ensure that no batch provider tries to display item data::
+
+  >>> empty = batch.next
+  >>> empty
+  <EmptyBatch start=30, size=10>
+  >>> empty.firstElement
+  Traceback (most recent call last):
+  ...
+  ValueError: EmptyBatch holds no item
+  >>> empty.lastElement
+  Traceback (most recent call last):
+  ...
+  ValueError: EmptyBatch holds no item
+  >>> empty[0]
+  Traceback (most recent call last):
+  ...
+  ValueError: EmptyBatch holds no item
+  >>> [item for item in empty]
+  Traceback (most recent call last):
+  ...
+  ValueError: EmptyBatch holds no item

Modified: z3c.batching/trunk/src/z3c/batching/tests.py
===================================================================
--- z3c.batching/trunk/src/z3c/batching/tests.py	2010-08-20 14:50:38 UTC (rev 115843)
+++ z3c.batching/trunk/src/z3c/batching/tests.py	2010-08-20 14:51:10 UTC (rev 115844)
@@ -27,6 +27,9 @@
         doctest.DocFileSuite(
                 'README.txt',
                 optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS),
+        doctest.DocFileSuite(
+                'subset.txt',
+                optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS),
         doctest.DocTestSuite(batch,
                 optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS),
         ))



More information about the checkins mailing list