Mercurial > p > roundup > code
annotate roundup/cgi/ZTUtils/Iterator.py @ 8241:741ea8a86012
fix: issue2551374. Error handling for filter expressions.
Errors in filter expressions are now reported. The UI needs some work
but even the current code is helpful when debugging filter
expressions.
mlink_expr:
defines/raises ExpressionError(error string template,
context=dict())
raises ExpressionError when it detects errors when popping arguments
off stack
raises ExpressionError when more than one element left on the stack
before returning
also ruff fix to group boolean expression with parens
back_anydbm.py, rdbms_common.py:
catches ExpressionError, augments context with class and
attribute being searched. raises the exception
for both link and multilink relations
client.py
catches ExpressionError returning a basic error page. The page is a
dead end. There are no links or anything for the user to move
forward. The user has to go back, possibly refresh the page (because
the submit button may be disalbled) re-enter the query and try
again.
This needs to be improved.
test_liveserver.py
test the error page generated by client.py
db_test_base
unit tests for filter with too few arguments, too many arguments,
check all repr and str formats.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Mon, 30 Dec 2024 20:22:55 -0500 |
| parents | 9bbc1d951677 |
| children | fed0f839c260 |
| rev | line source |
|---|---|
| 1049 | 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 | |
|
4570
6e3e4f24c753
Remove keyword expansions from CVS. All regression tests passed afterwards.
Eric S. Raymond <esr@thyrsus.com>
parents:
3200
diff
changeset
|
21 ''' |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1233
diff
changeset
|
22 __docformat__ = 'restructuredtext' |
| 1049 | 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): | |
|
3200
d2b1a946fdf4
change ZTUtils Iterator to always iter() its sequence argument
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
33 self.seq = iter(seq) # force seq to be an iterator |
|
d2b1a946fdf4
change ZTUtils Iterator to always iter() its sequence argument
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
34 self._inner = iterInner |
|
d2b1a946fdf4
change ZTUtils Iterator to always iter() its sequence argument
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
35 self._prep_next = iterInner.prep_next |
| 1049 | 36 |
| 37 def __getattr__(self, name): | |
| 38 try: | |
| 39 inner = getattr(self._inner, 'it_' + name) | |
| 40 except AttributeError: | |
|
5378
35ea9b1efc14
Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents:
4570
diff
changeset
|
41 raise AttributeError(name) |
| 1049 | 42 return inner(self) |
| 43 | |
| 44 def next(self): | |
| 45 if not (hasattr(self, '_next') or self._prep_next(self)): | |
| 46 return 0 | |
| 47 self.index = i = self.nextIndex | |
| 48 self.nextIndex = i+1 | |
| 49 self._advance(self) | |
| 50 return 1 | |
| 51 | |
| 52 def _advance(self, it): | |
| 53 self.item = self._next | |
| 54 del self._next | |
| 55 del self.end | |
| 56 self._advance = self._inner.advance | |
| 57 self.start = 1 | |
| 58 | |
| 59 def number(self): return self.nextIndex | |
| 60 | |
| 61 def even(self): return not self.index % 2 | |
| 62 | |
| 63 def odd(self): return self.index % 2 | |
| 64 | |
| 65 def letter(self, base=ord('a'), radix=26): | |
| 66 index = self.index | |
| 67 s = '' | |
| 68 while 1: | |
| 69 index, off = divmod(index, radix) | |
| 70 s = chr(base + off) + s | |
| 71 if not index: return s | |
| 72 | |
| 73 def Letter(self): | |
| 74 return self.letter(base=ord('A')) | |
| 75 | |
| 76 def Roman(self, rnvalues=( | |
| 77 (1000,'M'),(900,'CM'),(500,'D'),(400,'CD'), | |
| 78 (100,'C'),(90,'XC'),(50,'L'),(40,'XL'), | |
| 79 (10,'X'),(9,'IX'),(5,'V'),(4,'IV'),(1,'I')) ): | |
| 80 n = self.index + 1 | |
| 81 s = '' | |
| 82 for v, r in rnvalues: | |
| 83 rct, n = divmod(n, v) | |
| 84 s = s + r * rct | |
| 85 return s | |
| 86 | |
|
5419
ef6631409171
Python 3 preparation: avoid string.lower.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5396
diff
changeset
|
87 def roman(self, lower=lambda x:x.lower): |
|
7866
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
88 return self.Roman().lower() |
| 1049 | 89 |
| 90 def first(self, name=None): | |
| 91 if self.start: return 1 | |
|
7866
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
92 return self.same_part(name, self._last, self.item) |
| 1049 | 93 |
| 94 def last(self, name=None): | |
| 95 if self.end: return 1 | |
|
7866
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
96 return self.same_part(name, self.item, self._next) |
| 1049 | 97 |
| 98 def same_part(self, name, ob1, ob2): | |
|
7866
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
99 """I have no idea what this does. |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
100 |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
101 It returns True for first()/last() when there are more items |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
102 in the sequence. Called by first() to compare the previous |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
103 item in sequence and the current item. Caled by last() to |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
104 compare the current item and next item in sequence. |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
105 |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
106 Accepts a string version of the name of an attribute as 'name'. |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
107 |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
108 If no attribute name is provided, return True if the two items: |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
109 |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
110 are equal (==) - duplicate strings/integer/same object |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
111 |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
112 else False. |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
113 |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
114 If a non-existent attribute name is provided return False. |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
115 |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
116 If the attribute is present and the named attributes compare |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
117 equal (==) return True else False. |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
118 |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
119 No idea what use case this handles. Maybe this has |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
120 something to do with batching and first/last returning True |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
121 triggers a new group? |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
122 """ |
|
9bbc1d951677
issue2551331 - Fix repeat first/last methods.
John Rouillard <rouilj@ieee.org>
parents:
5419
diff
changeset
|
123 |
| 1049 | 124 if name is None: |
| 125 return ob1 == ob2 | |
| 126 no = [] | |
| 127 return getattr(ob1, name, no) == getattr(ob2, name, no) is not no | |
| 128 | |
| 129 def __iter__(self): | |
| 130 return IterIter(self) | |
| 131 | |
| 132 class InnerBase: | |
| 133 '''Base Inner class for Iterators''' | |
| 134 # Prep sets up ._next and .end | |
| 135 def prep_next(self, it): | |
| 136 it.next = self.no_next | |
| 137 it.end = 1 | |
| 138 return 0 | |
| 139 | |
| 140 # Advance knocks them down | |
| 141 def advance(self, it): | |
| 142 it._last = it.item | |
| 143 it.item = it._next | |
| 144 del it._next | |
| 145 del it.end | |
| 146 it.start = 0 | |
| 147 | |
| 148 def no_next(self, it): | |
| 149 return 0 | |
| 150 | |
| 151 def it_end(self, it): | |
| 152 if hasattr(it, '_next'): | |
| 153 return 0 | |
| 154 return not self.prep_next(it) | |
| 155 | |
| 156 class SeqInner(InnerBase): | |
| 157 '''Inner class for sequence Iterators''' | |
| 158 | |
| 159 def _supports(self, ob): | |
| 160 try: ob[0] | |
|
1233
69bf0d381fd7
Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
161 except (TypeError, AttributeError): return 0 |
| 1049 | 162 except: pass |
| 163 return 1 | |
| 164 | |
| 165 def prep_next(self, it): | |
| 166 i = it.nextIndex | |
| 167 try: | |
| 168 it._next = it.seq[i] | |
| 169 except IndexError: | |
| 170 it._prep_next = self.no_next | |
| 171 it.end = 1 | |
| 172 return 0 | |
| 173 it.end = 0 | |
| 174 return 1 | |
| 175 | |
| 176 def it_length(self, it): | |
| 177 it.length = l = len(it.seq) | |
| 178 return l | |
| 179 | |
| 180 try: | |
| 181 StopIteration=StopIteration | |
| 182 except NameError: | |
| 183 StopIteration="StopIteration" | |
| 184 | |
| 185 class IterInner(InnerBase): | |
| 186 '''Iterator inner class for Python iterators''' | |
| 187 | |
| 188 def _supports(self, ob): | |
| 189 try: | |
| 190 if hasattr(ob, 'next') and (ob is iter(ob)): | |
| 191 return 1 | |
| 192 except: | |
| 193 return 0 | |
| 194 | |
| 195 def prep_next(self, it): | |
| 196 try: | |
|
5396
831787cf6694
Python 3 preparation: update next() usage for iterators.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5378
diff
changeset
|
197 it._next = next(it.seq) |
| 1049 | 198 except StopIteration: |
| 199 it._prep_next = self.no_next | |
| 200 it.end = 1 | |
| 201 return 0 | |
| 202 it.end = 0 | |
| 203 return 1 | |
| 204 | |
| 205 class IterIter: | |
| 206 def __init__(self, it): | |
| 207 self.it = it | |
| 208 self.skip = it.nextIndex > 0 and not it.end | |
|
5396
831787cf6694
Python 3 preparation: update next() usage for iterators.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5378
diff
changeset
|
209 def __next__(self): |
| 1049 | 210 it = self.it |
| 211 if self.skip: | |
| 212 self.skip = 0 | |
| 213 return it.item | |
| 214 if it.next(): | |
| 215 return it.item | |
| 216 raise StopIteration | |
|
5396
831787cf6694
Python 3 preparation: update next() usage for iterators.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5378
diff
changeset
|
217 # Python 2 compatibility: |
|
831787cf6694
Python 3 preparation: update next() usage for iterators.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5378
diff
changeset
|
218 next = __next__ |
| 1049 | 219 |
| 220 seqInner = SeqInner() | |
| 221 iterInner = IterInner() |
