annotate markup/eval.py @ 31:2ab5fa60575d trunk

* More test cases for expression evaluation. * Fixes for the new AST-based Python 2.5 evaluation.
author cmlenz
date Wed, 28 Jun 2006 18:39:05 +0000
parents bcdbb7e5e4e5
children 2224a52256ca
rev   line source
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
2 #
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
3 # Copyright (C) 2006 Christopher Lenz
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
4 # All rights reserved.
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
5 #
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
27
b4f78c05e5c9 * Fix the boilerplate in the Python source files.
cmlenz
parents: 16
diff changeset
8 # are also available at http://markup.cmlenz.net/wiki/License.
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
9 #
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
27
b4f78c05e5c9 * Fix the boilerplate in the Python source files.
cmlenz
parents: 16
diff changeset
12 # history and logs, available at http://markup.cmlenz.net/log/.
b4f78c05e5c9 * Fix the boilerplate in the Python source files.
cmlenz
parents: 16
diff changeset
13
b4f78c05e5c9 * Fix the boilerplate in the Python source files.
cmlenz
parents: 16
diff changeset
14 """Support for "safe" evaluation of Python expressions."""
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
15
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
16 import __builtin__
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
17 try:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
18 import _ast # Python 2.5
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
19 except ImportError:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
20 _ast = None
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
21 import compiler
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
22 import operator
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
23
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
24 from markup.core import Stream
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
25
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
26 __all__ = ['Expression']
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
27
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
28
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
29 class Expression(object):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
30 """Evaluates Python expressions used in templates.
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
31
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
32 >>> data = dict(test='Foo', items=[1, 2, 3], dict={'some': 'thing'})
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
33 >>> Expression('test').evaluate(data)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
34 'Foo'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
35 >>> Expression('items[0]').evaluate(data)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
36 1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
37 >>> Expression('items[-1]').evaluate(data)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
38 3
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
39 >>> Expression('dict["some"]').evaluate(data)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
40 'thing'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
41
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
42 Similar to e.g. Javascript, expressions in templates can use the dot
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
43 notation for attribute access to access items in mappings:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
44
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
45 >>> Expression('dict.some').evaluate(data)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
46 'thing'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
47
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
48 This also works the other way around: item access can be used to access
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
49 any object attribute (meaning there's no use for `getattr()` in templates):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
50
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
51 >>> class MyClass(object):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
52 ... myattr = 'Bar'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
53 >>> data = dict(mine=MyClass(), key='myattr')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
54 >>> Expression('mine.myattr').evaluate(data)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
55 'Bar'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
56 >>> Expression('mine["myattr"]').evaluate(data)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
57 'Bar'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
58 >>> Expression('mine[key]').evaluate(data)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
59 'Bar'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
60
31
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
61 All of the standard Python operators are available to template expressions.
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
62 Built-in functions such as `len()` are also available in template
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
63 expressions:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
64
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
65 >>> data = dict(items=[1, 2, 3])
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
66 >>> Expression('len(items)').evaluate(data)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
67 3
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
68 """
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
69 __slots__ = ['source', 'ast']
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
70 __visitors = {}
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
71
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
72 def __init__(self, source):
27
b4f78c05e5c9 * Fix the boilerplate in the Python source files.
cmlenz
parents: 16
diff changeset
73 """Create the expression.
b4f78c05e5c9 * Fix the boilerplate in the Python source files.
cmlenz
parents: 16
diff changeset
74
b4f78c05e5c9 * Fix the boilerplate in the Python source files.
cmlenz
parents: 16
diff changeset
75 @param source: the expression as string
b4f78c05e5c9 * Fix the boilerplate in the Python source files.
cmlenz
parents: 16
diff changeset
76 """
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
77 self.source = source
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
78 self.ast = None
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
79
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
80 def __repr__(self):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
81 return '<Expression "%s">' % self.source
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
82
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
83 if _ast is None:
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
84
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
85 def evaluate(self, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
86 """Evaluate the expression against the given data dictionary.
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
87
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
88 @param data: a mapping containing the data to evaluate against
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
89 @return: the result of the evaluation
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
90 """
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
91 if not self.ast:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
92 self.ast = compiler.parse(self.source, 'eval')
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
93 return self._visit(self.ast.node, data)
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
94
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
95 # AST traversal
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
96
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
97 def _visit(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
98 v = self.__visitors.get(node.__class__)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
99 if not v:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
100 v = getattr(self, '_visit_%s' % node.__class__.__name__.lower())
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
101 self.__visitors[node.__class__] = v
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
102 return v(node, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
103
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
104 def _visit_expression(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
105 for child in node.getChildNodes():
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
106 return self._visit(child, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
107
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
108 # Functions & Accessors
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
109
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
110 def _visit_callfunc(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
111 func = self._visit(node.node, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
112 if func is None:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
113 return None
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
114 args = [self._visit(arg, data) for arg in node.args
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
115 if not isinstance(arg, compiler.ast.Keyword)]
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
116 kwargs = dict([(arg.name, self._visit(arg.expr, data)) for arg
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
117 in node.args if isinstance(arg, compiler.ast.Keyword)])
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
118 return func(*args, **kwargs)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
119
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
120 def _visit_getattr(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
121 obj = self._visit(node.expr, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
122 if hasattr(obj, node.attrname):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
123 return getattr(obj, node.attrname)
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
124 try:
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
125 return obj[node.attrname]
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
126 except TypeError:
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
127 return None
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
128
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
129 def _visit_slice(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
130 obj = self._visit(node.expr, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
131 lower = node.lower and self._visit(node.lower, data) or None
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
132 upper = node.upper and self._visit(node.upper, data) or None
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
133 return obj[lower:upper]
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
134
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
135 def _visit_subscript(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
136 obj = self._visit(node.expr, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
137 subs = map(lambda sub: self._visit(sub, data), node.subs)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
138 if len(subs) == 1:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
139 subs = subs[0]
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
140 try:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
141 return obj[subs]
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
142 except (KeyError, IndexError, TypeError):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
143 try:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
144 return getattr(obj, subs)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
145 except (AttributeError, TypeError):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
146 return None
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
147
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
148 # Operators
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
149
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
150 def _visit_and(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
151 return reduce(lambda x, y: x and y,
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
152 [self._visit(n, data) for n in node.nodes])
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
153
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
154 def _visit_or(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
155 return reduce(lambda x, y: x or y,
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
156 [self._visit(n, data) for n in node.nodes])
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
157
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
158 _OP_MAP = {'==': operator.eq, '!=': operator.ne,
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
159 '<': operator.lt, '<=': operator.le,
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
160 '>': operator.gt, '>=': operator.ge,
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
161 'in': lambda x, y: operator.contains(y, x),
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
162 'not in': lambda x, y: not operator.contains(y, x)}
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
163 def _visit_compare(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
164 result = self._visit(node.expr, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
165 ops = node.ops[:]
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
166 ops.reverse()
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
167 for op, rval in ops:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
168 result = self._OP_MAP[op](result, self._visit(rval, data))
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
169 return result
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
170
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
171 def _visit_add(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
172 return self._visit(node.left, data) + self._visit(node.right, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
173
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
174 def _visit_div(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
175 return self._visit(node.left, data) / self._visit(node.right, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
176
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
177 def _visit_floordiv(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
178 return self._visit(node.left, data) // self._visit(node.right, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
179
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
180 def _visit_mod(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
181 return self._visit(node.left, data) % self._visit(node.right, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
182
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
183 def _visit_mul(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
184 return self._visit(node.left, data) * self._visit(node.right, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
185
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
186 def _visit_power(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
187 return self._visit(node.left, data) ** self._visit(node.right, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
188
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
189 def _visit_sub(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
190 return self._visit(node.left, data) - self._visit(node.right, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
191
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
192 def _visit_not(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
193 return not self._visit(node.expr, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
194
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
195 def _visit_unaryadd(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
196 return +self._visit(node.expr, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
197
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
198 def _visit_unarysub(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
199 return -self._visit(node.expr, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
200
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
201 # Identifiers & Literals
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
202
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
203 def _visit_name(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
204 val = data.get(node.name)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
205 if val is None:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
206 val = getattr(__builtin__, node.name, None)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
207 return val
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
208
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
209 def _visit_const(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
210 return node.value
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
211
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
212 def _visit_dict(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
213 return dict([(self._visit(k, data), self._visit(v, data))
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
214 for k, v in node.items])
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
215
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
216 def _visit_tuple(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
217 return tuple([self._visit(n, data) for n in node.nodes])
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
218
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
219 def _visit_list(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
220 return [self._visit(n, data) for n in node.nodes]
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
221
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
222 else:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
223
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
224 def evaluate(self, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
225 """Evaluate the expression against the given data dictionary.
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
226
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
227 @param data: a mapping containing the data to evaluate against
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
228 @return: the result of the evaluation
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
229 """
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
230 if not self.ast:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
231 self.ast = compile(self.source, '?', 'eval', 0x400)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
232 return self._visit(self.ast, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
233
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
234 # AST traversal
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
235
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
236 def _visit(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
237 v = self.__visitors.get(node.__class__)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
238 if not v:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
239 v = getattr(self, '_visit_%s' % node.__class__.__name__.lower())
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
240 self.__visitors[node.__class__] = v
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
241 return v(node, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
242
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
243 def _visit_expression(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
244 return self._visit(node.body, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
245
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
246 # Functions & Accessors
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
247
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
248 def _visit_attribute(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
249 obj = self._visit(node.value, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
250 if hasattr(obj, node.attr):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
251 return getattr(obj, node.attr)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
252 try:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
253 return obj[node.attr]
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
254 except TypeError:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
255 return None
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
256
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
257 def _visit_call(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
258 func = self._visit(node.func, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
259 if func is None:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
260 return None
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
261 args = [self._visit(arg, data) for arg in node.args]
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
262 kwargs = dict([(kwarg.arg, self._visit(kwarg.value, data))
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
263 for kwarg in node.keywords])
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
264 return func(*args, **kwargs)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
265
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
266 def _visit_subscript(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
267 obj = self._visit(node.value, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
268 if isinstance(node.slice, _ast.Slice):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
269 try:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
270 return obj[self._visit(lower, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
271 self._visit(upper, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
272 self._visit(step, data)]
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
273 except (KeyError, IndexError, TypeError):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
274 pass
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
275 else:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
276 index = self._visit(node.slice.value, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
277 try:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
278 return obj[index]
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
279 except (KeyError, IndexError, TypeError):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
280 try:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
281 return getattr(obj, index)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
282 except (AttributeError, TypeError):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
283 pass
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
284 return None
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
285
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
286 # Operators
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
287
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
288 _OP_MAP = {_ast.Add: operator.add, _ast.And: lambda l, r: l and r,
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
289 _ast.Div: operator.div, _ast.Eq: operator.eq,
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
290 _ast.FloorDiv: operator.floordiv, _ast.Gt: operator.gt,
31
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
291 _ast.GtE: operator.ge,
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
292 _ast.In: lambda l, r: operator.contains(r, l),
31
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
293 _ast.Lt: operator.lt, _ast.LtE: operator.le,
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
294 _ast.Mod: operator.mod, _ast.Mult: operator.mul,
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
295 _ast.Not: operator.not_, _ast.NotEq: operator.ne,
31
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
296 _ast.NotIn: lambda l, r: not operator.contains(r, l),
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
297 _ast.Or: lambda l, r: l or r, _ast.Pow: operator.pow,
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
298 _ast.Sub: operator.sub, _ast.UAdd: operator.pos,
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
299 _ast.USub: operator.neg}
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
300
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
301 def _visit_unaryop(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
302 return self._OP_MAP[node.op.__class__](self._visit(node.operand, data))
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
303
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
304 def _visit_binop(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
305 return self._OP_MAP[node.op.__class__](self._visit(node.left, data),
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
306 self._visit(node.right, data))
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
307
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
308 def _visit_boolop(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
309 return reduce(self._OP_MAP[node.op.__class__],
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
310 [self._visit(n, data) for n in node.values])
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
311
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
312 def _visit_compare(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
313 result = self._visit(node.left, data)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
314 ops = node.ops[:]
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
315 ops.reverse()
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
316 for op, rval in zip(ops, node.comparators):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
317 result = self._OP_MAP[op.__class__](result,
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
318 self._visit(rval, data))
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
319 return result
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
320
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
321 # Identifiers & Literals
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
322
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
323 def _visit_dict(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
324 return dict([(self._visit(k, data), self._visit(v, data))
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
325 for k, v in zip(node.keys, node.values)])
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
326
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
327 def _visit_list(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
328 return [self._visit(n, data) for n in node.elts]
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
329
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
330 def _visit_name(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
331 val = data.get(node.id)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
332 if val is None:
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
333 val = getattr(__builtin__, node.id, None)
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
334 return val
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
335
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
336 def _visit_num(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
337 return node.n
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
338
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
339 def _visit_str(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
340 return node.s
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
341
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
342 def _visit_tuple(self, node, data):
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
343 return tuple([self._visit(n, data) for n in node.elts])
Copyright (C) 2012-2017 Edgewall Software