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 """Generic Python Expression Handler
|
|
1071
|
15
|
|
|
16 Modified for Roundup 0.5 release:
|
|
|
17
|
|
|
18 - more informative traceback info
|
|
|
19
|
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
20 """
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
21
|
|
1071
|
22 __version__='$Revision: 1.3 $'[11:-2]
|
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
23
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
24 from TALES import CompilerError
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
25 from string import strip, split, join, replace, lstrip
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
26 from sys import exc_info
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
27
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
28 class getSecurityManager:
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
29 '''Null security manager'''
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
30 def validate(self, *args, **kwargs):
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
31 return 1
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
32 addContext = removeContext = validateValue = validate
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
33
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
34 class PythonExpr:
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
35 def __init__(self, name, expr, engine):
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
36 self.expr = expr = replace(strip(expr), '\n', ' ')
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
37 try:
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
38 d = {}
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
39 exec 'def f():\n return %s\n' % strip(expr) in d
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
40 self._f = d['f']
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
41 except:
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
42 raise CompilerError, ('Python expression error:\n'
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
43 '%s: %s') % exc_info()[:2]
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
44 self._get_used_names()
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
45
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
46 def _get_used_names(self):
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
47 self._f_varnames = vnames = []
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
48 for vname in self._f.func_code.co_names:
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
49 if vname[0] not in '$_':
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
50 vnames.append(vname)
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
51
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
52 def _bind_used_names(self, econtext):
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
53 # Bind template variables
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
54 names = {}
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
55 vars = econtext.vars
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
56 getType = econtext._engine.getTypes().get
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
57 for vname in self._f_varnames:
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
58 has, val = vars.has_get(vname)
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
59 if not has:
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
60 has = val = getType(vname)
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
61 if has:
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
62 val = ExprTypeProxy(vname, val, econtext)
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
63 if has:
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
64 names[vname] = val
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
65 return names
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
66
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
67 def __call__(self, econtext):
|
1065
0f9aa62917bd
much nicer error messages when there's a templating error
Richard Jones <richard@users.sourceforge.net>
diff
changeset
|
68 __traceback_info__ = 'python expression "%s"'%self.expr
|
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
69 f = self._f
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
70 f.func_globals.update(self._bind_used_names(econtext))
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
71 return f()
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
72
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
73 def __str__(self):
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
74 return 'Python expression "%s"' % self.expr
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
75 def __repr__(self):
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
76 return '<PythonExpr %s>' % self.expr
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
77
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
78 class ExprTypeProxy:
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
79 '''Class that proxies access to an expression type handler'''
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
80 def __init__(self, name, handler, econtext):
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
81 self._name = name
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
82 self._handler = handler
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
83 self._econtext = econtext
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
84 def __call__(self, text):
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
85 return self._handler(self._name, text,
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
86 self._econtext._engine)(self._econtext)
|
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
87
|