annotate roundup/cgi/PageTemplates/Expressions.py @ 1055:cf72eae57a2c

Fixed instance installation ... moved the htmlbase module into templates and call it <template>_htmlbase.py ... no more try/except in instance __init__! Added :required to form handling. Handle multiple values for single form items with decent error report.
author Richard Jones <richard@users.sourceforge.net>
date Thu, 05 Sep 2002 23:39:14 +0000
parents b9988e118055
children 0f9aa62917bd
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
1 ##############################################################################
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
2 #
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
3 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
4 #
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
5 # This software is subject to the provisions of the Zope Public License,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
6 # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
10 # FOR A PARTICULAR PURPOSE
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
11 #
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
12 ##############################################################################
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
13
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
14 """Page Template Expression Engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
15
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
16 Page Template-specific implementation of TALES, with handlers
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
17 for Python expressions, string literals, and paths.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
18 """
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
19
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
20 __version__='$Revision: 1.1 $'[11:-2]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
21
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
22 import re, sys
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
23 from TALES import Engine, CompilerError, _valid_name, NAME_RE, \
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
24 Undefined, Default, _parse_expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
25 from string import strip, split, join, replace, lstrip
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
26
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
27 _engine = None
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
28 def getEngine():
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
29 global _engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
30 if _engine is None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
31 from PathIterator import Iterator
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
32 _engine = Engine(Iterator)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
33 installHandlers(_engine)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
34 return _engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
35
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
36 def installHandlers(engine):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
37 reg = engine.registerType
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
38 pe = PathExpr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
39 for pt in ('standard', 'path', 'exists', 'nocall'):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
40 reg(pt, pe)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
41 reg('string', StringExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
42 reg('python', PythonExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
43 reg('not', NotExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
44 reg('defer', DeferExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
45
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
46 from PythonExpr import getSecurityManager, PythonExpr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
47 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
48 from zExceptions import Unauthorized
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
49 except ImportError:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
50 Unauthorized = "Unauthorized"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
51 def call_with_ns(f, ns, arg=1):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
52 if arg==2:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
53 return f(None, ns)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
54 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
55 return f(ns)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
56
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
57 class _SecureModuleImporter:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
58 """Simple version of the importer for use with trusted code."""
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
59 __allow_access_to_unprotected_subobjects__ = 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
60 def __getitem__(self, module):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
61 __import__(module)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
62 return sys.modules[module]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
63
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
64 Undefs = (Undefined, AttributeError, KeyError,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
65 TypeError, IndexError, Unauthorized)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
66
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
67 def render(ob, ns):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
68 """
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
69 Calls the object, possibly a document template, or just returns it if
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
70 not callable. (From DT_Util.py)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
71 """
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
72 if hasattr(ob, '__render_with_namespace__'):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
73 ob = call_with_ns(ob.__render_with_namespace__, ns)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
74 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
75 base = ob
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
76 if callable(base):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
77 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
78 if getattr(base, 'isDocTemp', 0):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
79 ob = call_with_ns(ob, ns, 2)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
80 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
81 ob = ob()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
82 except AttributeError, n:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
83 if str(n) != '__call__':
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
84 raise
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
85 return ob
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
86
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
87 class SubPathExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
88 def __init__(self, path):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
89 self._path = path = split(strip(path), '/')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
90 self._base = base = path.pop(0)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
91 if not _valid_name(base):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
92 raise CompilerError, 'Invalid variable name "%s"' % base
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
93 # Parse path
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
94 self._dp = dp = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
95 for i in range(len(path)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
96 e = path[i]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
97 if e[:1] == '?' and _valid_name(e[1:]):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
98 dp.append((i, e[1:]))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
99 dp.reverse()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
100
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
101 def _eval(self, econtext,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
102 list=list, isinstance=isinstance, StringType=type('')):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
103 vars = econtext.vars
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
104 path = self._path
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
105 if self._dp:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
106 path = list(path) # Copy!
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
107 for i, varname in self._dp:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
108 val = vars[varname]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
109 if isinstance(val, StringType):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
110 path[i] = val
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
111 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
112 # If the value isn't a string, assume it's a sequence
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
113 # of path names.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
114 path[i:i+1] = list(val)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
115 __traceback_info__ = base = self._base
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
116 if base == 'CONTEXTS':
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
117 ob = econtext.contexts
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
118 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
119 ob = vars[base]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
120 if isinstance(ob, DeferWrapper):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
121 ob = ob()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
122 if path:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
123 ob = restrictedTraverse(ob, path, getSecurityManager())
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
124 return ob
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
125
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
126 class PathExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
127 def __init__(self, name, expr, engine):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
128 self._s = expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
129 self._name = name
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
130 paths = split(expr, '|')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
131 self._subexprs = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
132 add = self._subexprs.append
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
133 for i in range(len(paths)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
134 path = lstrip(paths[i])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
135 if _parse_expr(path):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
136 # This part is the start of another expression type,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
137 # so glue it back together and compile it.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
138 add(engine.compile(lstrip(join(paths[i:], '|'))))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
139 break
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
140 add(SubPathExpr(path)._eval)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
141
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
142 def _exists(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
143 for expr in self._subexprs:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
144 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
145 expr(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
146 except Undefs:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
147 pass
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
148 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
149 return 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
150 return 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
151
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
152 def _eval(self, econtext,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
153 isinstance=isinstance, StringType=type(''), render=render):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
154 for expr in self._subexprs[:-1]:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
155 # Try all but the last subexpression, skipping undefined ones.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
156 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
157 ob = expr(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
158 except Undefs:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
159 pass
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
160 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
161 break
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
162 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
163 # On the last subexpression allow exceptions through.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
164 ob = self._subexprs[-1](econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
165
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
166 if self._name == 'nocall' or isinstance(ob, StringType):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
167 return ob
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
168 # Return the rendered object
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
169 return render(ob, econtext.vars)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
170
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
171 def __call__(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
172 if self._name == 'exists':
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
173 return self._exists(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
174 return self._eval(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
175
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
176 def __str__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
177 return '%s expression %s' % (self._name, `self._s`)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
178
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
179 def __repr__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
180 return '%s:%s' % (self._name, `self._s`)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
181
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
182
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
183 _interp = re.compile(r'\$(%(n)s)|\${(%(n)s(?:/%(n)s)*)}' % {'n': NAME_RE})
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
184
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
185 class StringExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
186 def __init__(self, name, expr, engine):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
187 self._s = expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
188 if '%' in expr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
189 expr = replace(expr, '%', '%%')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
190 self._vars = vars = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
191 if '$' in expr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
192 parts = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
193 for exp in split(expr, '$$'):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
194 if parts: parts.append('$')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
195 m = _interp.search(exp)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
196 while m is not None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
197 parts.append(exp[:m.start()])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
198 parts.append('%s')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
199 vars.append(PathExpr('path', m.group(1) or m.group(2),
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
200 engine))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
201 exp = exp[m.end():]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
202 m = _interp.search(exp)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
203 if '$' in exp:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
204 raise CompilerError, (
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
205 '$ must be doubled or followed by a simple path')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
206 parts.append(exp)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
207 expr = join(parts, '')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
208 self._expr = expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
209
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
210 def __call__(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
211 vvals = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
212 for var in self._vars:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
213 v = var(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
214 if isinstance(v, Exception):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
215 raise v
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
216 vvals.append(v)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
217 return self._expr % tuple(vvals)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
218
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
219 def __str__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
220 return 'string expression %s' % `self._s`
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
221
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
222 def __repr__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
223 return 'string:%s' % `self._s`
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
224
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
225 class NotExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
226 def __init__(self, name, expr, compiler):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
227 self._s = expr = lstrip(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
228 self._c = compiler.compile(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
229
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
230 def __call__(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
231 return not econtext.evaluateBoolean(self._c)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
232
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
233 def __repr__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
234 return 'not:%s' % `self._s`
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
235
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
236 class DeferWrapper:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
237 def __init__(self, expr, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
238 self._expr = expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
239 self._econtext = econtext
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
240
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
241 def __str__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
242 return str(self())
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
243
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
244 def __call__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
245 return self._expr(self._econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
246
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
247 class DeferExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
248 def __init__(self, name, expr, compiler):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
249 self._s = expr = lstrip(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
250 self._c = compiler.compile(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
251
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
252 def __call__(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
253 return DeferWrapper(self._c, econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
254
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
255 def __repr__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
256 return 'defer:%s' % `self._s`
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
257
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
258
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
259 def restrictedTraverse(self, path, securityManager,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
260 get=getattr, has=hasattr, N=None, M=[],
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
261 TupleType=type(()) ):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
262
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
263 REQUEST = {'path': path}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
264 REQUEST['TraversalRequestNameStack'] = path = path[:] # Copy!
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
265 if not path[0]:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
266 # If the path starts with an empty string, go to the root first.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
267 self = self.getPhysicalRoot()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
268 path.pop(0)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
269
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
270 path.reverse()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
271 object = self
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
272 #print 'TRAVERSE', (object, path)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
273 while path:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
274 __traceback_info__ = REQUEST
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
275 name = path.pop()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
276
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
277 if isinstance(name, TupleType):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
278 object = apply(object, name)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
279 continue
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
280
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
281 if name[0] == '_':
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
282 # Never allowed in a URL.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
283 raise AttributeError, name
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
284
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
285 # Try an attribute.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
286 o = get(object, name, M)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
287 # print '...', (object, name, M, o)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
288 if o is M:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
289 # Try an item.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
290 # print '... try an item'
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
291 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
292 # XXX maybe in Python 2.2 we can just check whether
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
293 # the object has the attribute "__getitem__"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
294 # instead of blindly catching exceptions.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
295 o = object[name]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
296 except AttributeError, exc:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
297 if str(exc).find('__getitem__') >= 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
298 # The object does not support the item interface.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
299 # Try to re-raise the original attribute error.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
300 # XXX I think this only happens with
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
301 # ExtensionClass instances.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
302 get(object, name)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
303 raise
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
304 except TypeError, exc:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
305 if str(exc).find('unsubscriptable') >= 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
306 # The object does not support the item interface.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
307 # Try to re-raise the original attribute error.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
308 # XXX This is sooooo ugly.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
309 get(object, name)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
310 raise
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
311 #print '... object is now', `o`
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
312 object = o
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
313
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
314 return object
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
315

Roundup Issue Tracker: http://roundup-tracker.org/