[Zope-CVS] CVS: Packages/pypes/pypes - expression.py:1.3
Casey Duncan
casey at zope.com
Sat Jan 31 00:24:01 EST 2004
Update of /cvs-repository/Packages/pypes/pypes
In directory cvs.zope.org:/tmp/cvs-serv16271
Modified Files:
expression.py
Log Message:
Implement freeOperands method and simple expression __call__
make sure expression tests are run by runtests
=== Packages/pypes/pypes/expression.py 1.2 => 1.3 ===
--- Packages/pypes/pypes/expression.py:1.2 Fri Jan 30 00:41:37 2004
+++ Packages/pypes/pypes/expression.py Sat Jan 31 00:23:30 2004
@@ -16,6 +16,8 @@
$Id:S"""
import sys
+import __builtin__
+from sets import Set
from compiler import parse, ast
class Expression:
@@ -30,25 +32,63 @@
"""
self._expr = expr
self._tree = parse(expr, mode='eval')
- self._ns = {}
+ self._bindings = {}
if namespace is not None:
for name in self.names():
try:
- self._ns[name] = namespace[name]
+ self._bindings[name] = namespace[name]
except KeyError:
pass
def names(self, _tree=None, _names=None):
- """Return a list of the names used in the expression"""
+ """Return a set of the names used in the expression"""
if _tree is None:
_tree = self._tree
if _names is None:
- _names = []
+ _names = Set()
+ if isinstance(_tree, ast.Name):
+ _names.add(_tree.name)
for node in _tree.getChildNodes():
if isinstance(node, ast.Name):
- _names.append(node.name)
+ _names.add(node.name)
self.names(node, _names)
return _names
+
+ def freeOperands(self, free_names=[], _tree=None, _nodes=None):
+ """Return a list of ast nodes cooresponding to top-level operands with
+ free variables not in the expression's bound namespace or builtins,
+ excepting names supplied in free_names. These operands are satisfied by
+ names supplied when the expression is executed, which makes them
+ interesting to machinery intending to apply the expression.
+
+ These nodes are the right and left sides of comparisons, or single
+ nodes used in truth tests. Note that only top-level comparison nodes
+ are decended to find operands. Nested comparisons are therefore
+ themselves considered whole operands.
+ """
+ if _tree is None:
+ _tree = self._tree
+ if _nodes is None:
+ _nodes = []
+ all_names = (
+ Set(self._bindings.keys() + dir(__builtin__)) - Set(free_names))
+ for node in _tree.getChildNodes():
+ if isinstance(node, (ast.And, ast.Or, ast.Not)):
+ self.freeOperands(free_names, node, _nodes)
+ elif isinstance(node, ast.Compare):
+ for operand in node.getChildNodes():
+ if Set(self.names(operand)) - all_names:
+ _nodes.append(operand)
+ elif Set(self.names(node)) - all_names:
+ _nodes.append(node)
+ return _nodes
+
+ def __call__(self, namespace={}):
+ """Evaluate the expression with the namespace provided and return the
+ result. The provided namespace extends and overrides names bound to
+ the expression when constructed.
+ """
+ return eval(self._expr, self._bindings, namespace)
def __str__(self):
return "Expression('%s')" % self._expr
More information about the Zope-CVS
mailing list