Log message for revision 118863: fix `LazyMap` to avoid unnecessary function calls when not accessing items in order (fixes http://dev.plone.org/plone/ticket/9018)
Changed: U Zope/branches/2.13/doc/CHANGES.rst U Zope/branches/2.13/src/Products/ZCatalog/Lazy.py U Zope/branches/2.13/src/Products/ZCatalog/tests/test_lazy.py -=- Modified: Zope/branches/2.13/doc/CHANGES.rst =================================================================== --- Zope/branches/2.13/doc/CHANGES.rst 2010-12-14 13:24:24 UTC (rev 118862) +++ Zope/branches/2.13/doc/CHANGES.rst 2010-12-14 14:12:11 UTC (rev 118863) @@ -11,6 +11,8 @@ Bugs Fixed ++++++++++ +- Fix `LazyMap` to avoid unnecessary function calls. + - LP 686664: WebDAV Lock Manager ZMI view wasn't accessible. 2.13.1 (2010-12-07) Modified: Zope/branches/2.13/src/Products/ZCatalog/Lazy.py =================================================================== --- Zope/branches/2.13/src/Products/ZCatalog/Lazy.py 2010-12-14 13:24:24 UTC (rev 118862) +++ Zope/branches/2.13/src/Products/ZCatalog/Lazy.py 2010-12-14 14:12:11 UTC (rev 118863) @@ -145,44 +145,28 @@ # Don't access data until necessary def __init__(self, func, seq, length=None): - self._seq = seq - self._data = [] - self._func = func + self._seq=seq + self._func=func if length is not None: - self._len = length + self._len=length else: self._len = len(seq) + self._marker = object() + self._data = [self._marker] * self._len - def __getitem__(self, index): - data = self._data + def __getitem__(self,index): + data=self._data try: - s = self._seq + 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.13/src/Products/ZCatalog/tests/test_lazy.py =================================================================== --- Zope/branches/2.13/src/Products/ZCatalog/tests/test_lazy.py 2010-12-14 13:24:24 UTC (rev 118862) +++ Zope/branches/2.13/src/Products/ZCatalog/tests/test_lazy.py 2010-12-14 14:12:11 UTC (rev 118863) @@ -113,7 +113,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): _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org https://mail.zope.org/mailman/listinfo/zope-checkins