Mercurial > genshi > mirror
annotate markup/tests/eval.py @ 167:1999291f7a30 trunk
Handle non-ASCII characters in expressions. Closes #29. Thanks to Arnar Birgisson for reporting the problem and comping up with a patch!
author | cmlenz |
---|---|
date | Thu, 17 Aug 2006 15:22:12 +0000 |
parents | d681d2c3cd8d |
children | 061491fb4ea8 |
rev | line source |
---|---|
1 | 1 # -*- coding: utf-8 -*- |
2 # | |
66
59eb24184e9c
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
59eb24184e9c
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
59eb24184e9c
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
2ad83f1d337c
* 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
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
20 |
bcdbb7e5e4e5
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): |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
22 |
bcdbb7e5e4e5
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): |
bcdbb7e5e4e5
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({})) |
bcdbb7e5e4e5
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({})) |
bcdbb7e5e4e5
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({})) |
bcdbb7e5e4e5
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({})) |
bcdbb7e5e4e5
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({})) |
bcdbb7e5e4e5
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({})) |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
30 |
167
1999291f7a30
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): |
1999291f7a30
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'") |
1999291f7a30
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({})) |
1999291f7a30
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'") |
1999291f7a30
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({})) |
1999291f7a30
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
|
36 |
30
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
37 def test_num_literal(self): |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
38 self.assertEqual(42, Expression("42").evaluate({})) |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
39 self.assertEqual(42L, Expression("42L").evaluate({})) |
bcdbb7e5e4e5
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({})) |
bcdbb7e5e4e5
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(07, Expression("07").evaluate({})) |
bcdbb7e5e4e5
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(0xF2, Expression("0xF2").evaluate({})) |
bcdbb7e5e4e5
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(0XF2, Expression("0XF2").evaluate({})) |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
44 |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
45 def test_dict_literal(self): |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
46 self.assertEqual({}, Expression("{}").evaluate({})) |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
47 self.assertEqual({'key': True}, |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
48 Expression("{'key': value}").evaluate({'value': True})) |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
49 |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
50 def test_list_literal(self): |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
51 self.assertEqual([], Expression("[]").evaluate({})) |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
52 self.assertEqual([1, 2, 3], Expression("[1, 2, 3]").evaluate({})) |
bcdbb7e5e4e5
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([True], |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
54 Expression("[value]").evaluate({'value': True})) |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
55 |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
56 def test_tuple_literal(self): |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
57 self.assertEqual((), Expression("()").evaluate({})) |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
58 self.assertEqual((1, 2, 3), Expression("(1, 2, 3)").evaluate({})) |
bcdbb7e5e4e5
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((True,), |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
60 Expression("(value,)").evaluate({'value': True})) |
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
61 |
31 | 62 def test_unaryop_pos(self): |
63 self.assertEqual(1, Expression("+1").evaluate({})) | |
64 self.assertEqual(1, Expression("+x").evaluate({'x': 1})) | |
65 | |
66 def test_unaryop_neg(self): | |
67 self.assertEqual(-1, Expression("-1").evaluate({})) | |
68 self.assertEqual(-1, Expression("-x").evaluate({'x': 1})) | |
69 | |
70 def test_unaryop_not(self): | |
71 self.assertEqual(False, Expression("not True").evaluate({})) | |
72 self.assertEqual(False, Expression("not x").evaluate({'x': True})) | |
73 | |
32 | 74 def test_unaryop_inv(self): |
75 self.assertEqual(-2, Expression("~1").evaluate({})) | |
76 self.assertEqual(-2, Expression("~x").evaluate({'x': 1})) | |
77 | |
31 | 78 def test_binop_add(self): |
79 self.assertEqual(3, Expression("2 + 1").evaluate({})) | |
80 self.assertEqual(3, Expression("x + y").evaluate({'x': 2, 'y': 1})) | |
81 | |
82 def test_binop_sub(self): | |
83 self.assertEqual(1, Expression("2 - 1").evaluate({})) | |
84 self.assertEqual(1, Expression("x - y").evaluate({'x': 1, 'y': 1})) | |
85 | |
86 def test_binop_sub(self): | |
87 self.assertEqual(1, Expression("2 - 1").evaluate({})) | |
88 self.assertEqual(1, Expression("x - y").evaluate({'x': 2, 'y': 1})) | |
89 | |
90 def test_binop_mul(self): | |
91 self.assertEqual(4, Expression("2 * 2").evaluate({})) | |
92 self.assertEqual(4, Expression("x * y").evaluate({'x': 2, 'y': 2})) | |
93 | |
94 def test_binop_pow(self): | |
95 self.assertEqual(4, Expression("2 ** 2").evaluate({})) | |
96 self.assertEqual(4, Expression("x ** y").evaluate({'x': 2, 'y': 2})) | |
97 | |
98 def test_binop_div(self): | |
99 self.assertEqual(2, Expression("4 / 2").evaluate({})) | |
100 self.assertEqual(2, Expression("x / y").evaluate({'x': 4, 'y': 2})) | |
101 | |
102 def test_binop_floordiv(self): | |
103 self.assertEqual(1, Expression("3 // 2").evaluate({})) | |
104 self.assertEqual(1, Expression("x // y").evaluate({'x': 3, 'y': 2})) | |
105 | |
106 def test_binop_mod(self): | |
107 self.assertEqual(1, Expression("3 % 2").evaluate({})) | |
108 self.assertEqual(1, Expression("x % y").evaluate({'x': 3, 'y': 2})) | |
109 | |
32 | 110 def test_binop_and(self): |
111 self.assertEqual(0, Expression("1 & 0").evaluate({})) | |
112 self.assertEqual(0, Expression("x & y").evaluate({'x': 1, 'y': 0})) | |
113 | |
114 def test_binop_or(self): | |
115 self.assertEqual(1, Expression("1 | 0").evaluate({})) | |
116 self.assertEqual(1, Expression("x | y").evaluate({'x': 1, 'y': 0})) | |
117 | |
31 | 118 def test_binop_contains(self): |
119 self.assertEqual(True, Expression("1 in (1, 2, 3)").evaluate({})) | |
120 self.assertEqual(True, Expression("x in y").evaluate({'x': 1, | |
121 'y': (1, 2, 3)})) | |
122 | |
123 def test_binop_not_contains(self): | |
124 self.assertEqual(True, Expression("4 not in (1, 2, 3)").evaluate({})) | |
125 self.assertEqual(True, Expression("x not in y").evaluate({'x': 4, | |
126 'y': (1, 2, 3)})) | |
127 | |
32 | 128 def test_binop_is(self): |
129 self.assertEqual(True, Expression("1 is 1").evaluate({})) | |
130 self.assertEqual(True, Expression("x is y").evaluate({'x': 1, 'y': 1})) | |
131 self.assertEqual(False, Expression("1 is 2").evaluate({})) | |
132 self.assertEqual(False, Expression("x is y").evaluate({'x': 1, 'y': 2})) | |
133 | |
134 def test_binop_is_not(self): | |
135 self.assertEqual(True, Expression("1 is not 2").evaluate({})) | |
136 self.assertEqual(True, Expression("x is not y").evaluate({'x': 1, | |
137 'y': 2})) | |
138 self.assertEqual(False, Expression("1 is not 1").evaluate({})) | |
139 self.assertEqual(False, Expression("x is not y").evaluate({'x': 1, | |
140 'y': 1})) | |
141 | |
31 | 142 def test_boolop_and(self): |
143 self.assertEqual(False, Expression("True and False").evaluate({})) | |
144 self.assertEqual(False, Expression("x and y").evaluate({'x': True, | |
145 'y': False})) | |
146 | |
147 def test_boolop_or(self): | |
148 self.assertEqual(True, Expression("True or False").evaluate({})) | |
149 self.assertEqual(True, Expression("x or y").evaluate({'x': True, | |
150 'y': False})) | |
151 | |
152 def test_compare_eq(self): | |
153 self.assertEqual(True, Expression("1 == 1").evaluate({})) | |
154 self.assertEqual(True, Expression("x == y").evaluate({'x': 1, 'y': 1})) | |
155 | |
156 def test_compare_ne(self): | |
157 self.assertEqual(False, Expression("1 != 1").evaluate({})) | |
158 self.assertEqual(False, Expression("x != y").evaluate({'x': 1, 'y': 1})) | |
32 | 159 self.assertEqual(False, Expression("1 <> 1").evaluate({})) |
160 self.assertEqual(False, Expression("x <> y").evaluate({'x': 1, 'y': 1})) | |
31 | 161 |
162 def test_compare_lt(self): | |
163 self.assertEqual(True, Expression("1 < 2").evaluate({})) | |
164 self.assertEqual(True, Expression("x < y").evaluate({'x': 1, 'y': 2})) | |
165 | |
166 def test_compare_le(self): | |
167 self.assertEqual(True, Expression("1 <= 1").evaluate({})) | |
168 self.assertEqual(True, Expression("x <= y").evaluate({'x': 1, 'y': 1})) | |
169 | |
170 def test_compare_gt(self): | |
171 self.assertEqual(True, Expression("2 > 1").evaluate({})) | |
172 self.assertEqual(True, Expression("x > y").evaluate({'x': 2, 'y': 1})) | |
173 | |
174 def test_compare_ge(self): | |
175 self.assertEqual(True, Expression("1 >= 1").evaluate({})) | |
176 self.assertEqual(True, Expression("x >= y").evaluate({'x': 1, 'y': 1})) | |
177 | |
178 def test_compare_multi(self): | |
179 self.assertEqual(True, Expression("1 != 3 == 3").evaluate({})) | |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
66
diff
changeset
|
180 self.assertEqual(True, Expression("x != y == y").evaluate({'x': 1, |
31 | 181 'y': 3})) |
182 | |
87
1b874f032bde
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
|
183 def test_call_function(self): |
1b874f032bde
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
|
184 self.assertEqual(42, Expression("foo()").evaluate({'foo': lambda: 42})) |
1b874f032bde
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 data = {'foo': 'bar'} |
1b874f032bde
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('BAR', Expression("foo.upper()").evaluate(data)) |
1b874f032bde
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': range(42)}} |
1b874f032bde
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(42, Expression("len(foo.bar)").evaluate(data)) |
1b874f032bde
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 |
102 | 190 def test_call_keywords(self): |
191 self.assertEqual(42, Expression("foo(x=bar)").evaluate({'foo': lambda x: x, | |
192 'bar': 42})) | |
193 | |
90
c835e81c50af
When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents:
88
diff
changeset
|
194 def test_call_function_without_params(self): |
c835e81c50af
When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents:
88
diff
changeset
|
195 self.assertEqual(42, Expression("foo").evaluate({'foo': lambda: 42})) |
c835e81c50af
When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents:
88
diff
changeset
|
196 data = {'foo': 'bar'} |
c835e81c50af
When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents:
88
diff
changeset
|
197 self.assertEqual('BAR', Expression("foo.upper").evaluate(data)) |
c835e81c50af
When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents:
88
diff
changeset
|
198 data = {'foo': {'bar': range(42)}} |
c835e81c50af
When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents:
88
diff
changeset
|
199 |
118
c392d38694d9
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
|
200 def test_lambda(self): |
c392d38694d9
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
|
201 # Define a custom `sorted` function cause the builtin isn't available |
c392d38694d9
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 # on Python 2.3 |
c392d38694d9
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 def sorted(items, compfunc): |
c392d38694d9
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 items.sort(compfunc) |
c392d38694d9
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 return items |
c392d38694d9
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 data = {'items': [{'name': 'b', 'value': 0}, {'name': 'a', 'value': 1}], |
c392d38694d9
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 'sorted': sorted} |
c392d38694d9
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 expr = Expression("sorted(items, lambda a, b: cmp(a.name, b.name))") |
c392d38694d9
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 self.assertEqual([{'name': 'a', 'value': 1}, {'name': 'b', 'value': 0}], |
c392d38694d9
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.evaluate(data)) |
c392d38694d9
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 |
88
628ba9ed39ef
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
212 def test_list_comprehension(self): |
628ba9ed39ef
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
213 expr = Expression("[n for n in numbers if n < 2]") |
628ba9ed39ef
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
214 self.assertEqual([0, 1], expr.evaluate({'numbers': range(5)})) |
628ba9ed39ef
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
215 |
628ba9ed39ef
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
216 expr = Expression("[(i, n + 1) for i, n in enumerate(numbers)]") |
628ba9ed39ef
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
217 self.assertEqual([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)], |
628ba9ed39ef
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
218 expr.evaluate({'numbers': range(5)})) |
628ba9ed39ef
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
219 |
628ba9ed39ef
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
220 expr = Expression("[offset + n for n in numbers]") |
628ba9ed39ef
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
221 self.assertEqual([2, 3, 4, 5, 6], |
628ba9ed39ef
Add support for list comprehension in expressions (see #12).
cmlenz
parents:
87
diff
changeset
|
222 expr.evaluate({'numbers': range(5), 'offset': 2})) |
81
d60486018004
Template expressions are now compiled to Python bytecode.
cmlenz
parents:
66
diff
changeset
|
223 |
131
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
224 def test_list_comprehension_with_getattr(self): |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
225 items = [{'name': 'a', 'value': 1}, {'name': 'b', 'value': 2}] |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
226 expr = Expression("[i.name for i in items if i.value > 1]") |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
227 self.assertEqual(['b'], expr.evaluate({'items': items})) |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
228 |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
229 def test_list_comprehension_with_getitem(self): |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
230 items = [{'name': 'a', 'value': 1}, {'name': 'b', 'value': 2}] |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
231 expr = Expression("[i['name'] for i in items if i['value'] > 1]") |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
232 self.assertEqual(['b'], expr.evaluate({'items': items})) |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
233 |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
234 def test_error_position(self): |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
235 expr = Expression("nothing()", filename='index.html', lineno=50) |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
236 try: |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
237 expr.evaluate({}) |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
238 self.fail('Expected TypeError') |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
239 except TypeError, e: |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
240 exc_type, exc_value, exc_traceback = sys.exc_info() |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
241 frame = exc_traceback.tb_next |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
242 while frame.tb_next: |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
243 frame = frame.tb_next |
134
d681d2c3cd8d
* 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
|
244 self.assertEqual('<Expression "nothing()">', |
d681d2c3cd8d
* 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
|
245 frame.tb_frame.f_code.co_name) |
131
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
246 self.assertEqual('index.html', frame.tb_frame.f_code.co_filename) |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
247 self.assertEqual(50, frame.tb_lineno) |
2ad83f1d337c
* Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents:
118
diff
changeset
|
248 |
30
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
249 |
1 | 250 def suite(): |
251 suite = unittest.TestSuite() | |
30
bcdbb7e5e4e5
Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents:
27
diff
changeset
|
252 suite.addTest(unittest.makeSuite(ExpressionTestCase, 'test')) |
27 | 253 suite.addTest(doctest.DocTestSuite(Expression.__module__)) |
1 | 254 return suite |
255 | |
256 if __name__ == '__main__': | |
257 unittest.main(defaultTest='suite') |