annotate markup/tests/eval.py @ 131:203f459e7e26

* Support for line numbers in exceptions in expression evaluation (#22). * Fix bug in expression evaluation when item access was used inside a lambda or list comprehension. Thanks to Kevin Dangoor for reporting the problem.
author cmlenz
date Fri, 04 Aug 2006 13:07:52 +0000
parents 226613431921
children df44110ca91d
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
2ee9f28e16e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
31 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
32 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
33 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
34 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
35 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
36 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
37 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
38
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_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
40 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
41 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
42 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
43
2ee9f28e16e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
44 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
45 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
46 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
47 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
48 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
49
2ee9f28e16e5 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_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
51 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
52 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
53 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
54 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
55
31
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
56 def test_unaryop_pos(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
57 self.assertEqual(1, Expression("+1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
58 self.assertEqual(1, Expression("+x").evaluate({'x': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
59
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
60 def test_unaryop_neg(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
61 self.assertEqual(-1, Expression("-1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
62 self.assertEqual(-1, Expression("-x").evaluate({'x': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
63
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
64 def test_unaryop_not(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
65 self.assertEqual(False, Expression("not True").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
66 self.assertEqual(False, Expression("not x").evaluate({'x': True}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
67
32
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
68 def test_unaryop_inv(self):
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
69 self.assertEqual(-2, Expression("~1").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
70 self.assertEqual(-2, Expression("~x").evaluate({'x': 1}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
71
31
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
72 def test_binop_add(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
73 self.assertEqual(3, Expression("2 + 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
74 self.assertEqual(3, Expression("x + y").evaluate({'x': 2, 'y': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
75
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
76 def test_binop_sub(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
77 self.assertEqual(1, Expression("2 - 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
78 self.assertEqual(1, Expression("x - y").evaluate({'x': 1, 'y': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
79
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
80 def test_binop_sub(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
81 self.assertEqual(1, Expression("2 - 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
82 self.assertEqual(1, 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_mul(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
85 self.assertEqual(4, Expression("2 * 2").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
86 self.assertEqual(4, Expression("x * y").evaluate({'x': 2, 'y': 2}))
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_pow(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
89 self.assertEqual(4, Expression("2 ** 2").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
90 self.assertEqual(4, Expression("x ** y").evaluate({'x': 2, 'y': 2}))
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_div(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
93 self.assertEqual(2, Expression("4 / 2").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
94 self.assertEqual(2, Expression("x / y").evaluate({'x': 4, '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_floordiv(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
97 self.assertEqual(1, Expression("3 // 2").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
98 self.assertEqual(1, Expression("x // y").evaluate({'x': 3, '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_mod(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
101 self.assertEqual(1, Expression("3 % 2").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
102 self.assertEqual(1, Expression("x % y").evaluate({'x': 3, 'y': 2}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
103
32
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
104 def test_binop_and(self):
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
105 self.assertEqual(0, Expression("1 & 0").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
106 self.assertEqual(0, Expression("x & y").evaluate({'x': 1, 'y': 0}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
107
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
108 def test_binop_or(self):
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
109 self.assertEqual(1, Expression("1 | 0").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
110 self.assertEqual(1, Expression("x | y").evaluate({'x': 1, 'y': 0}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
111
31
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
112 def test_binop_contains(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
113 self.assertEqual(True, Expression("1 in (1, 2, 3)").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
114 self.assertEqual(True, Expression("x in y").evaluate({'x': 1,
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
115 'y': (1, 2, 3)}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
116
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
117 def test_binop_not_contains(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
118 self.assertEqual(True, Expression("4 not in (1, 2, 3)").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
119 self.assertEqual(True, Expression("x not in y").evaluate({'x': 4,
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
120 'y': (1, 2, 3)}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
121
32
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
122 def test_binop_is(self):
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
123 self.assertEqual(True, Expression("1 is 1").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
124 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
125 self.assertEqual(False, Expression("1 is 2").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
126 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
127
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
128 def test_binop_is_not(self):
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
129 self.assertEqual(True, Expression("1 is not 2").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
130 self.assertEqual(True, Expression("x is not y").evaluate({'x': 1,
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
131 'y': 2}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
132 self.assertEqual(False, Expression("1 is not 1").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
133 self.assertEqual(False, Expression("x is not y").evaluate({'x': 1,
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
134 'y': 1}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
135
31
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
136 def test_boolop_and(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
137 self.assertEqual(False, Expression("True and False").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
138 self.assertEqual(False, Expression("x and y").evaluate({'x': True,
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
139 'y': False}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
140
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
141 def test_boolop_or(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
142 self.assertEqual(True, Expression("True or False").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
143 self.assertEqual(True, Expression("x or y").evaluate({'x': True,
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
144 'y': False}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
145
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
146 def test_compare_eq(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
147 self.assertEqual(True, Expression("1 == 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
148 self.assertEqual(True, Expression("x == y").evaluate({'x': 1, 'y': 1}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
149
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
150 def test_compare_ne(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
151 self.assertEqual(False, Expression("1 != 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
152 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
153 self.assertEqual(False, Expression("1 <> 1").evaluate({}))
3b8c41bbf83d A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
154 self.assertEqual(False, Expression("x <> y").evaluate({'x': 1, 'y': 1}))
31
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
155
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
156 def test_compare_lt(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
157 self.assertEqual(True, Expression("1 < 2").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
158 self.assertEqual(True, Expression("x < y").evaluate({'x': 1, 'y': 2}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
159
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
160 def test_compare_le(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
161 self.assertEqual(True, Expression("1 <= 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
162 self.assertEqual(True, Expression("x <= y").evaluate({'x': 1, 'y': 1}))
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_gt(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
165 self.assertEqual(True, Expression("2 > 1").evaluate({}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
166 self.assertEqual(True, Expression("x > y").evaluate({'x': 2, 'y': 1}))
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_ge(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_multi(self):
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
173 self.assertEqual(True, Expression("1 != 3 == 3").evaluate({}))
81
cc034182061e Template expressions are now compiled to Python bytecode.
cmlenz
parents: 66
diff changeset
174 self.assertEqual(True, Expression("x != y == y").evaluate({'x': 1,
31
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
175 'y': 3}))
9a958398bed9 * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
176
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
177 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
178 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
179 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
180 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
181 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
182 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
183
102
12efdfe8af47 Ported [118] to trunk
jonas
parents: 90
diff changeset
184 def test_call_keywords(self):
12efdfe8af47 Ported [118] to trunk
jonas
parents: 90
diff changeset
185 self.assertEqual(42, Expression("foo(x=bar)").evaluate({'foo': lambda x: x,
12efdfe8af47 Ported [118] to trunk
jonas
parents: 90
diff changeset
186 'bar': 42}))
12efdfe8af47 Ported [118] to trunk
jonas
parents: 90
diff changeset
187
90
242610137d1f When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents: 88
diff changeset
188 def test_call_function_without_params(self):
242610137d1f When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents: 88
diff changeset
189 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
190 data = {'foo': 'bar'}
242610137d1f When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents: 88
diff changeset
191 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
192 data = {'foo': {'bar': range(42)}}
242610137d1f When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents: 88
diff changeset
193
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
194 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
195 # 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
196 # 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
197 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
198 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
199 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
200 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
201 '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
202 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
203 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
204 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
205
88
9ecae580dd93 Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
206 def test_list_comprehension(self):
9ecae580dd93 Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
207 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
208 self.assertEqual([0, 1], expr.evaluate({'numbers': range(5)}))
9ecae580dd93 Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
209
9ecae580dd93 Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
210 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
211 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
212 expr.evaluate({'numbers': range(5)}))
9ecae580dd93 Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
213
9ecae580dd93 Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
214 expr = Expression("[offset + n for n in numbers]")
9ecae580dd93 Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
215 self.assertEqual([2, 3, 4, 5, 6],
9ecae580dd93 Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
216 expr.evaluate({'numbers': range(5), 'offset': 2}))
81
cc034182061e Template expressions are now compiled to Python bytecode.
cmlenz
parents: 66
diff changeset
217
131
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
218 def test_list_comprehension_with_getattr(self):
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
219 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
220 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
221 self.assertEqual(['b'], expr.evaluate({'items': items}))
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
222
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
223 def test_list_comprehension_with_getitem(self):
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
224 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
225 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
226 self.assertEqual(['b'], expr.evaluate({'items': items}))
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
227
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
228 def test_error_position(self):
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
229 expr = Expression("nothing()", filename='index.html', lineno=50)
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
230 try:
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
231 expr.evaluate({})
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
232 self.fail('Expected TypeError')
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
233 except TypeError, e:
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
234 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
235 frame = exc_traceback.tb_next
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
236 while frame.tb_next:
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
237 frame = frame.tb_next
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
238 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
239 self.assertEqual(50, frame.tb_lineno)
203f459e7e26 * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
240
30
2ee9f28e16e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
241
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
242 def suite():
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
243 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
244 suite.addTest(unittest.makeSuite(ExpressionTestCase, 'test'))
27
b8456279c444 * Fix the boilerplate in the Python source files.
cmlenz
parents: 1
diff changeset
245 suite.addTest(doctest.DocTestSuite(Expression.__module__))
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
246 return suite
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
247
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
248 if __name__ == '__main__':
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
249 unittest.main(defaultTest='suite')
Copyright (C) 2012-2017 Edgewall Software