Mercurial > genshi > genshi-test
annotate markup/eval.py @ 86:5d98c4259d68
Accidentially left some doctests disabled.
author | cmlenz |
---|---|
date | Mon, 17 Jul 2006 09:01:08 +0000 |
parents | c82c002d4c32 |
children | c6f07b7cd3ea |
rev | line source |
---|---|
1 | 1 # -*- coding: utf-8 -*- |
2 # | |
66
822089ae65ce
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
822089ae65ce
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
822089ae65ce
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
cc034182061e
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
cc034182061e
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' | |
86 | 45 |
1 | 46 This also works the other way around: item access can be used to access |
47 any object attribute (meaning there's no use for `getattr()` in templates): | |
48 | |
49 >>> class MyClass(object): | |
50 ... myattr = 'Bar' | |
51 >>> data = dict(mine=MyClass(), key='myattr') | |
52 >>> Expression('mine.myattr').evaluate(data) | |
53 'Bar' | |
54 >>> Expression('mine["myattr"]').evaluate(data) | |
55 'Bar' | |
56 >>> Expression('mine[key]').evaluate(data) | |
57 'Bar' | |
58 | |
31 | 59 All of the standard Python operators are available to template expressions. |
1 | 60 Built-in functions such as `len()` are also available in template |
61 expressions: | |
62 | |
63 >>> data = dict(items=[1, 2, 3]) | |
64 >>> Expression('len(items)').evaluate(data) | |
65 3 | |
66 """ | |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
67 __slots__ = ['source', 'code'] |
69 | 68 _visitors = {} |
1 | 69 |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
70 def __init__(self, source, filename=None, lineno=-1): |
27 | 71 """Create the expression. |
72 | |
73 @param source: the expression as string | |
74 """ | |
1 | 75 self.source = source |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
76 |
86 | 77 ast = parse(self.source, 'eval') |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
78 if isinstance(filename, unicode): |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
79 # pycodegen doesn't like unicode in the filename |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
80 filename = filename.encode('utf-8', 'replace') |
86 | 81 ast.filename = filename or '<string>' |
82 gen = TemplateExpressionCodeGenerator(ast) | |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
83 if lineno >= 0: |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
84 gen.emit('SET_LINENO', lineno) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
85 self.code = gen.getCode() |
1 | 86 |
87 def __repr__(self): | |
88 return '<Expression "%s">' % self.source | |
89 | |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
90 def evaluate(self, data): |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
91 """Evaluate the expression against the given data dictionary. |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
92 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
93 @param data: a mapping containing the data to evaluate against |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
94 @return: the result of the evaluation |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
95 """ |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
96 return eval(self.code) |
30
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
97 |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
98 |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
99 class TemplateExpressionCodeGenerator(pycodegen.ExpressionCodeGenerator): |
30
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
100 |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
101 def visitGetattr(self, node): |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
102 """Overridden to fallback to item access if the object doesn't have an |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
103 attribute. |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
104 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
105 Also, if either method fails, this returns `None` instead of raising an |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
106 `AttributeError`. |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
107 """ |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
108 # check whether the object has the request attribute |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
109 self.visit(node.expr) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
110 self.emit('STORE_NAME', 'obj') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
111 self.emit('LOAD_GLOBAL', 'hasattr') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
112 self.emit('LOAD_NAME', 'obj') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
113 self.emit('LOAD_CONST', node.attrname) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
114 self.emit('CALL_FUNCTION', 2) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
115 else_ = self.newBlock() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
116 self.emit('JUMP_IF_FALSE', else_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
117 self.emit('POP_TOP') |
30
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
118 |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
119 # hasattr returned True, so return the attribute value |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
120 self.emit('LOAD_NAME', 'obj') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
121 self.emit('LOAD_ATTR', node.attrname) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
122 self.emit('STORE_NAME', 'val') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
123 return_ = self.newBlock() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
124 self.emit('JUMP_FORWARD', return_) |
30
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
125 |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
126 # hasattr returned False, so try item access |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
127 self.startBlock(else_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
128 try_ = self.newBlock() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
129 except_ = self.newBlock() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
130 self.emit('SETUP_EXCEPT', except_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
131 self.nextBlock(try_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
132 self.setups.push((pycodegen.EXCEPT, try_)) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
133 self.emit('LOAD_NAME', 'obj') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
134 self.emit('LOAD_CONST', node.attrname) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
135 self.emit('BINARY_SUBSCR') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
136 self.emit('STORE_NAME', 'val') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
137 self.emit('POP_BLOCK') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
138 self.setups.pop() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
139 self.emit('JUMP_FORWARD', return_) |
30
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
140 |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
141 # exception handler: just return `None` |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
142 self.startBlock(except_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
143 self.emit('DUP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
144 self.emit('LOAD_GLOBAL', 'KeyError') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
145 self.emit('LOAD_GLOBAL', 'TypeError') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
146 self.emit('BUILD_TUPLE', 2) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
147 self.emit('COMPARE_OP', 'exception match') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
148 next = self.newBlock() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
149 self.emit('JUMP_IF_FALSE', next) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
150 self.nextBlock() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
151 self.emit('POP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
152 self.emit('POP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
153 self.emit('POP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
154 self.emit('POP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
155 self.emit('LOAD_CONST', None) # exception handler body |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
156 self.emit('STORE_NAME', 'val') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
157 self.emit('JUMP_FORWARD', return_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
158 self.nextBlock(next) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
159 self.emit('POP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
160 self.emit('END_FINALLY') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
161 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
162 # return |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
163 self.nextBlock(return_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
164 self.emit('LOAD_NAME', 'val') |
30
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
165 |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
166 def visitName(self, node): |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
167 """Overridden to lookup names in the context data instead of in |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
168 locals/globals. |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
169 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
170 If a name is not found in the context data, we fall back to Python |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
171 builtins. |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
172 """ |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
173 next = self.newBlock() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
174 end = self.newBlock() |
30
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
175 |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
176 # default: lookup in context data |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
177 self.loadName('data') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
178 self.emit('LOAD_ATTR', 'get') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
179 self.emit('LOAD_CONST', node.name) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
180 self.emit('CALL_FUNCTION', 1) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
181 self.emit('STORE_NAME', 'val') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
182 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
183 # test whether the value "is None" |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
184 self.emit('LOAD_NAME', 'val') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
185 self.emit('LOAD_CONST', None) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
186 self.emit('COMPARE_OP', 'is') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
187 self.emit('JUMP_IF_FALSE', next) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
188 self.emit('POP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
189 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
190 # if it is, fallback to builtins |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
191 self.emit('LOAD_GLOBAL', 'getattr') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
192 self.emit('LOAD_GLOBAL', '__builtin__') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
193 self.emit('LOAD_CONST', node.name) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
194 self.emit('LOAD_CONST', None) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
195 self.emit('CALL_FUNCTION', 3) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
196 self.emit('STORE_NAME', 'val') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
197 self.emit('JUMP_FORWARD', end) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
198 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
199 self.nextBlock(next) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
200 self.emit('POP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
201 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
202 self.nextBlock(end) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
203 self.emit('LOAD_NAME', 'val') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
204 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
205 def visitSubscript(self, node, aug_flag=None): |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
206 """Overridden to fallback to attribute access if the object doesn't |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
207 have an item (or doesn't even support item access). |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
208 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
209 If either method fails, this returns `None` instead of raising an |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
210 `IndexError`, `KeyError`, or `TypeError`. |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
211 """ |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
212 self.visit(node.expr) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
213 self.emit('STORE_NAME', 'obj') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
214 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
215 if len(node.subs) > 1: |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
216 # For non-scalar subscripts, use the default method |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
217 # FIXME: this should catch exceptions |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
218 self.emit('LOAD_NAME', 'obj') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
219 for sub in node.subs: |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
220 self.visit(sub) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
221 self.emit('BUILD_TUPLE', len(node.subs)) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
222 self.emit('BINARY_SUBSCR') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
223 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
224 else: |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
225 # For a scalar subscript, fallback to attribute access |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
226 # FIXME: Would be nice if we could limit this to string subscripts |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
227 try_ = self.newBlock() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
228 except_ = self.newBlock() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
229 return_ = self.newBlock() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
230 self.emit('SETUP_EXCEPT', except_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
231 self.nextBlock(try_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
232 self.setups.push((pycodegen.EXCEPT, try_)) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
233 self.emit('LOAD_NAME', 'obj') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
234 self.visit(node.subs[0]) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
235 self.emit('BINARY_SUBSCR') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
236 self.emit('STORE_NAME', 'val') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
237 self.emit('POP_BLOCK') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
238 self.setups.pop() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
239 self.emit('JUMP_FORWARD', return_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
240 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
241 self.startBlock(except_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
242 self.emit('DUP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
243 self.emit('LOAD_GLOBAL', 'KeyError') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
244 self.emit('LOAD_GLOBAL', 'IndexError') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
245 self.emit('LOAD_GLOBAL', 'TypeError') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
246 self.emit('BUILD_TUPLE', 3) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
247 self.emit('COMPARE_OP', 'exception match') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
248 next = self.newBlock() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
249 self.emit('JUMP_IF_FALSE', next) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
250 self.nextBlock() |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
251 self.emit('POP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
252 self.emit('POP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
253 self.emit('POP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
254 self.emit('POP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
255 self.emit('LOAD_GLOBAL', 'getattr') # exception handler body |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
256 self.emit('LOAD_NAME', 'obj') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
257 self.visit(node.subs[0]) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
258 self.emit('LOAD_CONST', None) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
259 self.emit('CALL_FUNCTION', 3) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
260 self.emit('STORE_NAME', 'val') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
261 self.emit('JUMP_FORWARD', return_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
262 self.nextBlock(next) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
263 self.emit('POP_TOP') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
264 self.emit('END_FINALLY') |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
265 |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
266 # return |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
267 self.nextBlock(return_) |
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
69
diff
changeset
|
268 self.emit('LOAD_NAME', 'val') |