Mercurial > p > roundup > code
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 |
| rev | line source |
|---|---|
| 1049 | 1 ############################################################################## |
| 2 # | |
| 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 | 5 # This software is subject to the provisions of the Zope Public License, |
| 6 # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. | |
| 7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | |
| 8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | |
| 10 # FOR A PARTICULAR PURPOSE | |
|
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 | 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 | 18 |
| 19 """Page Template Expression Engine | |
| 20 | |
| 21 Page Template-specific implementation of TALES, with handlers | |
| 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 | 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 | 34 |
| 35 _engine = None | |
| 36 def getEngine(): | |
| 37 global _engine | |
| 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 | 40 _engine = Engine(Iterator) |
| 41 installHandlers(_engine) | |
| 42 return _engine | |
| 43 | |
| 44 def installHandlers(engine): | |
| 45 reg = engine.registerType | |
| 46 pe = PathExpr | |
| 47 for pt in ('standard', 'path', 'exists', 'nocall'): | |
| 48 reg(pt, pe) | |
| 49 reg('string', StringExpr) | |
| 50 reg('python', PythonExpr) | |
| 51 reg('not', NotExpr) | |
| 52 reg('defer', DeferExpr) | |
| 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 | 56 try: |
| 57 from zExceptions import Unauthorized | |
| 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 | 67 def call_with_ns(f, ns, arg=1): |
| 68 if arg==2: | |
| 69 return f(None, ns) | |
| 70 else: | |
| 71 return f(ns) | |
| 72 | |
| 73 class _SecureModuleImporter: | |
| 74 """Simple version of the importer for use with trusted code.""" | |
| 75 __allow_access_to_unprotected_subobjects__ = 1 | |
| 76 def __getitem__(self, module): | |
| 77 __import__(module) | |
| 78 return sys.modules[module] | |
| 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 | 82 Undefs = (Undefined, AttributeError, KeyError, |
| 83 TypeError, IndexError, Unauthorized) | |
| 84 | |
| 85 def render(ob, ns): | |
| 86 """ | |
| 87 Calls the object, possibly a document template, or just returns it if | |
| 88 not callable. (From DT_Util.py) | |
| 89 """ | |
| 90 if hasattr(ob, '__render_with_namespace__'): | |
| 91 ob = call_with_ns(ob.__render_with_namespace__, ns) | |
| 92 else: | |
| 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 | 95 try: |
| 96 if getattr(base, 'isDocTemp', 0): | |
| 97 ob = call_with_ns(ob, ns, 2) | |
| 98 else: | |
| 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 | 101 if str(n) != '__call__': |
| 102 raise | |
| 103 return ob | |
| 104 | |
| 105 class SubPathExpr: | |
| 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 | 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 | 111 # Parse path |
| 112 self._dp = dp = [] | |
| 113 for i in range(len(path)): | |
| 114 e = path[i] | |
| 115 if e[:1] == '?' and _valid_name(e[1:]): | |
| 116 dp.append((i, e[1:])) | |
| 117 dp.reverse() | |
| 118 | |
| 119 def _eval(self, econtext, | |
| 120 list=list, isinstance=isinstance, StringType=type('')): | |
| 121 vars = econtext.vars | |
| 122 path = self._path | |
| 123 if self._dp: | |
| 124 path = list(path) # Copy! | |
| 125 for i, varname in self._dp: | |
| 126 val = vars[varname] | |
| 127 if isinstance(val, StringType): | |
| 128 path[i] = val | |
| 129 else: | |
| 130 # If the value isn't a string, assume it's a sequence | |
| 131 # of path names. | |
| 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 | 136 ob = econtext.contexts |
| 137 else: | |
| 138 ob = vars[base] | |
| 139 if isinstance(ob, DeferWrapper): | |
| 140 ob = ob() | |
| 141 if path: | |
| 142 ob = restrictedTraverse(ob, path, getSecurityManager()) | |
| 143 return ob | |
| 144 | |
| 145 class PathExpr: | |
| 146 def __init__(self, name, expr, engine): | |
| 147 self._s = expr | |
| 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 | 151 self._subexprs = [] |
| 152 add = self._subexprs.append | |
| 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 | 155 if _parse_expr(path): |
| 156 # This part is the start of another expression type, | |
| 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 | 160 break |
| 161 add(SubPathExpr(path)._eval) | |
| 162 | |
| 163 def _exists(self, econtext): | |
| 164 for expr in self._subexprs: | |
| 165 try: | |
| 166 expr(econtext) | |
| 167 except Undefs: | |
| 168 pass | |
| 169 else: | |
| 170 return 1 | |
| 171 return 0 | |
| 172 | |
| 173 def _eval(self, econtext, | |
| 174 isinstance=isinstance, StringType=type(''), render=render): | |
| 175 for expr in self._subexprs[:-1]: | |
| 176 # Try all but the last subexpression, skipping undefined ones. | |
| 177 try: | |
| 178 ob = expr(econtext) | |
| 179 except Undefs: | |
| 180 pass | |
| 181 else: | |
| 182 break | |
| 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 | 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 | 189 |
| 190 if self._name == 'nocall' or isinstance(ob, StringType): | |
| 191 return ob | |
| 192 # Return the rendered object | |
| 193 return render(ob, econtext.vars) | |
| 194 | |
| 195 def __call__(self, econtext): | |
| 196 if self._name == 'exists': | |
| 197 return self._exists(econtext) | |
| 198 return self._eval(econtext) | |
| 199 | |
| 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 | 202 |
| 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 | 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 | 208 |
| 209 class StringExpr: | |
| 210 def __init__(self, name, expr, engine): | |
| 211 self._s = expr | |
| 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 | 214 self._vars = vars = [] |
| 215 if '$' in expr: | |
| 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 | 218 if parts: parts.append('$') |
| 219 m = _interp.search(exp) | |
| 220 while m is not None: | |
| 221 parts.append(exp[:m.start()]) | |
| 222 parts.append('%s') | |
| 223 vars.append(PathExpr('path', m.group(1) or m.group(2), | |
| 224 engine)) | |
| 225 exp = exp[m.end():] | |
| 226 m = _interp.search(exp) | |
| 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 | 229 '$ must be doubled or followed by a simple path') |
| 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 | 232 self._expr = expr |
|
2349
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
233 |
| 1049 | 234 def __call__(self, econtext): |
| 235 vvals = [] | |
| 236 for var in self._vars: | |
| 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 | 241 vvals.append(v) |
| 242 return self._expr % tuple(vvals) | |
| 243 | |
| 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 | 246 |
| 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 | 249 |
| 250 class NotExpr: | |
| 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 | 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 | 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 | 260 |
| 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 | 263 |
| 264 class DeferWrapper: | |
| 265 def __init__(self, expr, econtext): | |
| 266 self._expr = expr | |
| 267 self._econtext = econtext | |
| 268 | |
| 269 def __str__(self): | |
| 270 return str(self()) | |
| 271 | |
| 272 def __call__(self): | |
| 273 return self._expr(self._econtext) | |
| 274 | |
| 275 class DeferExpr: | |
| 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 | 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 | 280 def __call__(self, econtext): |
| 281 return DeferWrapper(self._c, econtext) | |
| 282 | |
| 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 | 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 | 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 | 294 get=getattr, has=hasattr, N=None, M=[], |
| 295 TupleType=type(()) ): | |
| 296 | |
| 297 REQUEST = {'path': path} | |
| 298 REQUEST['TraversalRequestNameStack'] = path = path[:] # Copy! | |
| 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 | 303 while path: |
| 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 | 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 | 319 |
| 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 | 322 if o is M: |
| 323 # Try an item. | |
| 324 try: | |
| 325 # XXX maybe in Python 2.2 we can just check whether | |
| 326 # the object has the attribute "__getitem__" | |
| 327 # instead of blindly catching exceptions. | |
| 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 | 330 if str(exc).find('__getitem__') >= 0: |
| 331 # The object does not support the item interface. | |
| 332 # Try to re-raise the original attribute error. | |
| 333 # XXX I think this only happens with | |
| 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 | 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 | 338 if str(exc).find('unsubscriptable') >= 0: |
| 339 # The object does not support the item interface. | |
| 340 # Try to re-raise the original attribute error. | |
| 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 | 343 raise |
|
2351
97fae0466d97
more ZPT porting tweaks
Richard Jones <richard@users.sourceforge.net>
parents:
2349
diff
changeset
|
344 done.append((name, o)) |
| 1049 | 345 object = o |
| 346 | |
| 347 return object |
