1 ##############################################################################
2 #
3 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
4 #
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
11 #
12 ##############################################################################
13 # Modified for Roundup:
14 #
15 # 1. more informative traceback info
17 """Generic Python Expression Handler
18 """
20 __version__='$Revision: 1.6 $'[11:-2]
22 from TALES import CompilerError
23 from sys import exc_info
25 class getSecurityManager:
26 '''Null security manager'''
27 def validate(self, *args, **kwargs):
28 return 1
29 addContext = removeContext = validateValue = validate
31 class PythonExpr:
32 def __init__(self, name, expr, engine):
33 self.expr = expr = expr.strip().replace('\n', ' ')
34 try:
35 d = {}
36 exec 'def f():\n return %s\n' % expr.strip() in d
37 self._f = d['f']
38 except:
39 raise CompilerError, ('Python expression error:\n'
40 '%s: %s') % exc_info()[:2]
41 self._get_used_names()
43 def _get_used_names(self):
44 self._f_varnames = vnames = []
45 for vname in self._f.func_code.co_names:
46 if vname[0] not in '$_':
47 vnames.append(vname)
49 def _bind_used_names(self, econtext, _marker=[]):
50 # Bind template variables
51 names = {'CONTEXTS': econtext.contexts}
52 vars = econtext.vars
53 getType = econtext.getCompiler().getTypes().get
54 for vname in self._f_varnames:
55 val = vars.get(vname, _marker)
56 if val is _marker:
57 has = val = getType(vname)
58 if has:
59 val = ExprTypeProxy(vname, val, econtext)
60 names[vname] = val
61 else:
62 names[vname] = val
63 return names
65 def __call__(self, econtext):
66 __traceback_info__ = 'python expression "%s"'%self.expr
67 f = self._f
68 f.func_globals.update(self._bind_used_names(econtext))
69 return f()
71 def __str__(self):
72 return 'Python expression "%s"' % self.expr
73 def __repr__(self):
74 return '<PythonExpr %s>' % self.expr
76 class ExprTypeProxy:
77 '''Class that proxies access to an expression type handler'''
78 def __init__(self, name, handler, econtext):
79 self._name = name
80 self._handler = handler
81 self._econtext = econtext
82 def __call__(self, text):
83 return self._handler(self._name, text,
84 self._econtext.getCompiler())(self._econtext)