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 ...@@ -8,6 +8,10 @@ Zope Changes
Features Added 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 - ZTUtils.Tree.TreeMaker now has additional methods for setting
various flags and attributes that influence how the tree is built, various flags and attributes that influence how the tree is built,
making these aspects accessible to PythonScripts. making these aspects accessible to PythonScripts.
......
...@@ -18,8 +18,8 @@ The Iterator() function accepts either a sequence or a Python ...@@ -18,8 +18,8 @@ The Iterator() function accepts either a sequence or a Python
iterator. The next() method fetches the next item, and returns iterator. The next() method fetches the next item, and returns
true if it succeeds. true if it succeeds.
$Id: Iterator.py,v 1.8 2002/09/26 17:29:45 evan Exp $''' $Id: Iterator.py,v 1.9 2002/10/09 17:33:49 evan Exp $'''
__version__='$Revision: 1.8 $'[11:-2] __version__='$Revision: 1.9 $'[11:-2]
class Iterator: class Iterator:
'''Simple Iterator class''' '''Simple Iterator class'''
...@@ -29,11 +29,10 @@ class Iterator: ...@@ -29,11 +29,10 @@ class Iterator:
nextIndex = 0 nextIndex = 0
def __init__(self, seq): def __init__(self, seq):
self.seq = seq self.seq = seq
for inner in seqInner, iterInner: if iterInner._supports(seq, self):
if inner._supports(seq): self._inner = iterInner
self._inner = inner self._prep_next = iterInner.prep_next
self._prep_next = inner.prep_next return
return
raise TypeError, "Iterator does not support %s" % `seq` raise TypeError, "Iterator does not support %s" % `seq`
def __getattr__(self, name): def __getattr__(self, name):
...@@ -130,48 +129,19 @@ class InnerBase: ...@@ -130,48 +129,19 @@ class InnerBase:
return 0 return 0
return not self.prep_next(it) 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): 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: try:
if hasattr(ob, 'next') and (ob is iter(ob)): it.iter = iter(ob)
return 1 return 1
except: except:
return 0 return 0
def prep_next(self, it): def prep_next(self, it):
try: try:
it._next = it.seq.next() it._next = it.iter.next()
except StopIteration: except StopIteration:
it._prep_next = self.no_next it._prep_next = self.no_next
it.end = 1 it.end = 1
...@@ -192,5 +162,4 @@ class IterIter: ...@@ -192,5 +162,4 @@ class IterIter:
return it.item return it.item
raise StopIteration raise StopIteration
seqInner = SeqInner()
iterInner = IterInner() iterInner = IterInner()
from __future__ import generators
import os, sys, unittest import os, sys, unittest
from ZTUtils import Iterator from ZTUtils import Iterator
...@@ -8,6 +9,26 @@ try: ...@@ -8,6 +9,26 @@ try:
except NameError: except NameError:
do_piter_test = 0 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): class IteratorTests(unittest.TestCase):
def testIterator0(self): def testIterator0(self):
...@@ -48,14 +69,21 @@ class IteratorTests(unittest.TestCase): ...@@ -48,14 +69,21 @@ class IteratorTests(unittest.TestCase):
assert not it.end, ( assert not it.end, (
"End false on element %s of %s" % (el, size)) "End false on element %s of %s" % (el, size))
def testIndex(self): def assertRangeMatch(self, ob, n):
it = Iterator(range(5)) it = Iterator(ob)
for el in range(5): for el in range(n):
assert it.next(), "Iterator stopped too soon" assert it.next(), "Iterator stopped too soon"
assert it.index == el, "Incorrect index" assert it.index == el, "Incorrect index"
assert it.number() == el + 1, "Incorrect number" assert it.number() == el + 1, "Incorrect number"
assert it.item == el, "Incorrect item" 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): def testFirstLast(self):
it = Iterator([1]) it = Iterator([1])
it.next() 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