[Zope-Checkins] SVN: Zope/branches/2.12/ back-port c118863 from 2.13

Andreas Zeidler az at zitc.de
Tue Dec 14 09:13:14 EST 2010


Log message for revision 118864:
  back-port c118863 from 2.13
  

Changed:
  U   Zope/branches/2.12/doc/CHANGES.rst
  U   Zope/branches/2.12/src/Products/ZCatalog/Lazy.py
  U   Zope/branches/2.12/src/Products/ZCatalog/tests/testLazySequences.py

-=-
Modified: Zope/branches/2.12/doc/CHANGES.rst
===================================================================
--- Zope/branches/2.12/doc/CHANGES.rst	2010-12-14 14:12:11 UTC (rev 118863)
+++ Zope/branches/2.12/doc/CHANGES.rst	2010-12-14 14:13:14 UTC (rev 118864)
@@ -11,6 +11,7 @@
 Bugs Fixed
 ++++++++++
 
+- Fix `LazyMap` to avoid unnecessary function calls.
 
 2.12.14 (2010-12-07)
 --------------------

Modified: Zope/branches/2.12/src/Products/ZCatalog/Lazy.py
===================================================================
--- Zope/branches/2.12/src/Products/ZCatalog/Lazy.py	2010-12-14 14:12:11 UTC (rev 118863)
+++ Zope/branches/2.12/src/Products/ZCatalog/Lazy.py	2010-12-14 14:13:14 UTC (rev 118864)
@@ -134,36 +134,22 @@
 
     def __init__(self, func, seq, length=None):
         self._seq=seq
-        self._data=[]
         self._func=func
         if length is not None: self._len=length
         else: self._len = len(seq)
+        self._marker = object()
+        self._data = [self._marker] * self._len
 
     def __getitem__(self,index):
-
         data=self._data
         try: s=self._seq
         except AttributeError: return data[index]
 
-        i=index
-        if i < 0: i=len(self)+i
-        if i < 0: raise IndexError, index
+        value = data[index]
+        if value is self._marker:
+            value = data[index] = self._func(s[index])
+        return value
 
-        ind=len(data)
-        if i < ind: return data[i]
-        ind=ind-1
-
-        func=self._func
-        while i > ind:
-            try:
-                ind=ind+1
-                data.append(func(s[ind]))
-            except IndexError:
-                del self._func
-                del self._seq
-                raise IndexError, index
-        return data[i]
-
 class LazyFilter(Lazy):
     # Act like a sequence, but get data from a filtering process.
     # Don't access data until necessary. Only data for which test(data) 

Modified: Zope/branches/2.12/src/Products/ZCatalog/tests/testLazySequences.py
===================================================================
--- Zope/branches/2.12/src/Products/ZCatalog/tests/testLazySequences.py	2010-12-14 14:12:11 UTC (rev 118863)
+++ Zope/branches/2.12/src/Products/ZCatalog/tests/testLazySequences.py	2010-12-14 14:13:14 UTC (rev 118864)
@@ -98,7 +98,17 @@
         lmap = self._createLMap(filter, seq1, seq2, seq3)
         self._compare(lmap, [str(x).lower() for x in (seq1 + seq2 + seq3)])
 
+    def testMapFuncIsOnlyCalledAsNecessary(self):
+        seq = range(10)
+        count = [0]     # closure only works with list, and `nonlocal` in py3
+        def func(x):
+            count[0] += 1
+            return x
+        lmap = self._createLMap(func, seq)
+        self.assertEqual(lmap[5], 5)
+        self.assertEqual(count[0], 1)
 
+
 class TestLazyFilter(TestLazyCat):
     def _createLSeq(self, *seq):
         return self._createLFilter(lambda x: True, *seq)



More information about the Zope-Checkins mailing list