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