Mercurial > p > roundup > code
comparison roundup/cgi/ZTUtils/Iterator.py @ 1049:b9988e118055
moved
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Thu, 05 Sep 2002 00:37:09 +0000 |
| parents | |
| children | 69bf0d381fd7 |
comparison
equal
deleted
inserted
replaced
| 1048:1250251f2793 | 1049:b9988e118055 |
|---|---|
| 1 ############################################################################## | |
| 2 # | |
| 3 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. | |
| 4 # | |
| 5 # This software is subject to the provisions of the Zope Public License, | |
| 6 # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. | |
| 7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | |
| 8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | |
| 10 # FOR A PARTICULAR PURPOSE | |
| 11 # | |
| 12 ############################################################################## | |
| 13 __doc__='''Iterator class | |
| 14 | |
| 15 Unlike the builtin iterators of Python 2.2+, these classes are | |
| 16 designed to maintain information about the state of an iteration. | |
| 17 The Iterator() function accepts either a sequence or a Python | |
| 18 iterator. The next() method fetches the next item, and returns | |
| 19 true if it succeeds. | |
| 20 | |
| 21 $Id: Iterator.py,v 1.1 2002-09-05 00:37:09 richard Exp $''' | |
| 22 __version__='$Revision: 1.1 $'[11:-2] | |
| 23 | |
| 24 import string | |
| 25 | |
| 26 class Iterator: | |
| 27 '''Simple Iterator class''' | |
| 28 | |
| 29 __allow_access_to_unprotected_subobjects__ = 1 | |
| 30 | |
| 31 nextIndex = 0 | |
| 32 def __init__(self, seq): | |
| 33 self.seq = seq | |
| 34 for inner in seqInner, iterInner: | |
| 35 if inner._supports(seq): | |
| 36 self._inner = inner | |
| 37 self._prep_next = inner.prep_next | |
| 38 return | |
| 39 raise TypeError, "Iterator does not support %s" % `seq` | |
| 40 | |
| 41 def __getattr__(self, name): | |
| 42 try: | |
| 43 inner = getattr(self._inner, 'it_' + name) | |
| 44 except AttributeError: | |
| 45 raise AttributeError, name | |
| 46 return inner(self) | |
| 47 | |
| 48 def next(self): | |
| 49 if not (hasattr(self, '_next') or self._prep_next(self)): | |
| 50 return 0 | |
| 51 self.index = i = self.nextIndex | |
| 52 self.nextIndex = i+1 | |
| 53 self._advance(self) | |
| 54 return 1 | |
| 55 | |
| 56 def _advance(self, it): | |
| 57 self.item = self._next | |
| 58 del self._next | |
| 59 del self.end | |
| 60 self._advance = self._inner.advance | |
| 61 self.start = 1 | |
| 62 | |
| 63 def number(self): return self.nextIndex | |
| 64 | |
| 65 def even(self): return not self.index % 2 | |
| 66 | |
| 67 def odd(self): return self.index % 2 | |
| 68 | |
| 69 def letter(self, base=ord('a'), radix=26): | |
| 70 index = self.index | |
| 71 s = '' | |
| 72 while 1: | |
| 73 index, off = divmod(index, radix) | |
| 74 s = chr(base + off) + s | |
| 75 if not index: return s | |
| 76 | |
| 77 def Letter(self): | |
| 78 return self.letter(base=ord('A')) | |
| 79 | |
| 80 def Roman(self, rnvalues=( | |
| 81 (1000,'M'),(900,'CM'),(500,'D'),(400,'CD'), | |
| 82 (100,'C'),(90,'XC'),(50,'L'),(40,'XL'), | |
| 83 (10,'X'),(9,'IX'),(5,'V'),(4,'IV'),(1,'I')) ): | |
| 84 n = self.index + 1 | |
| 85 s = '' | |
| 86 for v, r in rnvalues: | |
| 87 rct, n = divmod(n, v) | |
| 88 s = s + r * rct | |
| 89 return s | |
| 90 | |
| 91 def roman(self, lower=string.lower): | |
| 92 return lower(self.Roman()) | |
| 93 | |
| 94 def first(self, name=None): | |
| 95 if self.start: return 1 | |
| 96 return not self.same_part(name, self._last, self.item) | |
| 97 | |
| 98 def last(self, name=None): | |
| 99 if self.end: return 1 | |
| 100 return not self.same_part(name, self.item, self._next) | |
| 101 | |
| 102 def same_part(self, name, ob1, ob2): | |
| 103 if name is None: | |
| 104 return ob1 == ob2 | |
| 105 no = [] | |
| 106 return getattr(ob1, name, no) == getattr(ob2, name, no) is not no | |
| 107 | |
| 108 def __iter__(self): | |
| 109 return IterIter(self) | |
| 110 | |
| 111 class InnerBase: | |
| 112 '''Base Inner class for Iterators''' | |
| 113 # Prep sets up ._next and .end | |
| 114 def prep_next(self, it): | |
| 115 it.next = self.no_next | |
| 116 it.end = 1 | |
| 117 return 0 | |
| 118 | |
| 119 # Advance knocks them down | |
| 120 def advance(self, it): | |
| 121 it._last = it.item | |
| 122 it.item = it._next | |
| 123 del it._next | |
| 124 del it.end | |
| 125 it.start = 0 | |
| 126 | |
| 127 def no_next(self, it): | |
| 128 return 0 | |
| 129 | |
| 130 def it_end(self, it): | |
| 131 if hasattr(it, '_next'): | |
| 132 return 0 | |
| 133 return not self.prep_next(it) | |
| 134 | |
| 135 class SeqInner(InnerBase): | |
| 136 '''Inner class for sequence Iterators''' | |
| 137 | |
| 138 def _supports(self, ob): | |
| 139 try: ob[0] | |
| 140 except TypeError: return 0 | |
| 141 except: pass | |
| 142 return 1 | |
| 143 | |
| 144 def prep_next(self, it): | |
| 145 i = it.nextIndex | |
| 146 try: | |
| 147 it._next = it.seq[i] | |
| 148 except IndexError: | |
| 149 it._prep_next = self.no_next | |
| 150 it.end = 1 | |
| 151 return 0 | |
| 152 it.end = 0 | |
| 153 return 1 | |
| 154 | |
| 155 def it_length(self, it): | |
| 156 it.length = l = len(it.seq) | |
| 157 return l | |
| 158 | |
| 159 try: | |
| 160 StopIteration=StopIteration | |
| 161 except NameError: | |
| 162 StopIteration="StopIteration" | |
| 163 | |
| 164 class IterInner(InnerBase): | |
| 165 '''Iterator inner class for Python iterators''' | |
| 166 | |
| 167 def _supports(self, ob): | |
| 168 try: | |
| 169 if hasattr(ob, 'next') and (ob is iter(ob)): | |
| 170 return 1 | |
| 171 except: | |
| 172 return 0 | |
| 173 | |
| 174 def prep_next(self, it): | |
| 175 try: | |
| 176 it._next = it.seq.next() | |
| 177 except StopIteration: | |
| 178 it._prep_next = self.no_next | |
| 179 it.end = 1 | |
| 180 return 0 | |
| 181 it.end = 0 | |
| 182 return 1 | |
| 183 | |
| 184 class IterIter: | |
| 185 def __init__(self, it): | |
| 186 self.it = it | |
| 187 self.skip = it.nextIndex > 0 and not it.end | |
| 188 def next(self): | |
| 189 it = self.it | |
| 190 if self.skip: | |
| 191 self.skip = 0 | |
| 192 return it.item | |
| 193 if it.next(): | |
| 194 return it.item | |
| 195 raise StopIteration | |
| 196 | |
| 197 seqInner = SeqInner() | |
| 198 iterInner = IterInner() |
