Mercurial > genshi > mirror
annotate markup/eval.py @ 84:0a1843b2c096 trunk
Make dependency of the setup script on setuptools optional.
author | cmlenz |
---|---|
date | Sat, 15 Jul 2006 12:10:51 +0000 |
parents | 5ca4be55ad0b |
children | a54ebae77330 |
rev | line source |
---|---|
1 | 1 # -*- coding: utf-8 -*- |
2 # | |
66
59eb24184e9c
Switch copyright to Edgewall and URLs to markup.edgewall.org.
cmlenz
parents:
42
diff
changeset
|
3 # Copyright (C) 2006 Edgewall Software |
1 | 4 # All rights reserved. |
5 # | |
6 # This software is licensed as described in the file COPYING, which | |
7 # you should have received as part of this distribution. The terms | |
66
59eb24184e9c
Switch copyright to Edgewall and URLs to markup.edgewall.org.
cmlenz
parents:
42
diff
changeset
|
8 # are also available at http://markup.edgewall.org/wiki/License. |
1 | 9 # |
10 # This software consists of voluntary contributions made by many | |
11 # individuals. For the exact contribution history, see the revision | |
66
59eb24184e9c
Switch copyright to Edgewall and URLs to markup.edgewall.org.
cmlenz
parents:
42
diff
changeset
|
12 # history and logs, available at http://markup.edgewall.org/log/. |
27 | 13 |
14 """Support for "safe" evaluation of Python expressions.""" | |
1 | 15 |
32 | 16 from __future__ import division |
17 | |
1 | 18 import __builtin__ |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
19 from compiler import parse, pycodegen |
1 | 20 |
21 from markup.core import Stream | |
22 | |
23 __all__ = ['Expression'] | |
24 | |
25 | |
26 class Expression(object): | |
27 """Evaluates Python expressions used in templates. | |
28 | |
29 >>> data = dict(test='Foo', items=[1, 2, 3], dict={'some': 'thing'}) | |
30 >>> Expression('test').evaluate(data) | |
31 'Foo' | |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
32 |
1 | 33 >>> Expression('items[0]').evaluate(data) |
34 1 | |
35 >>> Expression('items[-1]').evaluate(data) | |
36 3 | |
37 >>> Expression('dict["some"]').evaluate(data) | |
38 'thing' | |
39 | |
40 Similar to e.g. Javascript, expressions in templates can use the dot | |
41 notation for attribute access to access items in mappings: | |
42 | |
43 >>> Expression('dict.some').evaluate(data) | |
44 'thing' | |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
45 """ |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
46 """ |
1 | 47 This also works the other way around: item access can be used to access |
48 any object attribute (meaning there's no use for `getattr()` in templates): | |
49 | |
50 >>> class MyClass(object): | |
51 ... myattr = 'Bar' | |
52 >>> data = dict(mine=MyClass(), key='myattr') | |
53 >>> Expression('mine.myattr').evaluate(data) | |
54 'Bar' | |
55 >>> Expression('mine["myattr"]').evaluate(data) | |
56 'Bar' | |
57 >>> Expression('mine[key]').evaluate(data) | |
58 'Bar' | |
59 | |
31 | 60 All of the standard Python operators are available to template expressions. |
1 | 61 Built-in functions such as `len()` are also available in template |
62 expressions: | |
63 | |
64 >>> data = dict(items=[1, 2, 3]) | |
65 >>> Expression('len(items)').evaluate(data) | |
66 3 | |
67 """ | |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
68 __slots__ = ['source', 'code'] |
69 | 69 _visitors = {} |
1 | 70 |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
71 def __init__(self, source, filename=None, lineno=-1): |
27 | 72 """Create the expression. |
73 | |
74 @param source: the expression as string | |
75 """ | |
1 | 76 self.source = source |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
77 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
78 tree = parse(self.source, 'eval') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
79 if isinstance(filename, unicode): |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
80 # pycodegen doesn't like unicode in the filename |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
81 filename = filename.encode('utf-8', 'replace') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
82 tree.filename = filename or '<string>' |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
83 gen = TemplateExpressionCodeGenerator(tree) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
84 if lineno >= 0: |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
85 gen.emit('SET_LINENO', lineno) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
86 self.code = gen.getCode() |
1 | 87 |
88 def __repr__(self): | |
89 return '<Expression "%s">' % self.source | |
90 | |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
91 def evaluate(self, data): |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
92 """Evaluate the expression against the given data dictionary. |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
93 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
94 @param data: a mapping containing the data to evaluate against |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
95 @return: the result of the evaluation |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
96 """ |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
97 return eval(self.code) |
30
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
98 |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
99 |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
100 class TemplateExpressionCodeGenerator(pycodegen.ExpressionCodeGenerator): |
30
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
101 |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
102 def visitGetattr(self, node): |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
103 """Overridden to fallback to item access if the object doesn't have an |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
104 attribute. |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
105 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
106 Also, if either method fails, this returns `None` instead of raising an |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
107 `AttributeError`. |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
108 """ |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
109 # check whether the object has the request attribute |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
110 self.visit(node.expr) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
111 self.emit('STORE_NAME', 'obj') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
112 self.emit('LOAD_GLOBAL', 'hasattr') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
113 self.emit('LOAD_NAME', 'obj') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
114 self.emit('LOAD_CONST', node.attrname) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
115 self.emit('CALL_FUNCTION', 2) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
116 else_ = self.newBlock() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
117 self.emit('JUMP_IF_FALSE', else_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
118 self.emit('POP_TOP') |
30
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
119 |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
120 # hasattr returned True, so return the attribute value |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
121 self.emit('LOAD_NAME', 'obj') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
122 self.emit('LOAD_ATTR', node.attrname) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
123 self.emit('STORE_NAME', 'val') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
124 return_ = self.newBlock() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
125 self.emit('JUMP_FORWARD', return_) |
30
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
126 |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
127 # hasattr returned False, so try item access |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
128 self.startBlock(else_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
129 try_ = self.newBlock() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
130 except_ = self.newBlock() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
131 self.emit('SETUP_EXCEPT', except_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
132 self.nextBlock(try_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
133 self.setups.push((pycodegen.EXCEPT, try_)) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
134 self.emit('LOAD_NAME', 'obj') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
135 self.emit('LOAD_CONST', node.attrname) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
136 self.emit('BINARY_SUBSCR') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
137 self.emit('STORE_NAME', 'val') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
138 self.emit('POP_BLOCK') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
139 self.setups.pop() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
140 self.emit('JUMP_FORWARD', return_) |
30
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
141 |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
142 # exception handler: just return `None` |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
143 self.startBlock(except_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
144 self.emit('DUP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
145 self.emit('LOAD_GLOBAL', 'KeyError') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
146 self.emit('LOAD_GLOBAL', 'TypeError') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
147 self.emit('BUILD_TUPLE', 2) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
148 self.emit('COMPARE_OP', 'exception match') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
149 next = self.newBlock() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
150 self.emit('JUMP_IF_FALSE', next) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
151 self.nextBlock() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
152 self.emit('POP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
153 self.emit('POP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
154 self.emit('POP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
155 self.emit('POP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
156 self.emit('LOAD_CONST', None) # exception handler body |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
157 self.emit('STORE_NAME', 'val') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
158 self.emit('JUMP_FORWARD', return_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
159 self.nextBlock(next) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
160 self.emit('POP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
161 self.emit('END_FINALLY') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
162 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
163 # return |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
164 self.nextBlock(return_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
165 self.emit('LOAD_NAME', 'val') |
30
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
166 |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
167 def visitName(self, node): |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
168 """Overridden to lookup names in the context data instead of in |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
169 locals/globals. |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
170 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
171 If a name is not found in the context data, we fall back to Python |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
172 builtins. |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
173 """ |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
174 next = self.newBlock() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
175 end = self.newBlock() |
30
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
176 |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
177 # default: lookup in context data |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
178 self.loadName('data') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
179 self.emit('LOAD_ATTR', 'get') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
180 self.emit('LOAD_CONST', node.name) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
181 self.emit('CALL_FUNCTION', 1) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
182 self.emit('STORE_NAME', 'val') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
183 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
184 # test whether the value "is None" |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
185 self.emit('LOAD_NAME', 'val') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
186 self.emit('LOAD_CONST', None) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
187 self.emit('COMPARE_OP', 'is') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
188 self.emit('JUMP_IF_FALSE', next) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
189 self.emit('POP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
190 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
191 # if it is, fallback to builtins |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
192 self.emit('LOAD_GLOBAL', 'getattr') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
193 self.emit('LOAD_GLOBAL', '__builtin__') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
194 self.emit('LOAD_CONST', node.name) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
195 self.emit('LOAD_CONST', None) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
196 self.emit('CALL_FUNCTION', 3) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
197 self.emit('STORE_NAME', 'val') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
198 self.emit('JUMP_FORWARD', end) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
199 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
200 self.nextBlock(next) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
201 self.emit('POP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
202 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
203 self.nextBlock(end) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
204 self.emit('LOAD_NAME', 'val') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
205 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
206 def visitSubscript(self, node, aug_flag=None): |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
207 """Overridden to fallback to attribute access if the object doesn't |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
208 have an item (or doesn't even support item access). |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
209 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
210 If either method fails, this returns `None` instead of raising an |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
211 `IndexError`, `KeyError`, or `TypeError`. |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
212 """ |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
213 self.visit(node.expr) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
214 self.emit('STORE_NAME', 'obj') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
215 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
216 if len(node.subs) > 1: |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
217 # For non-scalar subscripts, use the default method |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
218 # FIXME: this should catch exceptions |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
219 self.emit('LOAD_NAME', 'obj') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
220 for sub in node.subs: |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
221 self.visit(sub) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
222 self.emit('BUILD_TUPLE', len(node.subs)) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
223 self.emit('BINARY_SUBSCR') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
224 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
225 else: |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
226 # For a scalar subscript, fallback to attribute access |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
227 # FIXME: Would be nice if we could limit this to string subscripts |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
228 try_ = self.newBlock() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
229 except_ = self.newBlock() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
230 return_ = self.newBlock() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
231 self.emit('SETUP_EXCEPT', except_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
232 self.nextBlock(try_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
233 self.setups.push((pycodegen.EXCEPT, try_)) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
234 self.emit('LOAD_NAME', 'obj') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
235 self.visit(node.subs[0]) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
236 self.emit('BINARY_SUBSCR') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
237 self.emit('STORE_NAME', 'val') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
238 self.emit('POP_BLOCK') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
239 self.setups.pop() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
240 self.emit('JUMP_FORWARD', return_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
241 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
242 self.startBlock(except_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
243 self.emit('DUP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
244 self.emit('LOAD_GLOBAL', 'KeyError') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
245 self.emit('LOAD_GLOBAL', 'IndexError') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
246 self.emit('LOAD_GLOBAL', 'TypeError') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
247 self.emit('BUILD_TUPLE', 3) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
248 self.emit('COMPARE_OP', 'exception match') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
249 next = self.newBlock() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
250 self.emit('JUMP_IF_FALSE', next) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
251 self.nextBlock() |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
252 self.emit('POP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
253 self.emit('POP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
254 self.emit('POP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
255 self.emit('POP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
256 self.emit('LOAD_GLOBAL', 'getattr') # exception handler body |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
257 self.emit('LOAD_NAME', 'obj') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
258 self.visit(node.subs[0]) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
259 self.emit('LOAD_CONST', None) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
260 self.emit('CALL_FUNCTION', 3) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
261 self.emit('STORE_NAME', 'val') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
262 self.emit('JUMP_FORWARD', return_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
263 self.nextBlock(next) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
264 self.emit('POP_TOP') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
265 self.emit('END_FINALLY') |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
266 |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
267 # return |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
268 self.nextBlock(return_) |
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
269 self.emit('LOAD_NAME', 'val') |