annotate markup/eval.py @ 30:2ee9f28e16e5

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