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