[Zope-Checkins] CVS: Zope3/lib/python/Persistence/BTrees/tests - testBTrees.py:1.17

Tim Peters tim.one@comcast.net
Sat, 22 Jun 2002 15:35:27 -0400


Update of /cvs-repository/Zope3/lib/python/Persistence/BTrees/tests
In directory cvs.zope.org:/tmp/cvs-serv3613/tests

Modified Files:
	testBTrees.py 
Log Message:
Like Python 2.2 dicts, all flavors of BTree and Bucket (but not Set or
TreeSet) in Zope3 now support new .iterkeys(), .itervalues() and
.iteritems() methods.  These return iterators for the object's keys,
values or items.  Unlike Python dicts, but like BTree and Bucket .keys(),
.values() and .items() methods, .iter{key,value,item}s support optional
lo and hi range arguments (to restrict the elements generated to those
whose keys are in lo thru hi inclusive).

For BTrees, the .iterXYZ versions are a little faster than their
non-iter versions.  Both are "lazy" (elements are generated as needed,
not materialized in one gulp at the start).

The .iterXYZ versions are also "lazy" for Buckets, but the non-iter
versions are not.  That is, bucket.items() has always materialized a
possibly giant list of two-tuples, but bucket.iteritems() yields a
small iterator object that knows how to produce the right pairs as
needed.  So, for example, the peak memory use for

    for k, v in bucket.iteritems():

is small and independent of len(bucket), while

    for k, v in bucket.items():

requires memory proportional to len(bucket) right at the start.


=== Zope3/lib/python/Persistence/BTrees/tests/testBTrees.py 1.16 => 1.17 ===
         for i in range(100):
             self.assertEqual(v[i], i*i)
+        i = 0
+        for value in self.t.itervalues():
+            self.assertEqual(value, i*i)
+            i += 1
 
     def testValuesWorks1(self):
         for x in range(100):
@@ -193,13 +197,18 @@
 
     def testItemsWorks(self):
         for x in range(100):
-            self.t[x] = x
+            self.t[x] = 2*x
         v = self.t.items()
         i = 0
         for x in v:
-            self.assertEqual(x[0] , i, (x[0], i))
-            self.assertEqual(x[1] , i, (x[0], i))
-            i = i + 1
+            self.assertEqual(x[0], i)
+            self.assertEqual(x[1], 2*i)
+            i += 1
+
+        i = 0
+        for x in self.t.iteritems():
+            self.assertEqual(x, (i, 2*i))
+            i += 1
 
     def testDeleteInvalidKeyRaisesKeyError(self):
         self.assertRaises(KeyError, self._deletefail)
@@ -270,6 +279,7 @@
         keys = t.keys(200, 50)
         self.assertEqual(len(keys), 0)
         self.assertEqual(list(keys), [])
+        self.assertEqual(list(t.iterkeys(200, 50)), [])
 
     def testSlicing(self):
         # Test that slicing of .keys()/.values()/.items() works exactly the
@@ -347,7 +357,7 @@
         self.assertEqual(len(tslice), 60)
         self.assertEqual(list(tslice), zip(range(20, 80), [1]*60))
 
-    def testIterator(self):
+    def testIterators(self):
         t = self.t
 
         for keys in [], [-2], [1, 4], range(-170, 2000, 6):
@@ -371,6 +381,59 @@
             except StopIteration:
                 pass
             self.assertEqual(x, keys)
+
+            self.assertEqual(list(t.iterkeys()), keys)
+            self.assertEqual(list(t.itervalues()), list(t.values()))
+            self.assertEqual(list(t.iteritems()), list(t.items()))
+
+    def testRangedIterators(self):
+        t = self.t
+
+        for keys in [], [-2], [1, 4], range(-170, 2000, 13):
+            t.clear()
+            values = []
+            for k in keys:
+                value = -3 * k
+                t[k] = value
+                values.append(value)
+            items = zip(keys, values)
+
+            self.assertEqual(list(t.iterkeys()), keys)
+            self.assertEqual(list(t.itervalues()), values)
+            self.assertEqual(list(t.iteritems()), items)
+
+            if not keys:
+                continue
+
+            min_mid_max = (keys[0], keys[len(keys) >> 1], keys[-1])
+            for key1 in min_mid_max:
+                for lo in range(key1 - 1, key1 + 2):
+                    # Test one-sided range iterators.
+                    goodkeys = [k for k in keys if lo <= k]
+                    got = t.iterkeys(lo)
+                    self.assertEqual(goodkeys, list(got))
+
+                    goodvalues = [t[k] for k in goodkeys]
+                    got = t.itervalues(lo)
+                    self.assertEqual(goodvalues, list(got))
+
+                    gooditems = zip(goodkeys, goodvalues)
+                    got = t.iteritems(lo)
+                    self.assertEqual(gooditems, list(got))
+
+                    for key2 in min_mid_max:
+                        for hi in range(key2 - 1, key2 + 2):
+                            goodkeys = [k for k in keys if lo <= k <= hi]
+                            got = t.iterkeys(lo, hi)
+                            self.assertEqual(goodkeys, list(got))
+
+                            goodvalues = [t[k] for k in goodkeys]
+                            got = t.itervalues(lo, hi)
+                            self.assertEqual(goodvalues, list(got))
+
+                            gooditems = zip(goodkeys, goodvalues)
+                            got = t.iteritems(lo, hi)
+                            self.assertEqual(gooditems, list(got))
 
 class NormalSetTests(Base):
     """ Test common to all set types """