annotate roundup/cgi/PageTemplates/Expressions.py @ 2119:cc4667ef3f12

Added the ability to toggle where error messages go. They either go to the user (default, for backwards compatibility), the dispatcher, or both. These are able to be toggled via settings in config.py. Please refer to upgrading.txt for more details. (And Richard, let me know if I've done anything wrong with this checkin. :))
author Eddie Parker <eparker@users.sourceforge.net>
date Thu, 25 Mar 2004 19:27:15 +0000
parents fc52d57c6c3e
children b43efe461b3e
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.
1071
c08b3820edd1 Adhering to ZPL
Richard Jones <richard@users.sourceforge.net>
parents: 1065
diff changeset
18
c08b3820edd1 Adhering to ZPL
Richard Jones <richard@users.sourceforge.net>
parents: 1065
diff changeset
19
c08b3820edd1 Adhering to ZPL
Richard Jones <richard@users.sourceforge.net>
parents: 1065
diff changeset
20 Modified for Roundup 0.5 release:
c08b3820edd1 Adhering to ZPL
Richard Jones <richard@users.sourceforge.net>
parents: 1065
diff changeset
21
c08b3820edd1 Adhering to ZPL
Richard Jones <richard@users.sourceforge.net>
parents: 1065
diff changeset
22 - Removed all Zope-specific code (doesn't even try to import that stuff now)
c08b3820edd1 Adhering to ZPL
Richard Jones <richard@users.sourceforge.net>
parents: 1065
diff changeset
23 - Removed all Acquisition
c08b3820edd1 Adhering to ZPL
Richard Jones <richard@users.sourceforge.net>
parents: 1065
diff changeset
24 - Made traceback info more informative
c08b3820edd1 Adhering to ZPL
Richard Jones <richard@users.sourceforge.net>
parents: 1065
diff changeset
25
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
26 """
2005
fc52d57c6c3e documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents: 1233
diff changeset
27 __docformat__ = 'restructuredtext'
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
28
2005
fc52d57c6c3e documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents: 1233
diff changeset
29 __version__='$Revision: 1.9 $'[11:-2]
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
30
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
31 import re, sys
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
32 from TALES import Engine, CompilerError, _valid_name, NAME_RE, \
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
33 Undefined, Default, _parse_expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
34 from string import strip, split, join, replace, lstrip
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
35
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
36 _engine = None
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
37 def getEngine():
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
38 global _engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
39 if _engine is None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
40 from PathIterator import Iterator
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
41 _engine = Engine(Iterator)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
42 installHandlers(_engine)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
43 return _engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
44
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
45 def installHandlers(engine):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
46 reg = engine.registerType
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
47 pe = PathExpr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
48 for pt in ('standard', 'path', 'exists', 'nocall'):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
49 reg(pt, pe)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
50 reg('string', StringExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
51 reg('python', PythonExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
52 reg('not', NotExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
53 reg('defer', DeferExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
54
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
55 from PythonExpr import getSecurityManager, PythonExpr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
56 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
57 from zExceptions import Unauthorized
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
58 except ImportError:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
59 Unauthorized = "Unauthorized"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
60 def call_with_ns(f, ns, arg=1):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
61 if arg==2:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
62 return f(None, ns)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
63 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
64 return f(ns)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
65
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
66 class _SecureModuleImporter:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
67 """Simple version of the importer for use with trusted code."""
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
68 __allow_access_to_unprotected_subobjects__ = 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
69 def __getitem__(self, module):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
70 __import__(module)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
71 return sys.modules[module]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
72
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
73 Undefs = (Undefined, AttributeError, KeyError,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
74 TypeError, IndexError, Unauthorized)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
75
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
76 def render(ob, ns):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
77 """
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
78 Calls the object, possibly a document template, or just returns it if
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
79 not callable. (From DT_Util.py)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
80 """
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
81 if hasattr(ob, '__render_with_namespace__'):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
82 ob = call_with_ns(ob.__render_with_namespace__, ns)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
83 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
84 base = ob
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
85 if callable(base):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
86 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
87 if getattr(base, 'isDocTemp', 0):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
88 ob = call_with_ns(ob, ns, 2)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
89 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
90 ob = ob()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
91 except AttributeError, n:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
92 if str(n) != '__call__':
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
93 raise
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
94 return ob
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
95
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
96 class SubPathExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
97 def __init__(self, path):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
98 self._path = path = split(strip(path), '/')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
99 self._base = base = path.pop(0)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
100 if not _valid_name(base):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
101 raise CompilerError, 'Invalid variable name "%s"' % base
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
102 # Parse path
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
103 self._dp = dp = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
104 for i in range(len(path)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
105 e = path[i]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
106 if e[:1] == '?' and _valid_name(e[1:]):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
107 dp.append((i, e[1:]))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
108 dp.reverse()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
109
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
110 def _eval(self, econtext,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
111 list=list, isinstance=isinstance, StringType=type('')):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
112 vars = econtext.vars
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
113 path = self._path
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
114 if self._dp:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
115 path = list(path) # Copy!
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
116 for i, varname in self._dp:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
117 val = vars[varname]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
118 if isinstance(val, StringType):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
119 path[i] = val
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
120 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
121 # If the value isn't a string, assume it's a sequence
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
122 # of path names.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
123 path[i:i+1] = list(val)
1065
0f9aa62917bd much nicer error messages when there's a templating error
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
124 base = self._base
1136
7e193bbda38e added generic item editing
Richard Jones <richard@users.sourceforge.net>
parents: 1101
diff changeset
125 __traceback_info__ = 'path expression "%s"'%('/'.join(self._path))
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
126 if base == 'CONTEXTS':
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
127 ob = econtext.contexts
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
128 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
129 ob = vars[base]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
130 if isinstance(ob, DeferWrapper):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
131 ob = ob()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
132 if path:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
133 ob = restrictedTraverse(ob, path, getSecurityManager())
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
134 return ob
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
135
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
136 class PathExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
137 def __init__(self, name, expr, engine):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
138 self._s = expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
139 self._name = name
1233
69bf0d381fd7 Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents: 1181
diff changeset
140 self._hybrid = 0
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
141 paths = split(expr, '|')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
142 self._subexprs = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
143 add = self._subexprs.append
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
144 for i in range(len(paths)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
145 path = lstrip(paths[i])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
146 if _parse_expr(path):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
147 # This part is the start of another expression type,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
148 # so glue it back together and compile it.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
149 add(engine.compile(lstrip(join(paths[i:], '|'))))
1233
69bf0d381fd7 Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents: 1181
diff changeset
150 self._hybrid = 1
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
151 break
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
152 add(SubPathExpr(path)._eval)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
153
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
154 def _exists(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
155 for expr in self._subexprs:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
156 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
157 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 return 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
162 return 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
163
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
164 def _eval(self, econtext,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
165 isinstance=isinstance, StringType=type(''), render=render):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
166 for expr in self._subexprs[:-1]:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
167 # Try all but the last subexpression, skipping undefined ones.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
168 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
169 ob = expr(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
170 except Undefs:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
171 pass
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
172 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
173 break
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
174 else:
1233
69bf0d381fd7 Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents: 1181
diff changeset
175 # On the last subexpression allow exceptions through, and
69bf0d381fd7 Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents: 1181
diff changeset
176 # don't autocall if the expression was not a subpath.
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
177 ob = self._subexprs[-1](econtext)
1233
69bf0d381fd7 Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents: 1181
diff changeset
178 if self._hybrid:
69bf0d381fd7 Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents: 1181
diff changeset
179 return ob
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
180
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
181 if self._name == 'nocall' or isinstance(ob, StringType):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
182 return ob
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
183 # Return the rendered object
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
184 return render(ob, econtext.vars)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
185
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
186 def __call__(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
187 if self._name == 'exists':
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
188 return self._exists(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
189 return self._eval(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
190
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
191 def __str__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
192 return '%s expression %s' % (self._name, `self._s`)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
193
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
194 def __repr__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
195 return '%s:%s' % (self._name, `self._s`)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
196
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
197
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
198 _interp = re.compile(r'\$(%(n)s)|\${(%(n)s(?:/%(n)s)*)}' % {'n': NAME_RE})
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
199
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
200 class StringExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
201 def __init__(self, name, expr, engine):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
202 self._s = expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
203 if '%' in expr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
204 expr = replace(expr, '%', '%%')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
205 self._vars = vars = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
206 if '$' in expr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
207 parts = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
208 for exp in split(expr, '$$'):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
209 if parts: parts.append('$')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
210 m = _interp.search(exp)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
211 while m is not None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
212 parts.append(exp[:m.start()])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
213 parts.append('%s')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
214 vars.append(PathExpr('path', m.group(1) or m.group(2),
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
215 engine))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
216 exp = exp[m.end():]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
217 m = _interp.search(exp)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
218 if '$' in exp:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
219 raise CompilerError, (
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
220 '$ must be doubled or followed by a simple path')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
221 parts.append(exp)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
222 expr = join(parts, '')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
223 self._expr = expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
224
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
225 def __call__(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
226 vvals = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
227 for var in self._vars:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
228 v = var(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
229 if isinstance(v, Exception):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
230 raise v
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
231 vvals.append(v)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
232 return self._expr % tuple(vvals)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
233
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
234 def __str__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
235 return 'string expression %s' % `self._s`
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
236
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
237 def __repr__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
238 return 'string:%s' % `self._s`
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
239
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
240 class NotExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
241 def __init__(self, name, expr, compiler):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
242 self._s = expr = lstrip(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
243 self._c = compiler.compile(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
244
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
245 def __call__(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
246 return not econtext.evaluateBoolean(self._c)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
247
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
248 def __repr__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
249 return 'not:%s' % `self._s`
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
250
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
251 class DeferWrapper:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
252 def __init__(self, expr, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
253 self._expr = expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
254 self._econtext = econtext
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
255
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
256 def __str__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
257 return str(self())
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
258
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
259 def __call__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
260 return self._expr(self._econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
261
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
262 class DeferExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
263 def __init__(self, name, expr, compiler):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
264 self._s = expr = lstrip(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
265 self._c = compiler.compile(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
266
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
267 def __call__(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
268 return DeferWrapper(self._c, econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
269
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
270 def __repr__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
271 return 'defer:%s' % `self._s`
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
272
1136
7e193bbda38e added generic item editing
Richard Jones <richard@users.sourceforge.net>
parents: 1101
diff changeset
273 class TraversalError:
7e193bbda38e added generic item editing
Richard Jones <richard@users.sourceforge.net>
parents: 1101
diff changeset
274 def __init__(self, path, name):
7e193bbda38e added generic item editing
Richard Jones <richard@users.sourceforge.net>
parents: 1101
diff changeset
275 self.path = path
7e193bbda38e added generic item editing
Richard Jones <richard@users.sourceforge.net>
parents: 1101
diff changeset
276 self.name = name
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
277
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
278 def restrictedTraverse(self, path, securityManager,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
279 get=getattr, has=hasattr, N=None, M=[],
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
280 TupleType=type(()) ):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
281
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
282 REQUEST = {'path': path}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
283 REQUEST['TraversalRequestNameStack'] = path = path[:] # Copy!
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
284 if not path[0]:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
285 # If the path starts with an empty string, go to the root first.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
286 self = self.getPhysicalRoot()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
287 path.pop(0)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
288
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
289 path.reverse()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
290 object = self
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
291 #print 'TRAVERSE', (object, path)
1101
1ce96bf6482f better traversal error info
Richard Jones <richard@users.sourceforge.net>
parents: 1079
diff changeset
292 done = []
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
293 while path:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
294 name = path.pop()
1136
7e193bbda38e added generic item editing
Richard Jones <richard@users.sourceforge.net>
parents: 1101
diff changeset
295 __traceback_info__ = TraversalError(done, name)
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
296
1181
49aebf5a8691 some speedups, some fixes to the benchmarking
Richard Jones <richard@users.sourceforge.net>
parents: 1136
diff changeset
297 # if isinstance(name, TupleType):
49aebf5a8691 some speedups, some fixes to the benchmarking
Richard Jones <richard@users.sourceforge.net>
parents: 1136
diff changeset
298 # object = apply(object, name)
49aebf5a8691 some speedups, some fixes to the benchmarking
Richard Jones <richard@users.sourceforge.net>
parents: 1136
diff changeset
299 # continue
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
300
1079
04b44df7af1d removed some property name clashes
Richard Jones <richard@users.sourceforge.net>
parents: 1071
diff changeset
301 # if name[0] == '_':
04b44df7af1d removed some property name clashes
Richard Jones <richard@users.sourceforge.net>
parents: 1071
diff changeset
302 # # Never allowed in a URL.
04b44df7af1d removed some property name clashes
Richard Jones <richard@users.sourceforge.net>
parents: 1071
diff changeset
303 # raise AttributeError, name
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
304
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
305 # Try an attribute.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
306 o = get(object, name, M)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
307 # print '...', (object, name, M, o)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
308 if o is M:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
309 # Try an item.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
310 # print '... try an item'
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
311 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
312 # XXX maybe in Python 2.2 we can just check whether
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
313 # the object has the attribute "__getitem__"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
314 # instead of blindly catching exceptions.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
315 o = object[name]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
316 except AttributeError, exc:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
317 if str(exc).find('__getitem__') >= 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
318 # The object does not support the item interface.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
319 # Try to re-raise the original attribute error.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
320 # XXX I think this only happens with
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
321 # ExtensionClass instances.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
322 get(object, name)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
323 raise
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
324 except TypeError, exc:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
325 if str(exc).find('unsubscriptable') >= 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
326 # The object does not support the item interface.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
327 # Try to re-raise the original attribute error.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
328 # XXX This is sooooo ugly.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
329 get(object, name)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
330 raise
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
331 #print '... object is now', `o`
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
332 object = o
1136
7e193bbda38e added generic item editing
Richard Jones <richard@users.sourceforge.net>
parents: 1101
diff changeset
333 done.append((name, o))
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
334
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
335 return object
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
336

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