annotate markup/tests/eval.py @ 227:96a7e5011c69 trunk

Use list comprehension instead of `map()` in the AST transformer.
author cmlenz
date Fri, 08 Sep 2006 09:17:42 +0000
parents 16d7b5db7ef4
children
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
195
f5952780267a Fix missing import in unit test added in [244].
cmlenz
parents: 194
diff changeset
18 from markup.eval import Expression, Undefined
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
192
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
23 def test_name_lookup(self):
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
24 self.assertEqual('bar', Expression('foo').evaluate({'foo': 'bar'}))
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
25 self.assertEqual(id, Expression('id').evaluate({}, nocall=True))
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
26 self.assertEqual('bar', Expression('id').evaluate({'id': 'bar'}))
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
27 self.assertEqual(None, Expression('id').evaluate({'id': None},
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
28 nocall=True))
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
29
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
30 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
31 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
32 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
33 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
34 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
35 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
36 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
37
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
38 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
39 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
40 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
41 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
42 self.assertEqual(u'þ', expr.evaluate({}))
180
061491fb4ea8 String literals in XPath expressions are assumed to be UTF-8 encoded.
cmlenz
parents: 167
diff changeset
43 expr = Expression("'\xc3\xbe'")
061491fb4ea8 String literals in XPath expressions are assumed to be UTF-8 encoded.
cmlenz
parents: 167
diff changeset
44 self.assertEqual(u'þ', expr.evaluate({}))
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
45
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
46 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
47 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
48 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
49 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
50 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
51 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
52 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
53
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
54 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
55 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
56 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
57 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
58
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
59 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
60 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
61 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
62 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
63 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
64
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
65 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
66 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
67 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
68 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
69 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
70
31
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
71 def test_unaryop_pos(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
72 self.assertEqual(1, Expression("+1").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
73 self.assertEqual(1, Expression("+x").evaluate({'x': 1}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
74
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
75 def test_unaryop_neg(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
76 self.assertEqual(-1, Expression("-1").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
77 self.assertEqual(-1, Expression("-x").evaluate({'x': 1}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
78
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
79 def test_unaryop_not(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
80 self.assertEqual(False, Expression("not True").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
81 self.assertEqual(False, Expression("not x").evaluate({'x': True}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
82
32
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
83 def test_unaryop_inv(self):
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
84 self.assertEqual(-2, Expression("~1").evaluate({}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
85 self.assertEqual(-2, Expression("~x").evaluate({'x': 1}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
86
31
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
87 def test_binop_add(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
88 self.assertEqual(3, Expression("2 + 1").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
89 self.assertEqual(3, Expression("x + y").evaluate({'x': 2, 'y': 1}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
90
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
91 def test_binop_sub(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
92 self.assertEqual(1, Expression("2 - 1").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
93 self.assertEqual(1, Expression("x - y").evaluate({'x': 1, 'y': 1}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
94
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
95 def test_binop_sub(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
96 self.assertEqual(1, Expression("2 - 1").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
97 self.assertEqual(1, Expression("x - y").evaluate({'x': 2, 'y': 1}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
98
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
99 def test_binop_mul(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
100 self.assertEqual(4, Expression("2 * 2").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
101 self.assertEqual(4, Expression("x * y").evaluate({'x': 2, 'y': 2}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
102
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
103 def test_binop_pow(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
104 self.assertEqual(4, Expression("2 ** 2").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
105 self.assertEqual(4, Expression("x ** y").evaluate({'x': 2, 'y': 2}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
106
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
107 def test_binop_div(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
108 self.assertEqual(2, Expression("4 / 2").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
109 self.assertEqual(2, Expression("x / y").evaluate({'x': 4, 'y': 2}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
110
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
111 def test_binop_floordiv(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
112 self.assertEqual(1, Expression("3 // 2").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
113 self.assertEqual(1, Expression("x // y").evaluate({'x': 3, 'y': 2}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
114
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
115 def test_binop_mod(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
116 self.assertEqual(1, Expression("3 % 2").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
117 self.assertEqual(1, Expression("x % y").evaluate({'x': 3, 'y': 2}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
118
32
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
119 def test_binop_and(self):
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
120 self.assertEqual(0, Expression("1 & 0").evaluate({}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
121 self.assertEqual(0, Expression("x & y").evaluate({'x': 1, 'y': 0}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
122
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
123 def test_binop_or(self):
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
124 self.assertEqual(1, Expression("1 | 0").evaluate({}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
125 self.assertEqual(1, Expression("x | y").evaluate({'x': 1, 'y': 0}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
126
31
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
127 def test_binop_contains(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
128 self.assertEqual(True, Expression("1 in (1, 2, 3)").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
129 self.assertEqual(True, Expression("x in y").evaluate({'x': 1,
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
130 'y': (1, 2, 3)}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
131
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
132 def test_binop_not_contains(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
133 self.assertEqual(True, Expression("4 not in (1, 2, 3)").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
134 self.assertEqual(True, Expression("x not in y").evaluate({'x': 4,
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
135 'y': (1, 2, 3)}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
136
32
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
137 def test_binop_is(self):
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
138 self.assertEqual(True, Expression("1 is 1").evaluate({}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
139 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
140 self.assertEqual(False, Expression("1 is 2").evaluate({}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
141 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
142
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
143 def test_binop_is_not(self):
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
144 self.assertEqual(True, Expression("1 is not 2").evaluate({}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
145 self.assertEqual(True, Expression("x is not y").evaluate({'x': 1,
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
146 'y': 2}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
147 self.assertEqual(False, Expression("1 is not 1").evaluate({}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
148 self.assertEqual(False, Expression("x is not y").evaluate({'x': 1,
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
149 'y': 1}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
150
31
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
151 def test_boolop_and(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
152 self.assertEqual(False, Expression("True and False").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
153 self.assertEqual(False, Expression("x and y").evaluate({'x': True,
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
154 'y': False}))
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_boolop_or(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
157 self.assertEqual(True, Expression("True or False").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
158 self.assertEqual(True, Expression("x or y").evaluate({'x': True,
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
159 'y': False}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
160
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
161 def test_compare_eq(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
162 self.assertEqual(True, Expression("1 == 1").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
163 self.assertEqual(True, Expression("x == y").evaluate({'x': 1, 'y': 1}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
164
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
165 def test_compare_ne(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
166 self.assertEqual(False, Expression("1 != 1").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
167 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
168 self.assertEqual(False, Expression("1 <> 1").evaluate({}))
2224a52256ca A couple more operators supported in expressions.
cmlenz
parents: 31
diff changeset
169 self.assertEqual(False, Expression("x <> y").evaluate({'x': 1, 'y': 1}))
31
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
170
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
171 def test_compare_lt(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
172 self.assertEqual(True, Expression("1 < 2").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
173 self.assertEqual(True, Expression("x < y").evaluate({'x': 1, 'y': 2}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
174
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
175 def test_compare_le(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
176 self.assertEqual(True, Expression("1 <= 1").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
177 self.assertEqual(True, Expression("x <= y").evaluate({'x': 1, 'y': 1}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
178
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
179 def test_compare_gt(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
180 self.assertEqual(True, Expression("2 > 1").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
181 self.assertEqual(True, Expression("x > y").evaluate({'x': 2, 'y': 1}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
182
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
183 def test_compare_ge(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
184 self.assertEqual(True, Expression("1 >= 1").evaluate({}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
185 self.assertEqual(True, Expression("x >= y").evaluate({'x': 1, 'y': 1}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
186
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
187 def test_compare_multi(self):
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
188 self.assertEqual(True, Expression("1 != 3 == 3").evaluate({}))
81
d60486018004 Template expressions are now compiled to Python bytecode.
cmlenz
parents: 66
diff changeset
189 self.assertEqual(True, Expression("x != y == y").evaluate({'x': 1,
31
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
190 'y': 3}))
2ab5fa60575d * More test cases for expression evaluation.
cmlenz
parents: 30
diff changeset
191
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
192 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
193 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
194 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
195 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
196 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
197 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
198
102
e20a153cc20c Ported [118] to trunk
jonas
parents: 90
diff changeset
199 def test_call_keywords(self):
e20a153cc20c Ported [118] to trunk
jonas
parents: 90
diff changeset
200 self.assertEqual(42, Expression("foo(x=bar)").evaluate({'foo': lambda x: x,
e20a153cc20c Ported [118] to trunk
jonas
parents: 90
diff changeset
201 'bar': 42}))
e20a153cc20c Ported [118] to trunk
jonas
parents: 90
diff changeset
202
203
48fab34e5e4d Fix for handling function calls with star/dstar arguments in expressions. Closes #42. Many thanks to David Fraser for reporting the problem and providing a patch!
cmlenz
parents: 198
diff changeset
203 def test_call_star_args(self):
48fab34e5e4d Fix for handling function calls with star/dstar arguments in expressions. Closes #42. Many thanks to David Fraser for reporting the problem and providing a patch!
cmlenz
parents: 198
diff changeset
204 self.assertEqual(42, Expression("foo(*bar)").evaluate({'foo': lambda x: x,
48fab34e5e4d Fix for handling function calls with star/dstar arguments in expressions. Closes #42. Many thanks to David Fraser for reporting the problem and providing a patch!
cmlenz
parents: 198
diff changeset
205 'bar': [42]}))
48fab34e5e4d Fix for handling function calls with star/dstar arguments in expressions. Closes #42. Many thanks to David Fraser for reporting the problem and providing a patch!
cmlenz
parents: 198
diff changeset
206
48fab34e5e4d Fix for handling function calls with star/dstar arguments in expressions. Closes #42. Many thanks to David Fraser for reporting the problem and providing a patch!
cmlenz
parents: 198
diff changeset
207 def test_call_dstar_args(self):
48fab34e5e4d Fix for handling function calls with star/dstar arguments in expressions. Closes #42. Many thanks to David Fraser for reporting the problem and providing a patch!
cmlenz
parents: 198
diff changeset
208 def foo(x):
48fab34e5e4d Fix for handling function calls with star/dstar arguments in expressions. Closes #42. Many thanks to David Fraser for reporting the problem and providing a patch!
cmlenz
parents: 198
diff changeset
209 return x
48fab34e5e4d Fix for handling function calls with star/dstar arguments in expressions. Closes #42. Many thanks to David Fraser for reporting the problem and providing a patch!
cmlenz
parents: 198
diff changeset
210 self.assertEqual(42, Expression("foo(**bar)").evaluate({'foo': foo,
48fab34e5e4d Fix for handling function calls with star/dstar arguments in expressions. Closes #42. Many thanks to David Fraser for reporting the problem and providing a patch!
cmlenz
parents: 198
diff changeset
211 'bar': {"x": 42}}))
48fab34e5e4d Fix for handling function calls with star/dstar arguments in expressions. Closes #42. Many thanks to David Fraser for reporting the problem and providing a patch!
cmlenz
parents: 198
diff changeset
212
90
c835e81c50af When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents: 88
diff changeset
213 def test_call_function_without_params(self):
c835e81c50af When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents: 88
diff changeset
214 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
215 data = {'foo': 'bar'}
c835e81c50af When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents: 88
diff changeset
216 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
217 data = {'foo': {'bar': range(42)}}
c835e81c50af When an expression evaluates to a callable, it is called implicitly.
cmlenz
parents: 88
diff changeset
218
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
219 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
220 # 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
221 # 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
222 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
223 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
224 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
225 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
226 '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
227 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
228 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
229 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
230
88
628ba9ed39ef Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
231 def test_list_comprehension(self):
628ba9ed39ef Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
232 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
233 self.assertEqual([0, 1], expr.evaluate({'numbers': range(5)}))
628ba9ed39ef Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
234
628ba9ed39ef Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
235 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
236 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
237 expr.evaluate({'numbers': range(5)}))
628ba9ed39ef Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
238
628ba9ed39ef Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
239 expr = Expression("[offset + n for n in numbers]")
628ba9ed39ef Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
240 self.assertEqual([2, 3, 4, 5, 6],
628ba9ed39ef Add support for list comprehension in expressions (see #12).
cmlenz
parents: 87
diff changeset
241 expr.evaluate({'numbers': range(5), 'offset': 2}))
81
d60486018004 Template expressions are now compiled to Python bytecode.
cmlenz
parents: 66
diff changeset
242
131
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
243 def test_list_comprehension_with_getattr(self):
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
244 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
245 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
246 self.assertEqual(['b'], expr.evaluate({'items': items}))
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
247
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
248 def test_list_comprehension_with_getitem(self):
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
249 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
250 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
251 self.assertEqual(['b'], expr.evaluate({'items': items}))
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
252
198
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
253 if sys.version_info >= (2, 4):
227
96a7e5011c69 Use list comprehension instead of `map()` in the AST transformer.
cmlenz
parents: 225
diff changeset
254 # Generator expressions only supported in Python 2.4 and up
96a7e5011c69 Use list comprehension instead of `map()` in the AST transformer.
cmlenz
parents: 225
diff changeset
255
198
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
256 def test_generator_expression(self):
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
257 expr = Expression("list(n for n in numbers if n < 2)")
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
258 self.assertEqual([0, 1], expr.evaluate({'numbers': range(5)}))
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
259
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
260 expr = Expression("list((i, n + 1) for i, n in enumerate(numbers))")
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
261 self.assertEqual([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)],
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
262 expr.evaluate({'numbers': range(5)}))
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
263
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
264 expr = Expression("list(offset + n for n in numbers)")
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
265 self.assertEqual([2, 3, 4, 5, 6],
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
266 expr.evaluate({'numbers': range(5), 'offset': 2}))
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
267
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
268 def test_generator_expression_with_getattr(self):
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
269 items = [{'name': 'a', 'value': 1}, {'name': 'b', 'value': 2}]
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
270 expr = Expression("list(i.name for i in items if i.value > 1)")
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
271 self.assertEqual(['b'], expr.evaluate({'items': items}))
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
272
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
273 def test_generator_expression_with_getitem(self):
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
274 items = [{'name': 'a', 'value': 1}, {'name': 'b', 'value': 2}]
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
275 expr = Expression("list(i['name'] for i in items if i['value'] > 1)")
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
276 self.assertEqual(['b'], expr.evaluate({'items': items}))
ca8a9defe6fe Implemented support for generator expressions (fixes #16)
mgood
parents: 195
diff changeset
277
225
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
278 def test_slice(self):
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
279 expr = Expression("numbers[0:2]")
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
280 self.assertEqual([0, 1], expr.evaluate({'numbers': range(5)}))
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
281
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
282 def test_slice_with_vars(self):
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
283 expr = Expression("numbers[start:end]")
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
284 self.assertEqual([0, 1], expr.evaluate({'numbers': range(5), 'start': 0, 'end': 2}))
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
285
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
286 def test_slice_copy(self):
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
287 expr = Expression("numbers[:]")
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
288 self.assertEqual([0, 1, 2, 3, 4], expr.evaluate({'numbers': range(5)}))
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
289
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
290 def test_slice_stride(self):
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
291 expr = Expression("numbers[::stride]")
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
292 self.assertEqual([0, 2, 4], expr.evaluate({'numbers': range(5), 'stride': 2}))
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
293
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
294 def test_slice_negative_start(self):
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
295 expr = Expression("numbers[-1:]")
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
296 self.assertEqual([4], expr.evaluate({'numbers': range(5)}))
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
297
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
298 def test_slice_negative_end(self):
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
299 expr = Expression("numbers[:-1]")
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
300 self.assertEqual([0, 1, 2, 3], expr.evaluate({'numbers': range(5)}))
16d7b5db7ef4 support slices in expressions (fixes #51)
mgood
parents: 203
diff changeset
301
194
c0535b218466 Fix regression introduced in [242]: any reference to an undefined name would result in a `NameError`.
cmlenz
parents: 192
diff changeset
302 def test_error_access_undefined(self):
c0535b218466 Fix regression introduced in [242]: any reference to an undefined name would result in a `NameError`.
cmlenz
parents: 192
diff changeset
303 expr = Expression("nothing", filename='index.html', lineno=50)
c0535b218466 Fix regression introduced in [242]: any reference to an undefined name would result in a `NameError`.
cmlenz
parents: 192
diff changeset
304 self.assertEqual(Undefined, type(expr.evaluate({})))
c0535b218466 Fix regression introduced in [242]: any reference to an undefined name would result in a `NameError`.
cmlenz
parents: 192
diff changeset
305
192
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
306 def test_error_call_undefined(self):
131
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
307 expr = Expression("nothing()", filename='index.html', lineno=50)
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
308 try:
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
309 expr.evaluate({})
192
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
310 self.fail('Expected NameError')
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
311 except NameError, e:
131
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
312 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
313 frame = exc_traceback.tb_next
192
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
314 frames = []
131
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
315 while frame.tb_next:
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
316 frame = frame.tb_next
192
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
317 frames.append(frame)
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
318 self.assertEqual('<Expression "nothing()">',
192
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
319 frames[-3].tb_frame.f_code.co_name)
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
320 self.assertEqual('index.html',
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
321 frames[-3].tb_frame.f_code.co_filename)
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
322 self.assertEqual(50, frames[-3].tb_lineno)
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
323
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
324 def test_error_getattr_undefined(self):
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
325 expr = Expression("nothing.nil", filename='index.html', lineno=50)
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
326 try:
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
327 expr.evaluate({})
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
328 self.fail('Expected NameError')
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
329 except NameError, e:
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
330 exc_type, exc_value, exc_traceback = sys.exc_info()
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
331 frame = exc_traceback.tb_next
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
332 frames = []
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
333 while frame.tb_next:
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
334 frame = frame.tb_next
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
335 frames.append(frame)
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
336 self.assertEqual('<Expression "nothing.nil">',
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
337 frames[-3].tb_frame.f_code.co_name)
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
338 self.assertEqual('index.html',
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
339 frames[-3].tb_frame.f_code.co_filename)
b64e36bc1100 Expression evaluation now differentiates between undefined variables and variables that are defined but set to `None`.
cmlenz
parents: 180
diff changeset
340 self.assertEqual(50, frames[-3].tb_lineno)
131
2ad83f1d337c * Support for line numbers in exceptions in expression evaluation (#22).
cmlenz
parents: 118
diff changeset
341
30
bcdbb7e5e4e5 Experimental support for using the new native AST in Python 2.5 instead of the `compiler` package.
cmlenz
parents: 27
diff changeset
342
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
343 def suite():
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
344 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
345 suite.addTest(unittest.makeSuite(ExpressionTestCase, 'test'))
27
b4f78c05e5c9 * Fix the boilerplate in the Python source files.
cmlenz
parents: 1
diff changeset
346 suite.addTest(doctest.DocTestSuite(Expression.__module__))
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
347 return suite
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
348
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
349 if __name__ == '__main__':
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
350 unittest.main(defaultTest='suite')
Copyright (C) 2012-2017 Edgewall Software