Commit 31674e78 authored by Evan Simpson's avatar Evan Simpson

Close Collector #385, #577 and simplify ZTUtils.Iterator implementation.

parent a62b6382
......@@ -8,6 +8,10 @@ Zope Changes
Features Added
- ZTUtils.Iterator now handles any object that has a Python
iterator, resolving Collector #385 and #577. The
implementation is somwhat simpler, as well.
- ZTUtils.Tree.TreeMaker now has additional methods for setting
various flags and attributes that influence how the tree is built,
making these aspects accessible to PythonScripts.
......
......@@ -18,8 +18,8 @@ The Iterator() function accepts either a sequence or a Python
iterator. The next() method fetches the next item, and returns
true if it succeeds.
$Id: Iterator.py,v 1.8 2002/09/26 17:29:45 evan Exp $'''
__version__='$Revision: 1.8 $'[11:-2]
$Id: Iterator.py,v 1.9 2002/10/09 17:33:49 evan Exp $'''
__version__='$Revision: 1.9 $'[11:-2]
class Iterator:
'''Simple Iterator class'''
......@@ -29,11 +29,10 @@ class Iterator:
nextIndex = 0
def __init__(self, seq):
self.seq = seq
for inner in seqInner, iterInner:
if inner._supports(seq):
self._inner = inner
self._prep_next = inner.prep_next
return
if iterInner._supports(seq, self):
self._inner = iterInner
self._prep_next = iterInner.prep_next
return
raise TypeError, "Iterator does not support %s" % `seq`
def __getattr__(self, name):
......@@ -130,48 +129,19 @@ class InnerBase:
return 0
return not self.prep_next(it)
class SeqInner(InnerBase):
'''Inner class for sequence Iterators'''
def _supports(self, ob):
try: ob[0]
except (TypeError, AttributeError): return 0
except: pass
return 1
def prep_next(self, it):
i = it.nextIndex
try:
it._next = it.seq[i]
except IndexError:
it._prep_next = self.no_next
it.end = 1
return 0
it.end = 0
return 1
def it_length(self, it):
it.length = l = len(it.seq)
return l
try:
StopIteration=StopIteration
except NameError:
StopIteration="StopIteration"
class IterInner(InnerBase):
'''Iterator inner class for Python iterators'''
'''Iterator inner class for objects with Python iterators'''
def _supports(self, ob):
def _supports(self, ob, it):
try:
if hasattr(ob, 'next') and (ob is iter(ob)):
return 1
it.iter = iter(ob)
return 1
except:
return 0
def prep_next(self, it):
try:
it._next = it.seq.next()
it._next = it.iter.next()
except StopIteration:
it._prep_next = self.no_next
it.end = 1
......@@ -192,5 +162,4 @@ class IterIter:
return it.item
raise StopIteration
seqInner = SeqInner()
iterInner = IterInner()
from __future__ import generators
import os, sys, unittest
from ZTUtils import Iterator
......@@ -8,6 +9,26 @@ try:
except NameError:
do_piter_test = 0
class itemIterator:
'Ignore the __getitem__ argument in order to catch non-monotonic access.'
def __init__(self, n):
self.n = n
self.i = 0
def __getitem__(self, i):
if self.i >= self.n:
raise IndexError
i = self.i
self.i = self.i + 1
return i
class genIterator:
'Generator-based iteration'
def __init__(self, n):
self.n = n
def __iter__(self):
for i in range(self.n):
yield i
class IteratorTests(unittest.TestCase):
def testIterator0(self):
......@@ -48,14 +69,21 @@ class IteratorTests(unittest.TestCase):
assert not it.end, (
"End false on element %s of %s" % (el, size))
def testIndex(self):
it = Iterator(range(5))
for el in range(5):
def assertRangeMatch(self, ob, n):
it = Iterator(ob)
for el in range(n):
assert it.next(), "Iterator stopped too soon"
assert it.index == el, "Incorrect index"
assert it.number() == el + 1, "Incorrect number"
assert it.item == el, "Incorrect item"
def testIndex(self):
self.assertRangeMatch(range(5), 5)
self.assertRangeMatch((0,1,2,3,4), 5)
self.assertRangeMatch({0:0, 1:1, 2:2, 3:3, 4:4}, 5)
self.assertRangeMatch(itemIterator(5), 5)
self.assertRangeMatch(genIterator(5), 5)
def testFirstLast(self):
it = Iterator([1])
it.next()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment