/usr/share/pyshared/zope/tales/expressions.py is in python-zope.tales 3.5.3-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | ##############################################################################
#
# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Basic Page Template expression types.
$Id: expressions.py 126816 2012-06-11 19:00:21Z tseaver $
"""
import re, types
from zope.interface import implements
from zope.tales.tales import _valid_name, _parse_expr, NAME_RE, Undefined
from zope.tales.interfaces import ITALESExpression, ITALESFunctionNamespace
Undefs = (Undefined, AttributeError, LookupError, TypeError)
_marker = object()
namespace_re = re.compile(r'(\w+):(.+)')
def simpleTraverse(object, path_items, econtext):
"""Traverses a sequence of names, first trying attributes then items.
"""
for name in path_items:
next = getattr(object, name, _marker)
if next is not _marker:
object = next
elif hasattr(object, '__getitem__'):
object = object[name]
else:
# Allow AttributeError to propagate
object = getattr(object, name)
return object
class SubPathExpr(object):
def __init__(self, path, traverser, engine):
self._traverser = traverser
self._engine = engine
# Parse path
compiledpath = []
currentpath = []
for element in str(path).strip().split('/'):
if not element:
raise engine.getCompilerError()(
'Path element may not be empty in %r' % path)
if element.startswith('?'):
if currentpath:
compiledpath.append(tuple(currentpath))
currentpath = []
if not _valid_name(element[1:]):
raise engine.getCompilerError()(
'Invalid variable name "%s"' % element[1:])
compiledpath.append(element[1:])
else:
match = namespace_re.match(element)
if match:
if currentpath:
compiledpath.append(tuple(currentpath))
currentpath = []
namespace, functionname = match.groups()
if not _valid_name(namespace):
raise engine.getCompilerError()(
'Invalid namespace name "%s"' % namespace)
try:
compiledpath.append(
self._engine.getFunctionNamespace(namespace))
except KeyError:
raise engine.getCompilerError()(
'Unknown namespace "%s"' % namespace)
currentpath.append(functionname)
else:
currentpath.append(element)
if currentpath:
compiledpath.append(tuple(currentpath))
first = compiledpath[0]
base = first[0]
if callable(first):
# check for initial function
raise engine.getCompilerError()(
'Namespace function specified in first subpath element')
elif isinstance(first, basestring):
# check for initial ?
raise engine.getCompilerError()(
'Dynamic name specified in first subpath element')
if base and not _valid_name(base):
raise engine.getCompilerError()(
'Invalid variable name "%s"' % element)
self._base = base
compiledpath[0] = first[1:]
self._compiled_path = tuple(compiledpath)
def _eval(self, econtext,
isinstance=isinstance):
vars = econtext.vars
compiled_path = self._compiled_path
base = self._base
if base == 'CONTEXTS' or not base: # Special base name
ob = econtext.contexts
else:
ob = vars[base]
if isinstance(ob, DeferWrapper):
ob = ob()
for element in compiled_path:
if isinstance(element, tuple):
ob = self._traverser(ob, element, econtext)
elif isinstance(element, basestring):
val = vars[element]
# If the value isn't a string, assume it's a sequence
# of path names.
if isinstance(val, basestring):
val = (val,)
ob = self._traverser(ob, val, econtext)
elif callable(element):
ob = element(ob)
# TODO: Once we have n-ary adapters, use them.
if ITALESFunctionNamespace.providedBy(ob):
ob.setEngine(econtext)
else:
raise ValueError(repr(element))
return ob
class PathExpr(object):
"""One or more subpath expressions, separated by '|'."""
implements(ITALESExpression)
# _default_type_names contains the expression type names this
# class is usually registered for.
_default_type_names = (
'standard',
'path',
'exists',
'nocall',
)
def __init__(self, name, expr, engine, traverser=simpleTraverse):
self._s = expr
self._name = name
self._hybrid = False
paths = expr.split('|')
self._subexprs = []
add = self._subexprs.append
for i in range(len(paths)):
path = paths[i].lstrip()
if _parse_expr(path):
# This part is the start of another expression type,
# so glue it back together and compile it.
add(engine.compile('|'.join(paths[i:]).lstrip()))
self._hybrid = True
break
add(SubPathExpr(path, traverser, engine)._eval)
def _exists(self, econtext):
for expr in self._subexprs:
try:
expr(econtext)
except Undefs:
pass
else:
return 1
return 0
def _eval(self, econtext):
for expr in self._subexprs[:-1]:
# Try all but the last subexpression, skipping undefined ones.
try:
ob = expr(econtext)
except Undefs:
pass
else:
break
else:
# On the last subexpression allow exceptions through, and
# don't autocall if the expression was not a subpath.
ob = self._subexprs[-1](econtext)
if self._hybrid:
return ob
if self._name == 'nocall':
return ob
# Call the object if it is callable. Note that checking for
# callable() isn't safe because the object might be security
# proxied (and security proxies report themselves callable, no
# matter what the underlying object is). We therefore check
# for the __call__ attribute, but not with hasattr as that
# eats babies, err, exceptions. In addition to that, we
# support calling old style classes which don't have a
# __call__.
if (getattr(ob, '__call__', _marker) is not _marker
or isinstance(ob, types.ClassType)):
return ob()
return ob
def __call__(self, econtext):
if self._name == 'exists':
return self._exists(econtext)
return self._eval(econtext)
def __str__(self):
return '%s expression (%s)' % (self._name, `self._s`)
def __repr__(self):
return '<PathExpr %s:%s>' % (self._name, `self._s`)
_interp = re.compile(
r'\$(%(n)s)|\${(%(n)s(?:/[^}|]*)*(?:\|%(n)s(?:/[^}|]*)*)*)}'
% {'n': NAME_RE})
class StringExpr(object):
implements(ITALESExpression)
def __init__(self, name, expr, engine):
self._s = expr
if '%' in expr:
expr = expr.replace('%', '%%')
self._vars = vars = []
if '$' in expr:
# Use whatever expr type is registered as "path".
path_type = engine.getTypes()['path']
parts = []
for exp in expr.split('$$'):
if parts: parts.append('$')
m = _interp.search(exp)
while m is not None:
parts.append(exp[:m.start()])
parts.append('%s')
vars.append(path_type(
'path', m.group(1) or m.group(2), engine))
exp = exp[m.end():]
m = _interp.search(exp)
if '$' in exp:
raise engine.getCompilerError()(
'$ must be doubled or followed by a simple path')
parts.append(exp)
expr = ''.join(parts)
self._expr = expr
def __call__(self, econtext):
vvals = []
for var in self._vars:
v = var(econtext)
vvals.append(v)
return self._expr % tuple(vvals)
def __str__(self):
return 'string expression (%s)' % `self._s`
def __repr__(self):
return '<StringExpr %s>' % `self._s`
class NotExpr(object):
implements(ITALESExpression)
def __init__(self, name, expr, engine):
self._s = expr = expr.lstrip()
self._c = engine.compile(expr)
def __call__(self, econtext):
return int(not econtext.evaluateBoolean(self._c))
def __repr__(self):
return '<NotExpr %s>' % `self._s`
class DeferWrapper(object):
def __init__(self, expr, econtext):
self._expr = expr
self._econtext = econtext
def __str__(self):
return str(self())
def __call__(self):
return self._expr(self._econtext)
class DeferExpr(object):
implements(ITALESExpression)
def __init__(self, name, expr, compiler):
self._s = expr = expr.lstrip()
self._c = compiler.compile(expr)
def __call__(self, econtext):
return DeferWrapper(self._c, econtext)
def __repr__(self):
return '<DeferExpr %s>' % `self._s`
class LazyWrapper(DeferWrapper):
"""Wrapper for lazy: expression
"""
def __init__(self, expr, econtext):
DeferWrapper.__init__(self, expr, econtext)
self._result = _marker
def __call__(self):
r = self._result
if r is _marker:
self._result = r = self._expr(self._econtext)
return r
class LazyExpr(DeferExpr):
"""lazy: expression handler for lazy initialization of expressions
"""
def __call__(self, econtext):
return LazyWrapper(self._c, econtext)
def __repr__(self):
return 'lazy:%s' % `self._s`
class SimpleModuleImporter(object):
"""Minimal module importer with no security."""
def __getitem__(self, module):
mod = self._get_toplevel_module(module)
path = module.split('.')
for name in path[1:]:
mod = getattr(mod, name)
return mod
def _get_toplevel_module(self, module):
# This can be overridden to add security proxies.
return __import__(module)
|