Code

missed one
[roundup.git] / PageTemplates / PythonExpr.py
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 ##############################################################################
14 """Generic Python Expression Handler
15 """
17 __version__='$Revision: 1.1 $'[11:-2]
19 from TALES import CompilerError
20 from string import strip, split, join, replace, lstrip
21 from sys import exc_info
23 class getSecurityManager:
24     '''Null security manager'''
25     def validate(self, *args, **kwargs):
26         return 1
27     addContext = removeContext = validateValue = validate
29 class PythonExpr:
30     def __init__(self, name, expr, engine):
31         self.expr = expr = replace(strip(expr), '\n', ' ')
32         try:
33             d = {}
34             exec 'def f():\n return %s\n' % strip(expr) in d
35             self._f = d['f']
36         except:
37             raise CompilerError, ('Python expression error:\n'
38                                   '%s: %s') % exc_info()[:2]
39         self._get_used_names()
41     def _get_used_names(self):
42         self._f_varnames = vnames = []
43         for vname in self._f.func_code.co_names:
44             if vname[0] not in '$_':
45                 vnames.append(vname)
47     def _bind_used_names(self, econtext):
48         # Bind template variables
49         names = {}
50         vars = econtext.vars
51         getType = econtext._engine.getTypes().get
52         for vname in self._f_varnames:
53             has, val = vars.has_get(vname)
54             if not has:
55                 has = val = getType(vname)
56                 if has:
57                     val = ExprTypeProxy(vname, val, econtext)
58             if has:
59                 names[vname] = val
60         return names
62     def __call__(self, econtext):
63         __traceback_info__ = self.expr
64         f = self._f
65         f.func_globals.update(self._bind_used_names(econtext))        
66         return f()
68     def __str__(self):
69         return 'Python expression "%s"' % self.expr
70     def __repr__(self):
71         return '<PythonExpr %s>' % self.expr
73 class ExprTypeProxy:
74     '''Class that proxies access to an expression type handler'''
75     def __init__(self, name, handler, econtext):
76         self._name = name
77         self._handler = handler
78         self._econtext = econtext
79     def __call__(self, text):
80         return self._handler(self._name, text,
81                              self._econtext._engine)(self._econtext)