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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
4 # All rights reserved.
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
5 #
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
9 #
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
13
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
14 import doctest
131
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
15 import sys
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
16 import unittest
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
17
27
b8456279c444 * Fix the boilerplate in the Python source files.
cmlenz
parents: 1
diff changeset
18 from markup.eval import Expression
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
64 def test_unaryop_pos(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
65 self.assertEqual(1, Expression("+1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
66 self.assertEqual(1, Expression("+x").evaluate({'x': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
67
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
68 def test_unaryop_neg(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
69 self.assertEqual(-1, Expression("-1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
70 self.assertEqual(-1, Expression("-x").evaluate({'x': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
71
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
72 def test_unaryop_not(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
73 self.assertEqual(False, Expression("not True").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
74 self.assertEqual(False, Expression("not x").evaluate({'x': True}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
75
32
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
76 def test_unaryop_inv(self):
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
77 self.assertEqual(-2, Expression("~1").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
78 self.assertEqual(-2, Expression("~x").evaluate({'x': 1}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
79
31
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
80 def test_binop_add(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
81 self.assertEqual(3, Expression("2 + 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
82 self.assertEqual(3, Expression("x + y").evaluate({'x': 2, 'y': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
83
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
84 def test_binop_sub(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
85 self.assertEqual(1, Expression("2 - 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
86 self.assertEqual(1, Expression("x - y").evaluate({'x': 1, 'y': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
87
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
88 def test_binop_sub(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
89 self.assertEqual(1, Expression("2 - 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
90 self.assertEqual(1, Expression("x - y").evaluate({'x': 2, 'y': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
91
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
92 def test_binop_mul(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
93 self.assertEqual(4, Expression("2 * 2").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
94 self.assertEqual(4, Expression("x * y").evaluate({'x': 2, 'y': 2}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
95
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
96 def test_binop_pow(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
97 self.assertEqual(4, Expression("2 ** 2").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
98 self.assertEqual(4, Expression("x ** y").evaluate({'x': 2, 'y': 2}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
99
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
100 def test_binop_div(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
101 self.assertEqual(2, Expression("4 / 2").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
102 self.assertEqual(2, Expression("x / y").evaluate({'x': 4, 'y': 2}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
103
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
104 def test_binop_floordiv(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
105 self.assertEqual(1, Expression("3 // 2").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
106 self.assertEqual(1, Expression("x // y").evaluate({'x': 3, 'y': 2}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
107
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
108 def test_binop_mod(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
109 self.assertEqual(1, Expression("3 % 2").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
110 self.assertEqual(1, Expression("x % y").evaluate({'x': 3, 'y': 2}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
111
32
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
112 def test_binop_and(self):
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
113 self.assertEqual(0, Expression("1 & 0").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
114 self.assertEqual(0, Expression("x & y").evaluate({'x': 1, 'y': 0}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
115
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
116 def test_binop_or(self):
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
117 self.assertEqual(1, Expression("1 | 0").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
118 self.assertEqual(1, Expression("x | y").evaluate({'x': 1, 'y': 0}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
119
31
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
120 def test_binop_contains(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
121 self.assertEqual(True, Expression("1 in (1, 2, 3)").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
122 self.assertEqual(True, Expression("x in y").evaluate({'x': 1,
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
123 'y': (1, 2, 3)}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
124
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
125 def test_binop_not_contains(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
126 self.assertEqual(True, Expression("4 not in (1, 2, 3)").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
127 self.assertEqual(True, Expression("x not in y").evaluate({'x': 4,
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
128 'y': (1, 2, 3)}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
129
32
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
130 def test_binop_is(self):
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
131 self.assertEqual(True, Expression("1 is 1").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
132 self.assertEqual(True, Expression("x is y").evaluate({'x': 1, 'y': 1}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
133 self.assertEqual(False, Expression("1 is 2").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
134 self.assertEqual(False, Expression("x is y").evaluate({'x': 1, 'y': 2}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
135
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
136 def test_binop_is_not(self):
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
137 self.assertEqual(True, Expression("1 is not 2").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
138 self.assertEqual(True, Expression("x is not y").evaluate({'x': 1,
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
139 'y': 2}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
140 self.assertEqual(False, Expression("1 is not 1").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
141 self.assertEqual(False, Expression("x is not y").evaluate({'x': 1,
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
142 'y': 1}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
143
31
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
144 def test_boolop_and(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
145 self.assertEqual(False, Expression("True and False").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
146 self.assertEqual(False, Expression("x and y").evaluate({'x': True,
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
147 'y': False}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
148
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
149 def test_boolop_or(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
150 self.assertEqual(True, Expression("True or False").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
151 self.assertEqual(True, Expression("x or y").evaluate({'x': True,
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
152 'y': False}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
153
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
154 def test_compare_eq(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
155 self.assertEqual(True, Expression("1 == 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
156 self.assertEqual(True, Expression("x == y").evaluate({'x': 1, 'y': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
157
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
158 def test_compare_ne(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
159 self.assertEqual(False, Expression("1 != 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
160 self.assertEqual(False, Expression("x != y").evaluate({'x': 1, 'y': 1}))
32
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
161 self.assertEqual(False, Expression("1 <> 1").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
162 self.assertEqual(False, Expression("x <> y").evaluate({'x': 1, 'y': 1}))
31
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
163
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
164 def test_compare_lt(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
165 self.assertEqual(True, Expression("1 < 2").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
166 self.assertEqual(True, Expression("x < y").evaluate({'x': 1, 'y': 2}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
167
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
168 def test_compare_le(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
169 self.assertEqual(True, Expression("1 <= 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
170 self.assertEqual(True, Expression("x <= y").evaluate({'x': 1, 'y': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
171
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
172 def test_compare_gt(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
173 self.assertEqual(True, Expression("2 > 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
174 self.assertEqual(True, Expression("x > y").evaluate({'x': 2, 'y': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
175
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
176 def test_compare_ge(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
177 self.assertEqual(True, Expression("1 >= 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
178 self.assertEqual(True, Expression("x >= y").evaluate({'x': 1, 'y': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
179
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
180 def test_compare_multi(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
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
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
183 'y': 3}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
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
12efdfe8af47 Ported [118] to trunk
jonas
parents: 90
diff changeset
192 def test_call_keywords(self):
12efdfe8af47 Ported [118] to trunk
jonas
parents: 90
diff changeset
193 self.assertEqual(42, Expression("foo(x=bar)").evaluate({'foo': lambda x: x,
12efdfe8af47 Ported [118] to trunk
jonas
parents: 90
diff changeset
194 'bar': 42}))
12efdfe8af47 Ported [118] to trunk
jonas
parents: 90
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
252 def suite():
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
b8456279c444 * Fix the boilerplate in the Python source files.
cmlenz
parents: 1
diff changeset
255 suite.addTest(doctest.DocTestSuite(Expression.__module__))
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
256 return suite
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
257
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
258 if __name__ == '__main__':
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
259 unittest.main(defaultTest='suite')
Copyright (C) 2012-2017 Edgewall Software