diff options
author | Christian Theune <ct@gocept.com> | 2007-05-03 22:35:25 +0000 |
---|---|---|
committer | Christian Theune <ct@gocept.com> | 2007-05-03 22:35:25 +0000 |
commit | c22323738052f10b7d7a7666af461665c98a5b74 (patch) | |
tree | 3758cb7be28ca04ff4a52f116697a7fa77889ffb /src/zope/tales/pythonexpr.py | |
parent | 870f3ec712344b8c3edfdd0cae88a665612bb6b3 (diff) | |
parent | 6a5b890041b03a7cbf466e2b5b67622b3bedab2f (diff) | |
download | zope-tales-c22323738052f10b7d7a7666af461665c98a5b74.tar.gz |
Moving code to satellite.
Diffstat (limited to 'src/zope/tales/pythonexpr.py')
-rw-r--r-- | src/zope/tales/pythonexpr.py | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/zope/tales/pythonexpr.py b/src/zope/tales/pythonexpr.py new file mode 100644 index 0000000..7fab3bb --- /dev/null +++ b/src/zope/tales/pythonexpr.py @@ -0,0 +1,77 @@ +############################################################################## +# +# Copyright (c) 2001, 2002 Zope Corporation 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. +# +############################################################################## +"""Generic Python Expression Handler + +$Id$ +""" + +class PythonExpr(object): + def __init__(self, name, expr, engine): + text = '\n'.join(expr.splitlines()) # normalize line endings + text = '(' + text + ')' # Put text in parens so newlines don't matter + self.text = text + try: + code = self._compile(text, '<string>') + except SyntaxError, e: + raise engine.getCompilerError()(str(e)) + self._code = code + self._varnames = code.co_names + + def _compile(self, text, filename): + return compile(text, filename, 'eval') + + def _bind_used_names(self, econtext, builtins): + # Construct a dictionary of globals with which the Python + # expression should be evaluated. + names = {} + vars = econtext.vars + marker = self + if not isinstance(builtins, dict): + builtins = builtins.__dict__ + for vname in self._varnames: + val = vars.get(vname, marker) + if val is not marker: + names[vname] = val + elif vname not in builtins: + # Fall back to using expression types as variable values. + val = econtext._engine.getTypes().get(vname, marker) + if val is not marker: + val = ExprTypeProxy(vname, val, econtext) + names[vname] = val + + names['__builtins__'] = builtins + return names + + def __call__(self, econtext): + __traceback_info__ = self.text + vars = self._bind_used_names(econtext, __builtins__) + return eval(self._code, vars) + + def __str__(self): + return 'Python expression "%s"' % self.text + + def __repr__(self): + return '<PythonExpr %s>' % self.text + + +class ExprTypeProxy(object): + '''Class that proxies access to an expression type handler''' + def __init__(self, name, handler, econtext): + self._name = name + self._handler = handler + self._econtext = econtext + + def __call__(self, text): + return self._handler(self._name, text, + self._econtext._engine)(self._econtext) |