Mercurial > genshi > genshi-test
annotate markup/tests/eval.py @ 180:194025141c89
String literals in XPath expressions are assumed to be UTF-8 encoded.
author | cmlenz |
---|---|
date | Mon, 21 Aug 2006 19:25:29 +0000 |
parents | 7888f4104cc0 |
children | cda3bdfc19ed |
rev | line source |
---|---|
1 | 1 # -*- coding: utf-8 -*- |
2 # | |
66
822089ae65ce
Switch copyright to Edgewall and URLs to markup.edgewall.org.
cmlenz
parents:
32
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:
32
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:
32
diff
changeset
|
12 # history and logs, available at hhttp://markup.edgewall.org/log/. |
1 | 13 |
14 import doctest | |
131
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
15 import sys |
1 | 16 import unittest |
17 | |
27 | 18 from markup.eval import Expression |
1 | 19 |
30
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
20 |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
21 class ExpressionTestCase(unittest.TestCase): |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
22 |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
23 def test_str_literal(self): |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
24 self.assertEqual('foo', Expression('"foo"').evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
25 self.assertEqual('foo', Expression('"""foo"""').evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
26 self.assertEqual('foo', Expression("'foo'").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
27 self.assertEqual('foo', Expression("'''foo'''").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
28 self.assertEqual('foo', Expression("u'foo'").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
29 self.assertEqual('foo', Expression("r'foo'").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
30 |
167
7888f4104cc0
Handle non-ASCII characters in expressions. Closes #29. Thanks to Arnar Birgisson for reporting the problem and comping up with a patch!
cmlenz
parents:
134
diff
changeset
|
31 def test_str_literal_non_ascii(self): |
7888f4104cc0
Handle non-ASCII characters in expressions. Closes #29. Thanks to Arnar Birgisson for reporting the problem and comping up with a patch!
cmlenz
parents:
134
diff
changeset
|
32 expr = Expression(u"u'\xfe'") |
7888f4104cc0
Handle non-ASCII characters in expressions. Closes #29. Thanks to Arnar Birgisson for reporting the problem and comping up with a patch!
cmlenz
parents:
134
diff
changeset
|
33 self.assertEqual(u'þ', expr.evaluate({})) |
7888f4104cc0
Handle non-ASCII characters in expressions. Closes #29. Thanks to Arnar Birgisson for reporting the problem and comping up with a patch!
cmlenz
parents:
134
diff
changeset
|
34 expr = Expression("u'\xfe'") |
7888f4104cc0
Handle non-ASCII characters in expressions. Closes #29. Thanks to Arnar Birgisson for reporting the problem and comping up with a patch!
cmlenz
parents:
134
diff
changeset
|
35 self.assertEqual(u'þ', expr.evaluate({})) |
180
194025141c89
String literals in XPath expressions are assumed to be UTF-8 encoded.
cmlenz
parents:
167
diff
changeset
|
36 expr = Expression("'\xc3\xbe'") |
194025141c89
String literals in XPath expressions are assumed to be UTF-8 encoded.
cmlenz
parents:
167
diff
changeset
|
37 self.assertEqual(u'þ', expr.evaluate({})) |
167
7888f4104cc0
Handle non-ASCII characters in expressions. Closes #29. Thanks to Arnar Birgisson for reporting the problem and comping up with a patch!
cmlenz
parents:
134
diff
changeset
|
38 |
30
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
39 def test_num_literal(self): |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
40 self.assertEqual(42, Expression("42").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
41 self.assertEqual(42L, Expression("42L").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
42 self.assertEqual(.42, Expression(".42").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
43 self.assertEqual(07, Expression("07").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
44 self.assertEqual(0xF2, Expression("0xF2").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
45 self.assertEqual(0XF2, Expression("0XF2").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
46 |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
47 def test_dict_literal(self): |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
48 self.assertEqual({}, Expression("{}").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
49 self.assertEqual({'key': True}, |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
50 Expression("{'key': value}").evaluate({'value': True})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
51 |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
52 def test_list_literal(self): |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
53 self.assertEqual([], Expression("[]").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
54 self.assertEqual([1, 2, 3], Expression("[1, 2, 3]").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
55 self.assertEqual([True], |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
56 Expression("[value]").evaluate({'value': True})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
57 |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
58 def test_tuple_literal(self): |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
59 self.assertEqual((), Expression("()").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
60 self.assertEqual((1, 2, 3), Expression("(1, 2, 3)").evaluate({})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
61 self.assertEqual((True,), |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
62 Expression("(value,)").evaluate({'value': True})) |
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
63 |
31 | 64 def test_unaryop_pos(self): |
65 self.assertEqual(1, Expression("+1").evaluate({})) | |
66 self.assertEqual(1, Expression("+x").evaluate({'x': 1})) | |
67 | |
68 def test_unaryop_neg(self): | |
69 self.assertEqual(-1, Expression("-1").evaluate({})) | |
70 self.assertEqual(-1, Expression("-x").evaluate({'x': 1})) | |
71 | |
72 def test_unaryop_not(self): | |
73 self.assertEqual(False, Expression("not True").evaluate({})) | |
74 self.assertEqual(False, Expression("not x").evaluate({'x': True})) | |
75 | |
32 | 76 def test_unaryop_inv(self): |
77 self.assertEqual(-2, Expression("~1").evaluate({})) | |
78 self.assertEqual(-2, Expression("~x").evaluate({'x': 1})) | |
79 | |
31 | 80 def test_binop_add(self): |
81 self.assertEqual(3, Expression("2 + 1").evaluate({})) | |
82 self.assertEqual(3, Expression("x + y").evaluate({'x': 2, 'y': 1})) | |
83 | |
84 def test_binop_sub(self): | |
85 self.assertEqual(1, Expression("2 - 1").evaluate({})) | |
86 self.assertEqual(1, Expression("x - y").evaluate({'x': 1, 'y': 1})) | |
87 | |
88 def test_binop_sub(self): | |
89 self.assertEqual(1, Expression("2 - 1").evaluate({})) | |
90 self.assertEqual(1, Expression("x - y").evaluate({'x': 2, 'y': 1})) | |
91 | |
92 def test_binop_mul(self): | |
93 self.assertEqual(4, Expression("2 * 2").evaluate({})) | |
94 self.assertEqual(4, Expression("x * y").evaluate({'x': 2, 'y': 2})) | |
95 | |
96 def test_binop_pow(self): | |
97 self.assertEqual(4, Expression("2 ** 2").evaluate({})) | |
98 self.assertEqual(4, Expression("x ** y").evaluate({'x': 2, 'y': 2})) | |
99 | |
100 def test_binop_div(self): | |
101 self.assertEqual(2, Expression("4 / 2").evaluate({})) | |
102 self.assertEqual(2, Expression("x / y").evaluate({'x': 4, 'y': 2})) | |
103 | |
104 def test_binop_floordiv(self): | |
105 self.assertEqual(1, Expression("3 // 2").evaluate({})) | |
106 self.assertEqual(1, Expression("x // y").evaluate({'x': 3, 'y': 2})) | |
107 | |
108 def test_binop_mod(self): | |
109 self.assertEqual(1, Expression("3 % 2").evaluate({})) | |
110 self.assertEqual(1, Expression("x % y").evaluate({'x': 3, 'y': 2})) | |
111 | |
32 | 112 def test_binop_and(self): |
113 self.assertEqual(0, Expression("1 & 0").evaluate({})) | |
114 self.assertEqual(0, Expression("x & y").evaluate({'x': 1, 'y': 0})) | |
115 | |
116 def test_binop_or(self): | |
117 self.assertEqual(1, Expression("1 | 0").evaluate({})) | |
118 self.assertEqual(1, Expression("x | y").evaluate({'x': 1, 'y': 0})) | |
119 | |
31 | 120 def test_binop_contains(self): |
121 self.assertEqual(True, Expression("1 in (1, 2, 3)").evaluate({})) | |
122 self.assertEqual(True, Expression("x in y").evaluate({'x': 1, | |
123 'y': (1, 2, 3)})) | |
124 | |
125 def test_binop_not_contains(self): | |
126 self.assertEqual(True, Expression("4 not in (1, 2, 3)").evaluate({})) | |
127 self.assertEqual(True, Expression("x not in y").evaluate({'x': 4, | |
128 'y': (1, 2, 3)})) | |
129 | |
32 | 130 def test_binop_is(self): |
131 self.assertEqual(True, Expression("1 is 1").evaluate({})) | |
132 self.assertEqual(True, Expression("x is y").evaluate({'x': 1, 'y': 1})) | |
133 self.assertEqual(False, Expression("1 is 2").evaluate({})) | |
134 self.assertEqual(False, Expression("x is y").evaluate({'x': 1, 'y': 2})) | |
135 | |
136 def test_binop_is_not(self): | |
137 self.assertEqual(True, Expression("1 is not 2").evaluate({})) | |
138 self.assertEqual(True, Expression("x is not y").evaluate({'x': 1, | |
139 'y': 2})) | |
140 self.assertEqual(False, Expression("1 is not 1").evaluate({})) | |
141 self.assertEqual(False, Expression("x is not y").evaluate({'x': 1, | |
142 'y': 1})) | |
143 | |
31 | 144 def test_boolop_and(self): |
145 self.assertEqual(False, Expression("True and False").evaluate({})) | |
146 self.assertEqual(False, Expression("x and y").evaluate({'x': True, | |
147 'y': False})) | |
148 | |
149 def test_boolop_or(self): | |
150 self.assertEqual(True, Expression("True or False").evaluate({})) | |
151 self.assertEqual(True, Expression("x or y").evaluate({'x': True, | |
152 'y': False})) | |
153 | |
154 def test_compare_eq(self): | |
155 self.assertEqual(True, Expression("1 == 1").evaluate({})) | |
156 self.assertEqual(True, Expression("x == y").evaluate({'x': 1, 'y': 1})) | |
157 | |
158 def test_compare_ne(self): | |
159 self.assertEqual(False, Expression("1 != 1").evaluate({})) | |
160 self.assertEqual(False, Expression("x != y").evaluate({'x': 1, 'y': 1})) | |
32 | 161 self.assertEqual(False, Expression("1 <> 1").evaluate({})) |
162 self.assertEqual(False, Expression("x <> y").evaluate({'x': 1, 'y': 1})) | |
31 | 163 |
164 def test_compare_lt(self): | |
165 self.assertEqual(True, Expression("1 < 2").evaluate({})) | |
166 self.assertEqual(True, Expression("x < y").evaluate({'x': 1, 'y': 2})) | |
167 | |
168 def test_compare_le(self): | |
169 self.assertEqual(True, Expression("1 <= 1").evaluate({})) | |
170 self.assertEqual(True, Expression("x <= y").evaluate({'x': 1, 'y': 1})) | |
171 | |
172 def test_compare_gt(self): | |
173 self.assertEqual(True, Expression("2 > 1").evaluate({})) | |
174 self.assertEqual(True, Expression("x > y").evaluate({'x': 2, 'y': 1})) | |
175 | |
176 def test_compare_ge(self): | |
177 self.assertEqual(True, Expression("1 >= 1").evaluate({})) | |
178 self.assertEqual(True, Expression("x >= y").evaluate({'x': 1, 'y': 1})) | |
179 | |
180 def test_compare_multi(self): | |
181 self.assertEqual(True, Expression("1 != 3 == 3").evaluate({})) | |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
66
diff
changeset
|
182 self.assertEqual(True, Expression("x != y == y").evaluate({'x': 1, |
31 | 183 'y': 3})) |
184 | |
87
c6f07b7cd3ea
Fix some problems in expression evaluation by transforming the AST and compiling that to bytecode, instead of generating bytecode directly. Invalidates #13.
cmlenz
parents:
81
diff
changeset
|
185 def test_call_function(self): |
c6f07b7cd3ea
Fix some problems in expression evaluation by transforming the AST and compiling that to bytecode, instead of generating bytecode directly. Invalidates #13.
cmlenz
parents:
81
diff
changeset
|
186 self.assertEqual(42, Expression("foo()").evaluate({'foo': lambda: 42})) |
c6f07b7cd3ea
Fix some problems in expression evaluation by transforming the AST and compiling that to bytecode, instead of generating bytecode directly. Invalidates #13.
cmlenz
parents:
81
diff
changeset
|
187 data = {'foo': 'bar'} |
c6f07b7cd3ea
Fix some problems in expression evaluation by transforming the AST and compiling that to bytecode, instead of generating bytecode directly. Invalidates #13.
cmlenz
parents:
81
diff
changeset
|
188 self.assertEqual('BAR', Expression("foo.upper()").evaluate(data)) |
c6f07b7cd3ea
Fix some problems in expression evaluation by transforming the AST and compiling that to bytecode, instead of generating bytecode directly. Invalidates #13.
cmlenz
parents:
81
diff
changeset
|
189 data = {'foo': {'bar': range(42)}} |
c6f07b7cd3ea
Fix some problems in expression evaluation by transforming the AST and compiling that to bytecode, instead of generating bytecode directly. Invalidates #13.
cmlenz
parents:
81
diff
changeset
|
190 self.assertEqual(42, Expression("len(foo.bar)").evaluate(data)) |
c6f07b7cd3ea
Fix some problems in expression evaluation by transforming the AST and compiling that to bytecode, instead of generating bytecode directly. Invalidates #13.
cmlenz
parents:
81
diff
changeset
|
191 |
102 | 192 def test_call_keywords(self): |
193 self.assertEqual(42, Expression("foo(x=bar)").evaluate({'foo': lambda x: x, | |
194 'bar': 42})) | |
195 | |
90
242610137d1f
When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents:
88
diff
changeset
|
196 def test_call_function_without_params(self): |
242610137d1f
When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents:
88
diff
changeset
|
197 self.assertEqual(42, Expression("foo").evaluate({'foo': lambda: 42})) |
242610137d1f
When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents:
88
diff
changeset
|
198 data = {'foo': 'bar'} |
242610137d1f
When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents:
88
diff
changeset
|
199 self.assertEqual('BAR', Expression("foo.upper").evaluate(data)) |
242610137d1f
When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents:
88
diff
changeset
|
200 data = {'foo': {'bar': range(42)}} |
242610137d1f
When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents:
88
diff
changeset
|
201 |
118
226613431921
Add basic support for using `lambda`s in expressions. Closes #21. (Not sure about default arguments, need a test case).
cmlenz
parents:
102
diff
changeset
|
202 def test_lambda(self): |
226613431921
Add basic support for using `lambda`s in expressions. Closes #21. (Not sure about default arguments, need a test case).
cmlenz
parents:
102
diff
changeset
|
203 # Define a custom `sorted` function cause the builtin isn't available |
226613431921
Add basic support for using `lambda`s in expressions. Closes #21. (Not sure about default arguments, need a test case).
cmlenz
parents:
102
diff
changeset
|
204 # on Python 2.3 |
226613431921
Add basic support for using `lambda`s in expressions. Closes #21. (Not sure about default arguments, need a test case).
cmlenz
parents:
102
diff
changeset
|
205 def sorted(items, compfunc): |
226613431921
Add basic support for using `lambda`s in expressions. Closes #21. (Not sure about default arguments, need a test case).
cmlenz
parents:
102
diff
changeset
|
206 items.sort(compfunc) |
226613431921
Add basic support for using `lambda`s in expressions. Closes #21. (Not sure about default arguments, need a test case).
cmlenz
parents:
102
diff
changeset
|
207 return items |
226613431921
Add basic support for using `lambda`s in expressions. Closes #21. (Not sure about default arguments, need a test case).
cmlenz
parents:
102
diff
changeset
|
208 data = {'items': [{'name': 'b', 'value': 0}, {'name': 'a', 'value': 1}], |
226613431921
Add basic support for using `lambda`s in expressions. Closes #21. (Not sure about default arguments, need a test case).
cmlenz
parents:
102
diff
changeset
|
209 'sorted': sorted} |
226613431921
Add basic support for using `lambda`s in expressions. Closes #21. (Not sure about default arguments, need a test case).
cmlenz
parents:
102
diff
changeset
|
210 expr = Expression("sorted(items, lambda a, b: cmp(a.name, b.name))") |
226613431921
Add basic support for using `lambda`s in expressions. Closes #21. (Not sure about default arguments, need a test case).
cmlenz
parents:
102
diff
changeset
|
211 self.assertEqual([{'name': 'a', 'value': 1}, {'name': 'b', 'value': 0}], |
226613431921
Add basic support for using `lambda`s in expressions. Closes #21. (Not sure about default arguments, need a test case).
cmlenz
parents:
102
diff
changeset
|
212 expr.evaluate(data)) |
226613431921
Add basic support for using `lambda`s in expressions. Closes #21. (Not sure about default arguments, need a test case).
cmlenz
parents:
102
diff
changeset
|
213 |
88
9ecae580dd93
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
214 def test_list_comprehension(self): |
9ecae580dd93
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
215 expr = Expression("[n for n in numbers if n < 2]") |
9ecae580dd93
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
216 self.assertEqual([0, 1], expr.evaluate({'numbers': range(5)})) |
9ecae580dd93
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
217 |
9ecae580dd93
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
218 expr = Expression("[(i, n + 1) for i, n in enumerate(numbers)]") |
9ecae580dd93
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
219 self.assertEqual([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)], |
9ecae580dd93
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
220 expr.evaluate({'numbers': range(5)})) |
9ecae580dd93
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
221 |
9ecae580dd93
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
222 expr = Expression("[offset + n for n in numbers]") |
9ecae580dd93
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
223 self.assertEqual([2, 3, 4, 5, 6], |
9ecae580dd93
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
224 expr.evaluate({'numbers': range(5), 'offset': 2})) |
81
cc034182061e
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
66
diff
changeset
|
225 |
131
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
226 def test_list_comprehension_with_getattr(self): |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
227 items = [{'name': 'a', 'value': 1}, {'name': 'b', 'value': 2}] |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
228 expr = Expression("[i.name for i in items if i.value > 1]") |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
229 self.assertEqual(['b'], expr.evaluate({'items': items})) |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
230 |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
231 def test_list_comprehension_with_getitem(self): |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
232 items = [{'name': 'a', 'value': 1}, {'name': 'b', 'value': 2}] |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
233 expr = Expression("[i['name'] for i in items if i['value'] > 1]") |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
234 self.assertEqual(['b'], expr.evaluate({'items': items})) |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
235 |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
236 def test_error_position(self): |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
237 expr = Expression("nothing()", filename='index.html', lineno=50) |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
238 try: |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
239 expr.evaluate({}) |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
240 self.fail('Expected TypeError') |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
241 except TypeError, e: |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
242 exc_type, exc_value, exc_traceback = sys.exc_info() |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
243 frame = exc_traceback.tb_next |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
244 while frame.tb_next: |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
245 frame = frame.tb_next |
134
df44110ca91d
* Improve the accuracy of line numbers for text nodes, so that reported errors about syntax or evaluation errors in expressions point to the right line (not quite perfect yet, though).
cmlenz
parents:
131
diff
changeset
|
246 self.assertEqual('<Expression "nothing()">', |
df44110ca91d
* Improve the accuracy of line numbers for text nodes, so that reported errors about syntax or evaluation errors in expressions point to the right line (not quite perfect yet, though).
cmlenz
parents:
131
diff
changeset
|
247 frame.tb_frame.f_code.co_name) |
131
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
248 self.assertEqual('index.html', frame.tb_frame.f_code.co_filename) |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
249 self.assertEqual(50, frame.tb_lineno) |
203f459e7e26
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
250 |
30
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
251 |
1 | 252 def suite(): |
253 suite = unittest.TestSuite() | |
30
2ee9f28e16e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
254 suite.addTest(unittest.makeSuite(ExpressionTestCase, 'test')) |
27 | 255 suite.addTest(doctest.DocTestSuite(Expression.__module__)) |
1 | 256 return suite |
257 | |
258 if __name__ == '__main__': | |
259 unittest.main(defaultTest='suite') |