[Zope-Checkins] CVS: Zope/lib/python/Products/ZCatalog - Catalog.py:1.104 Lazy.py:1.9

Casey Duncan casey@zope.com
Wed, 11 Dec 2002 13:56:58 -0500


Update of /cvs-repository/Zope/lib/python/Products/ZCatalog
In directory cvs.zope.org:/tmp/cvs-serv9541

Modified Files:
	Catalog.py Lazy.py 
Log Message:
Refactor Lazy concatenation to remove some old cruft and simplify the code
Catalog empty results are now always a LazyCat([]) rather than a LazyCat(SomeEmptySequencishThingFromTheIndexes)


=== Zope/lib/python/Products/ZCatalog/Catalog.py 1.103 => 1.104 ===
--- Zope/lib/python/Products/ZCatalog/Catalog.py:1.103	Mon Dec  9 17:58:18 2002
+++ Zope/lib/python/Products/ZCatalog/Catalog.py	Wed Dec 11 13:56:58 2002
@@ -519,7 +519,7 @@
                 return self.sortResults(rs, sort_index, reverse, limit, merge)
         else:
             # Empty result set
-            return LazyCat(rs)
+            return LazyCat([])
 
     def sortResults(self, rs, sort_index, reverse=0, limit=None, merge=1):
         # Sort a result set using a sort index. Return a lazy


=== Zope/lib/python/Products/ZCatalog/Lazy.py 1.8 => 1.9 ===
--- Zope/lib/python/Products/ZCatalog/Lazy.py:1.8	Thu Dec  5 16:17:05 2002
+++ Zope/lib/python/Products/ZCatalog/Lazy.py	Wed Dec 11 13:56:58 2002
@@ -22,7 +22,7 @@
     def __repr__(self): return `list(self)`
 
     def __len__(self):
-
+        # This is a worst-case len, subclasses should try to do better
         try: return self._len
         except AttributeError: pass
 
@@ -34,34 +34,13 @@
             except:
                 self._len=l
                 return l
+                
 
     def __add__(self, other):
-        try:
-            for base in other.__class__.__bases__:
-                if base.__name__ == 'Lazy':
-                    break
-            else:
-                raise TypeError
-        except:
-            raise TypeError, "Can not concatenate objects. Both must be lazy sequences."
-
-        if self.__class__.__name__ == 'LazyCat':
-            if hasattr(self, '_seq'):
-                seq = self._seq
-            else:
-                seq = [self._data]
-        else:
-            seq = [self]
-
-        if other.__class__.__name__ == 'LazyCat':
-            if hasattr(other, '_seq'):
-                seq = seq + other._seq
-            else:
-                seq.append(other._data)
-        else:
-            seq.append(other)
-
-        return LazyCat(seq)
+        if not isinstance(other, Lazy):
+            raise TypeError(
+                "Can not concatenate objects. Both must be lazy sequences.")
+        return LazyCat([self, other])
 
     def __getslice__(self,i1,i2):
         r=[]
@@ -77,6 +56,19 @@
     # for accessing small parts of big searches.
 
     def __init__(self, sequences, length=None):
+        if len(sequences) < 100:
+            # Optimize structure of LazyCats to avoid nesting
+            # We don't do this for large numbers of input sequences
+            # to make instantiation faster instead
+            flattened_seq = []
+            for s in sequences:
+                if isinstance(s, LazyCat):
+                    # If one of the sequences passed is itself a LazyCat, add
+                    # its base sequences rather than nest LazyCats
+                    flattened_seq.extend(s._seq)
+                else:
+                    flattened_seq.append(s)
+            sequences = flattened_seq
         self._seq=sequences
         self._data=[]
         self._sindex=0
@@ -118,6 +110,18 @@
                 self._eindex=eindex=-1
         self._eindex=eindex
         return data[i]
+        
+    def __len__(self):
+        # Make len of LazyCat only as expensive as the lens 
+        # of its underlying sequences
+        try:
+            return self._len
+        except:
+            l = 0
+            for s in self._seq:
+               l += len(s)
+            self._len = l
+            return l
 
 class LazyMap(Lazy):
     # Act like a sequence, but get data from a filtering process.