annotate roundup/cgi/PageTemplates/Expressions.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 33b25e51e127
children
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.
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
4 #
1049
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
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
11 #
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
12 ##############################################################################
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
13 # Modified for Roundup:
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
14 #
2663
5f9e00836006 update comment
Richard Jones <richard@users.sourceforge.net>
parents: 2351
diff changeset
15 # 1. removed all Zope-specific code (doesn't even try to import that stuff now)
5f9e00836006 update comment
Richard Jones <richard@users.sourceforge.net>
parents: 2351
diff changeset
16 # 2. removed all Acquisition
5f9e00836006 update comment
Richard Jones <richard@users.sourceforge.net>
parents: 2351
diff changeset
17 # 3. removed blocking of leading-underscore URL components
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
18
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
19 """Page Template Expression Engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
20
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
21 Page Template-specific implementation of TALES, with handlers
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
22 for Python expressions, string literals, and paths.
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
23 """
1071
c08b3820edd1 Adhering to ZPL
Richard Jones <richard@users.sourceforge.net>
parents: 1065
diff changeset
24
5812
33b25e51e127 More fixes for: DeprecationWarning: Using or importing the ABCs from
John Rouillard <rouilj@ieee.org>
parents: 5406
diff changeset
25 import re, sys
33b25e51e127 More fixes for: DeprecationWarning: Using or importing the ABCs from
John Rouillard <rouilj@ieee.org>
parents: 5406
diff changeset
26 try:
33b25e51e127 More fixes for: DeprecationWarning: Using or importing the ABCs from
John Rouillard <rouilj@ieee.org>
parents: 5406
diff changeset
27 from collections.abc import Callable
33b25e51e127 More fixes for: DeprecationWarning: Using or importing the ABCs from
John Rouillard <rouilj@ieee.org>
parents: 5406
diff changeset
28 except ImportError:
33b25e51e127 More fixes for: DeprecationWarning: Using or importing the ABCs from
John Rouillard <rouilj@ieee.org>
parents: 5406
diff changeset
29 from collections import Callable
33b25e51e127 More fixes for: DeprecationWarning: Using or importing the ABCs from
John Rouillard <rouilj@ieee.org>
parents: 5406
diff changeset
30
5388
d26921b851c3 Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5378
diff changeset
31 from .TALES import Engine, CompilerError, _valid_name, NAME_RE, \
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
32 Undefined, Default, _parse_expr
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
33
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
34
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
35 _engine = None
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
36 def getEngine():
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
37 global _engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
38 if _engine is None:
5388
d26921b851c3 Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5378
diff changeset
39 from .PathIterator import Iterator
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
40 _engine = Engine(Iterator)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
41 installHandlers(_engine)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
42 return _engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
43
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
44 def installHandlers(engine):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
45 reg = engine.registerType
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
46 pe = PathExpr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
47 for pt in ('standard', 'path', 'exists', 'nocall'):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
48 reg(pt, pe)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
49 reg('string', StringExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
50 reg('python', PythonExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
51 reg('not', NotExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
52 reg('defer', DeferExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
53
5388
d26921b851c3 Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5378
diff changeset
54 from .PythonExpr import getSecurityManager, PythonExpr
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
55 guarded_getattr = getattr
1049
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:
5265
63868084b8bb Python 2 and 3 support. Convert Exception to BaseException. TAL and
John Rouillard <rouilj@ieee.org>
parents: 5248
diff changeset
59 class Unauthorized(BaseException):
4238
445e1bc8b1df remove use of string exception
Richard Jones <richard@users.sourceforge.net>
parents: 2663
diff changeset
60 pass
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
61
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
62 def acquisition_security_filter(orig, inst, name, v, real_validate):
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
63 if real_validate(orig, inst, name, v):
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
64 return 1
5378
35ea9b1efc14 Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5377
diff changeset
65 raise Unauthorized(name)
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
66
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
67 def call_with_ns(f, ns, arg=1):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
68 if arg==2:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
69 return f(None, ns)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
70 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
71 return f(ns)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
72
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
73 class _SecureModuleImporter:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
74 """Simple version of the importer for use with trusted code."""
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
75 __allow_access_to_unprotected_subobjects__ = 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
76 def __getitem__(self, module):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
77 __import__(module)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
78 return sys.modules[module]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
79
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
80 SecureModuleImporter = _SecureModuleImporter()
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
81
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
82 Undefs = (Undefined, AttributeError, KeyError,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
83 TypeError, IndexError, Unauthorized)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
84
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
85 def render(ob, ns):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
86 """
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
87 Calls the object, possibly a document template, or just returns it if
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
88 not callable. (From DT_Util.py)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
89 """
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
90 if hasattr(ob, '__render_with_namespace__'):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
91 ob = call_with_ns(ob.__render_with_namespace__, ns)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
92 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
93 base = ob
5812
33b25e51e127 More fixes for: DeprecationWarning: Using or importing the ABCs from
John Rouillard <rouilj@ieee.org>
parents: 5406
diff changeset
94 if isinstance(base, Callable):
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
95 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
96 if getattr(base, 'isDocTemp', 0):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
97 ob = call_with_ns(ob, ns, 2)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
98 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
99 ob = ob()
5248
198b6e810c67 Use Python-3-compatible 'as' syntax for except statements
Eric S. Raymond <esr@thyrsus.com>
parents: 4570
diff changeset
100 except AttributeError as n:
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
101 if str(n) != '__call__':
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
102 raise
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
103 return ob
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
104
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
105 class SubPathExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
106 def __init__(self, path):
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
107 self._path = path = path.strip().split('/')
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
108 self._base = base = path.pop(0)
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
109 if base and not _valid_name(base):
5378
35ea9b1efc14 Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5377
diff changeset
110 raise CompilerError('Invalid variable name "%s"' % base)
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
111 # Parse path
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
112 self._dp = dp = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
113 for i in range(len(path)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
114 e = path[i]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
115 if e[:1] == '?' and _valid_name(e[1:]):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
116 dp.append((i, e[1:]))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
117 dp.reverse()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
118
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
119 def _eval(self, econtext,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
120 list=list, isinstance=isinstance, StringType=type('')):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
121 vars = econtext.vars
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
122 path = self._path
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
123 if self._dp:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
124 path = list(path) # Copy!
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
125 for i, varname in self._dp:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
126 val = vars[varname]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
127 if isinstance(val, StringType):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
128 path[i] = val
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
129 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
130 # If the value isn't a string, assume it's a sequence
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
131 # of path names.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
132 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
133 base = self._base
1136
7e193bbda38e added generic item editing
Richard Jones <richard@users.sourceforge.net>
parents: 1101
diff changeset
134 __traceback_info__ = 'path expression "%s"'%('/'.join(self._path))
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
135 if base == 'CONTEXTS' or not base:
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
136 ob = econtext.contexts
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
137 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
138 ob = vars[base]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
139 if isinstance(ob, DeferWrapper):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
140 ob = ob()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
141 if path:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
142 ob = restrictedTraverse(ob, path, getSecurityManager())
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
143 return ob
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
144
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
145 class PathExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
146 def __init__(self, name, expr, engine):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
147 self._s = expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
148 self._name = name
1233
69bf0d381fd7 Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents: 1181
diff changeset
149 self._hybrid = 0
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
150 paths = expr.split('|')
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
151 self._subexprs = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
152 add = self._subexprs.append
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
153 for i in range(len(paths)):
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
154 path = paths[i].lstrip()
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
155 if _parse_expr(path):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
156 # This part is the start of another expression type,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
157 # so glue it back together and compile it.
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
158 add(engine.compile(('|'.join(paths[i:]).lstrip())))
1233
69bf0d381fd7 Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents: 1181
diff changeset
159 self._hybrid = 1
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
160 break
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
161 add(SubPathExpr(path)._eval)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
162
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
163 def _exists(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
164 for expr in self._subexprs:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
165 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
166 expr(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
167 except Undefs:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
168 pass
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
169 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
170 return 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
171 return 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
172
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
173 def _eval(self, econtext,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
174 isinstance=isinstance, StringType=type(''), render=render):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
175 for expr in self._subexprs[:-1]:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
176 # Try all but the last subexpression, skipping undefined ones.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
177 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
178 ob = expr(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
179 except Undefs:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
180 pass
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
181 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
182 break
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
183 else:
1233
69bf0d381fd7 Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents: 1181
diff changeset
184 # On the last subexpression allow exceptions through, and
69bf0d381fd7 Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents: 1181
diff changeset
185 # don't autocall if the expression was not a subpath.
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
186 ob = self._subexprs[-1](econtext)
1233
69bf0d381fd7 Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents: 1181
diff changeset
187 if self._hybrid:
69bf0d381fd7 Zope Collector fixes.
Richard Jones <richard@users.sourceforge.net>
parents: 1181
diff changeset
188 return ob
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
189
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
190 if self._name == 'nocall' or isinstance(ob, StringType):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
191 return ob
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
192 # Return the rendered object
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
193 return render(ob, econtext.vars)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
194
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
195 def __call__(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
196 if self._name == 'exists':
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
197 return self._exists(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
198 return self._eval(econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
199
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
200 def __str__(self):
5377
12fe83f90f0d Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5265
diff changeset
201 return '%s expression %s' % (self._name, repr(self._s))
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
202
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
203 def __repr__(self):
5377
12fe83f90f0d Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5265
diff changeset
204 return '%s:%s' % (self._name, repr(self._s))
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
205
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
206
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
207 _interp = re.compile(r'\$(%(n)s)|\${(%(n)s(?:/[^}]*)*)}' % {'n': NAME_RE})
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
208
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
209 class StringExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
210 def __init__(self, name, expr, engine):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
211 self._s = expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
212 if '%' in expr:
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
213 expr = expr.replace('%', '%%')
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
214 self._vars = vars = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
215 if '$' in expr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
216 parts = []
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
217 for exp in expr.split('$$'):
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
218 if parts: parts.append('$')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
219 m = _interp.search(exp)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
220 while m is not None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
221 parts.append(exp[:m.start()])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
222 parts.append('%s')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
223 vars.append(PathExpr('path', m.group(1) or m.group(2),
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
224 engine))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
225 exp = exp[m.end():]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
226 m = _interp.search(exp)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
227 if '$' in exp:
5378
35ea9b1efc14 Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5377
diff changeset
228 raise CompilerError(
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
229 '$ must be doubled or followed by a simple path')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
230 parts.append(exp)
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
231 expr = ''.join(parts)
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
232 self._expr = expr
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
233
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
234 def __call__(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
235 vvals = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
236 for var in self._vars:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
237 v = var(econtext)
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
238 # I hope this isn't in use anymore.
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
239 ## if isinstance(v, Exception):
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
240 ## raise v
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
241 vvals.append(v)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
242 return self._expr % tuple(vvals)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
243
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
244 def __str__(self):
5377
12fe83f90f0d Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5265
diff changeset
245 return 'string expression %s' % repr(self._s)
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
246
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
247 def __repr__(self):
5377
12fe83f90f0d Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5265
diff changeset
248 return 'string:%s' % repr(self._s)
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
249
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
250 class NotExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
251 def __init__(self, name, expr, compiler):
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
252 self._s = expr = expr.lstrip()
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
253 self._c = compiler.compile(expr)
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
254
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
255 def __call__(self, econtext):
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
256 # We use the (not x) and 1 or 0 formulation to avoid changing
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
257 # the representation of the result in Python 2.3, where the
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
258 # result of "not" becomes an instance of bool.
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
259 return (not econtext.evaluateBoolean(self._c)) and 1 or 0
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
260
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
261 def __repr__(self):
5377
12fe83f90f0d Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5265
diff changeset
262 return 'not:%s' % repr(self._s)
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
263
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
264 class DeferWrapper:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
265 def __init__(self, expr, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
266 self._expr = expr
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
267 self._econtext = econtext
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
268
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
269 def __str__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
270 return str(self())
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
271
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
272 def __call__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
273 return self._expr(self._econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
274
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
275 class DeferExpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
276 def __init__(self, name, expr, compiler):
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
277 self._s = expr = expr.lstrip()
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
278 self._c = compiler.compile(expr)
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
279
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
280 def __call__(self, econtext):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
281 return DeferWrapper(self._c, econtext)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
282
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
283 def __repr__(self):
5377
12fe83f90f0d Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5265
diff changeset
284 return 'defer:%s' % repr(self._s)
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
285
2351
97fae0466d97 more ZPT porting tweaks
Richard Jones <richard@users.sourceforge.net>
parents: 2349
diff changeset
286 class TraversalError:
97fae0466d97 more ZPT porting tweaks
Richard Jones <richard@users.sourceforge.net>
parents: 2349
diff changeset
287 def __init__(self, path, name):
97fae0466d97 more ZPT porting tweaks
Richard Jones <richard@users.sourceforge.net>
parents: 2349
diff changeset
288 self.path = path
97fae0466d97 more ZPT porting tweaks
Richard Jones <richard@users.sourceforge.net>
parents: 2349
diff changeset
289 self.name = name
97fae0466d97 more ZPT porting tweaks
Richard Jones <richard@users.sourceforge.net>
parents: 2349
diff changeset
290
97fae0466d97 more ZPT porting tweaks
Richard Jones <richard@users.sourceforge.net>
parents: 2349
diff changeset
291
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
292
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
293 def restrictedTraverse(object, path, securityManager,
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
294 get=getattr, has=hasattr, N=None, M=[],
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
295 TupleType=type(()) ):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
296
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
297 REQUEST = {'path': path}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
298 REQUEST['TraversalRequestNameStack'] = path = path[:] # Copy!
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
299 path.reverse()
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
300 validate = securityManager.validate
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
301 __traceback_info__ = REQUEST
2351
97fae0466d97 more ZPT porting tweaks
Richard Jones <richard@users.sourceforge.net>
parents: 2349
diff changeset
302 done = []
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
303 while path:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
304 name = path.pop()
2351
97fae0466d97 more ZPT porting tweaks
Richard Jones <richard@users.sourceforge.net>
parents: 2349
diff changeset
305 __traceback_info__ = TraversalError(done, name)
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
306
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
307 if isinstance(name, TupleType):
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
308 object = object(*name)
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
309 continue
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
310
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
311 if not name:
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
312 # Skip directly to item access
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
313 o = object[name]
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
314 # Check access to the item.
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
315 if not validate(object, object, name, o):
5378
35ea9b1efc14 Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5377
diff changeset
316 raise Unauthorized(name)
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
317 object = o
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
318 continue
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
319
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
320 # Try an attribute.
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
321 o = guarded_getattr(object, name, M)
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
322 if o is M:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
323 # Try an item.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
324 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
325 # XXX maybe in Python 2.2 we can just check whether
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
326 # the object has the attribute "__getitem__"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
327 # instead of blindly catching exceptions.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
328 o = object[name]
5248
198b6e810c67 Use Python-3-compatible 'as' syntax for except statements
Eric S. Raymond <esr@thyrsus.com>
parents: 4570
diff changeset
329 except AttributeError as exc:
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
330 if str(exc).find('__getitem__') >= 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
331 # The object does not support the item interface.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
332 # Try to re-raise the original attribute error.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
333 # XXX I think this only happens with
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
334 # ExtensionClass instances.
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
335 guarded_getattr(object, name)
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
336 raise
5248
198b6e810c67 Use Python-3-compatible 'as' syntax for except statements
Eric S. Raymond <esr@thyrsus.com>
parents: 4570
diff changeset
337 except TypeError as exc:
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
338 if str(exc).find('unsubscriptable') >= 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
339 # The object does not support the item interface.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
340 # Try to re-raise the original attribute error.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
341 # XXX This is sooooo ugly.
2349
b43efe461b3e update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents: 2005
diff changeset
342 guarded_getattr(object, name)
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
343 raise
2351
97fae0466d97 more ZPT porting tweaks
Richard Jones <richard@users.sourceforge.net>
parents: 2349
diff changeset
344 done.append((name, o))
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
345 object = o
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
346
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
347 return object

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