Rev 4744: Add __iter__ support. in http://bazaar.launchpad.net/~jameinel/bzr/2.1-static-tuple

John Arbash Meinel john at arbash-meinel.com
Fri Oct 2 21:32:55 BST 2009


At http://bazaar.launchpad.net/~jameinel/bzr/2.1-static-tuple

------------------------------------------------------------
revno: 4744
revision-id: john at arbash-meinel.com-20091002203250-q6iv6o2mwjqp4g53
parent: john at arbash-meinel.com-20091002201552-tzrgn1g92ujxt3wu
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.1-static-tuple
timestamp: Fri 2009-10-02 15:32:50 -0500
message:
  Add __iter__ support.
-------------- next part --------------
=== modified file 'bzrlib/_static_tuple_interned_pyx.pyx'
--- a/bzrlib/_static_tuple_interned_pyx.pyx	2009-10-02 20:15:52 +0000
+++ b/bzrlib/_static_tuple_interned_pyx.pyx	2009-10-02 20:32:50 +0000
@@ -312,6 +312,59 @@
         if not exists:
             raise KeyError('Key %s not present' % (key,))
 
+    def __iter__(self):
+        return _StaticTupleInterner_iterator(self)
+
+
+cdef class _StaticTupleInterner_iterator:
+    """Iterator over the StaticTupleInterner structure."""
+
+    cdef Py_ssize_t pos
+    cdef StaticTupleInterner table
+    cdef Py_ssize_t used # track if things have been mutated while iterating
+    cdef Py_ssize_t len # number of entries left
+
+    def __init__(self, obj):
+        self.table = obj
+        self.pos = 0
+        self.used = self.table.used
+        self.len = self.table.used
+
+    def __iter__(self):
+        return self
+
+    def __next__(self):
+        cdef Py_ssize_t mask, i
+        cdef PyObject **table
+
+        if self.table is None:
+            raise StopIteration
+        if self.table.used != self.used:
+            # Force this exception to continue to be raised
+            self.used = -1
+            raise RuntimeError("Set size changed during iteration")
+        i = self.pos
+        mask = self.table.mask
+        table = self.table.table
+        assert i >= 0
+        while i <= mask and (table[i] == NULL or table[i] == _dummy):
+            i += 1
+        self.pos = i + 1
+        if i > mask:
+            # we walked to the end
+            self.table = None
+            raise StopIteration
+        # We must have found one
+        key = <object>(table[i])
+        self.len -= 1
+        return key
+
+    def __length_hint__(self):
+        if self.table is not None and self.used == self.table.used:
+            return self.len
+        return 0
+    
+
 
 cdef api StaticTupleInterner StaticTupleInterner_New():
     """Create a new StaticTupleInterner object."""

=== modified file 'bzrlib/tests/test__static_tuple_interned.py'
--- a/bzrlib/tests/test__static_tuple_interned.py	2009-10-02 20:15:52 +0000
+++ b/bzrlib/tests/test__static_tuple_interned.py	2009-10-02 20:32:50 +0000
@@ -283,3 +283,24 @@
         self.assertFillState(0, obj.fill, 0x3ff, obj)
         # but there should be fewer than 1/5th dummy entries
         self.assertTrue(obj.fill < 1024 / 5)
+
+    def test__iter__(self):
+        obj = _module.StaticTupleInterner()
+        k1 = StaticTuple('1')
+        k2 = StaticTuple('1', '2')
+        k3 = StaticTuple('3', '4')
+        obj.add(k1)
+        obj.add(k2)
+        obj.add(k3)
+        all = set()
+        for key in obj:
+            all.add(key)
+        self.assertEqual(sorted([k1, k2, k3]), sorted(all))
+        iterator = iter(obj)
+        iterator.next()
+        obj.add(StaticTuple('foo'))
+        # Set changed size
+        self.assertRaises(RuntimeError, iterator.next)
+        # And even removing an item still causes it to fail
+        del obj[k2]
+        self.assertRaises(RuntimeError, iterator.next)



More information about the bazaar-commits mailing list