Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | import parser |
2 | import unittest | |
3 | from test import test_support | |
4 | ||
5 | # | |
6 | # First, we test that we can generate trees from valid source fragments, | |
7 | # and that these valid trees are indeed allowed by the tree-loading side | |
8 | # of the parser module. | |
9 | # | |
10 | ||
11 | class RoundtripLegalSyntaxTestCase(unittest.TestCase): | |
12 | ||
13 | def roundtrip(self, f, s): | |
14 | st1 = f(s) | |
15 | t = st1.totuple() | |
16 | try: | |
17 | st2 = parser.sequence2st(t) | |
18 | except parser.ParserError, why: | |
19 | self.fail("could not roundtrip %r: %s" % (s, why)) | |
20 | ||
21 | self.assertEquals(t, st2.totuple(), | |
22 | "could not re-generate syntax tree") | |
23 | ||
24 | def check_expr(self, s): | |
25 | self.roundtrip(parser.expr, s) | |
26 | ||
27 | def check_suite(self, s): | |
28 | self.roundtrip(parser.suite, s) | |
29 | ||
30 | def test_yield_statement(self): | |
31 | self.check_suite("def f(): yield 1") | |
32 | self.check_suite("def f(): return; yield 1") | |
33 | self.check_suite("def f(): yield 1; return") | |
34 | self.check_suite("def f():\n" | |
35 | " for x in range(30):\n" | |
36 | " yield x\n") | |
37 | ||
38 | def test_expressions(self): | |
39 | self.check_expr("foo(1)") | |
40 | self.check_expr("[1, 2, 3]") | |
41 | self.check_expr("[x**3 for x in range(20)]") | |
42 | self.check_expr("[x**3 for x in range(20) if x % 3]") | |
43 | self.check_expr("foo(*args)") | |
44 | self.check_expr("foo(*args, **kw)") | |
45 | self.check_expr("foo(**kw)") | |
46 | self.check_expr("foo(key=value)") | |
47 | self.check_expr("foo(key=value, *args)") | |
48 | self.check_expr("foo(key=value, *args, **kw)") | |
49 | self.check_expr("foo(key=value, **kw)") | |
50 | self.check_expr("foo(a, b, c, *args)") | |
51 | self.check_expr("foo(a, b, c, *args, **kw)") | |
52 | self.check_expr("foo(a, b, c, **kw)") | |
53 | self.check_expr("foo + bar") | |
54 | self.check_expr("foo - bar") | |
55 | self.check_expr("foo * bar") | |
56 | self.check_expr("foo / bar") | |
57 | self.check_expr("foo // bar") | |
58 | self.check_expr("lambda: 0") | |
59 | self.check_expr("lambda x: 0") | |
60 | self.check_expr("lambda *y: 0") | |
61 | self.check_expr("lambda *y, **z: 0") | |
62 | self.check_expr("lambda **z: 0") | |
63 | self.check_expr("lambda x, y: 0") | |
64 | self.check_expr("lambda foo=bar: 0") | |
65 | self.check_expr("lambda foo=bar, spaz=nifty+spit: 0") | |
66 | self.check_expr("lambda foo=bar, **z: 0") | |
67 | self.check_expr("lambda foo=bar, blaz=blat+2, **z: 0") | |
68 | self.check_expr("lambda foo=bar, blaz=blat+2, *y, **z: 0") | |
69 | self.check_expr("lambda x, *y, **z: 0") | |
70 | self.check_expr("(x for x in range(10))") | |
71 | self.check_expr("foo(x for x in range(10))") | |
72 | ||
73 | def test_print(self): | |
74 | self.check_suite("print") | |
75 | self.check_suite("print 1") | |
76 | self.check_suite("print 1,") | |
77 | self.check_suite("print >>fp") | |
78 | self.check_suite("print >>fp, 1") | |
79 | self.check_suite("print >>fp, 1,") | |
80 | ||
81 | def test_simple_expression(self): | |
82 | # expr_stmt | |
83 | self.check_suite("a") | |
84 | ||
85 | def test_simple_assignments(self): | |
86 | self.check_suite("a = b") | |
87 | self.check_suite("a = b = c = d = e") | |
88 | ||
89 | def test_simple_augmented_assignments(self): | |
90 | self.check_suite("a += b") | |
91 | self.check_suite("a -= b") | |
92 | self.check_suite("a *= b") | |
93 | self.check_suite("a /= b") | |
94 | self.check_suite("a //= b") | |
95 | self.check_suite("a %= b") | |
96 | self.check_suite("a &= b") | |
97 | self.check_suite("a |= b") | |
98 | self.check_suite("a ^= b") | |
99 | self.check_suite("a <<= b") | |
100 | self.check_suite("a >>= b") | |
101 | self.check_suite("a **= b") | |
102 | ||
103 | def test_function_defs(self): | |
104 | self.check_suite("def f(): pass") | |
105 | self.check_suite("def f(*args): pass") | |
106 | self.check_suite("def f(*args, **kw): pass") | |
107 | self.check_suite("def f(**kw): pass") | |
108 | self.check_suite("def f(foo=bar): pass") | |
109 | self.check_suite("def f(foo=bar, *args): pass") | |
110 | self.check_suite("def f(foo=bar, *args, **kw): pass") | |
111 | self.check_suite("def f(foo=bar, **kw): pass") | |
112 | ||
113 | self.check_suite("def f(a, b): pass") | |
114 | self.check_suite("def f(a, b, *args): pass") | |
115 | self.check_suite("def f(a, b, *args, **kw): pass") | |
116 | self.check_suite("def f(a, b, **kw): pass") | |
117 | self.check_suite("def f(a, b, foo=bar): pass") | |
118 | self.check_suite("def f(a, b, foo=bar, *args): pass") | |
119 | self.check_suite("def f(a, b, foo=bar, *args, **kw): pass") | |
120 | self.check_suite("def f(a, b, foo=bar, **kw): pass") | |
121 | ||
122 | self.check_suite("@staticmethod\n" | |
123 | "def f(): pass") | |
124 | self.check_suite("@staticmethod\n" | |
125 | "@funcattrs(x, y)\n" | |
126 | "def f(): pass") | |
127 | self.check_suite("@funcattrs()\n" | |
128 | "def f(): pass") | |
129 | ||
130 | def test_import_from_statement(self): | |
131 | self.check_suite("from sys.path import *") | |
132 | self.check_suite("from sys.path import dirname") | |
133 | self.check_suite("from sys.path import (dirname)") | |
134 | self.check_suite("from sys.path import (dirname,)") | |
135 | self.check_suite("from sys.path import dirname as my_dirname") | |
136 | self.check_suite("from sys.path import (dirname as my_dirname)") | |
137 | self.check_suite("from sys.path import (dirname as my_dirname,)") | |
138 | self.check_suite("from sys.path import dirname, basename") | |
139 | self.check_suite("from sys.path import (dirname, basename)") | |
140 | self.check_suite("from sys.path import (dirname, basename,)") | |
141 | self.check_suite( | |
142 | "from sys.path import dirname as my_dirname, basename") | |
143 | self.check_suite( | |
144 | "from sys.path import (dirname as my_dirname, basename)") | |
145 | self.check_suite( | |
146 | "from sys.path import (dirname as my_dirname, basename,)") | |
147 | self.check_suite( | |
148 | "from sys.path import dirname, basename as my_basename") | |
149 | self.check_suite( | |
150 | "from sys.path import (dirname, basename as my_basename)") | |
151 | self.check_suite( | |
152 | "from sys.path import (dirname, basename as my_basename,)") | |
153 | ||
154 | def test_basic_import_statement(self): | |
155 | self.check_suite("import sys") | |
156 | self.check_suite("import sys as system") | |
157 | self.check_suite("import sys, math") | |
158 | self.check_suite("import sys as system, math") | |
159 | self.check_suite("import sys, math as my_math") | |
160 | ||
161 | def test_pep263(self): | |
162 | self.check_suite("# -*- coding: iso-8859-1 -*-\n" | |
163 | "pass\n") | |
164 | ||
165 | def test_assert(self): | |
166 | self.check_suite("assert alo < ahi and blo < bhi\n") | |
167 | ||
168 | # | |
169 | # Second, we take *invalid* trees and make sure we get ParserError | |
170 | # rejections for them. | |
171 | # | |
172 | ||
173 | class IllegalSyntaxTestCase(unittest.TestCase): | |
174 | ||
175 | def check_bad_tree(self, tree, label): | |
176 | try: | |
177 | parser.sequence2st(tree) | |
178 | except parser.ParserError: | |
179 | pass | |
180 | else: | |
181 | self.fail("did not detect invalid tree for %r" % label) | |
182 | ||
183 | def test_junk(self): | |
184 | # not even remotely valid: | |
185 | self.check_bad_tree((1, 2, 3), "<junk>") | |
186 | ||
187 | def test_illegal_yield_1(self): | |
188 | # Illegal yield statement: def f(): return 1; yield 1 | |
189 | tree = \ | |
190 | (257, | |
191 | (264, | |
192 | (285, | |
193 | (259, | |
194 | (1, 'def'), | |
195 | (1, 'f'), | |
196 | (260, (7, '('), (8, ')')), | |
197 | (11, ':'), | |
198 | (291, | |
199 | (4, ''), | |
200 | (5, ''), | |
201 | (264, | |
202 | (265, | |
203 | (266, | |
204 | (272, | |
205 | (275, | |
206 | (1, 'return'), | |
207 | (313, | |
208 | (292, | |
209 | (293, | |
210 | (294, | |
211 | (295, | |
212 | (297, | |
213 | (298, | |
214 | (299, | |
215 | (300, | |
216 | (301, | |
217 | (302, (303, (304, (305, (2, '1')))))))))))))))))), | |
218 | (264, | |
219 | (265, | |
220 | (266, | |
221 | (272, | |
222 | (276, | |
223 | (1, 'yield'), | |
224 | (313, | |
225 | (292, | |
226 | (293, | |
227 | (294, | |
228 | (295, | |
229 | (297, | |
230 | (298, | |
231 | (299, | |
232 | (300, | |
233 | (301, | |
234 | (302, | |
235 | (303, (304, (305, (2, '1')))))))))))))))))), | |
236 | (4, ''))), | |
237 | (6, ''))))), | |
238 | (4, ''), | |
239 | (0, '')))) | |
240 | self.check_bad_tree(tree, "def f():\n return 1\n yield 1") | |
241 | ||
242 | def test_illegal_yield_2(self): | |
243 | # Illegal return in generator: def f(): return 1; yield 1 | |
244 | tree = \ | |
245 | (257, | |
246 | (264, | |
247 | (265, | |
248 | (266, | |
249 | (278, | |
250 | (1, 'from'), | |
251 | (281, (1, '__future__')), | |
252 | (1, 'import'), | |
253 | (279, (1, 'generators')))), | |
254 | (4, ''))), | |
255 | (264, | |
256 | (285, | |
257 | (259, | |
258 | (1, 'def'), | |
259 | (1, 'f'), | |
260 | (260, (7, '('), (8, ')')), | |
261 | (11, ':'), | |
262 | (291, | |
263 | (4, ''), | |
264 | (5, ''), | |
265 | (264, | |
266 | (265, | |
267 | (266, | |
268 | (272, | |
269 | (275, | |
270 | (1, 'return'), | |
271 | (313, | |
272 | (292, | |
273 | (293, | |
274 | (294, | |
275 | (295, | |
276 | (297, | |
277 | (298, | |
278 | (299, | |
279 | (300, | |
280 | (301, | |
281 | (302, (303, (304, (305, (2, '1')))))))))))))))))), | |
282 | (264, | |
283 | (265, | |
284 | (266, | |
285 | (272, | |
286 | (276, | |
287 | (1, 'yield'), | |
288 | (313, | |
289 | (292, | |
290 | (293, | |
291 | (294, | |
292 | (295, | |
293 | (297, | |
294 | (298, | |
295 | (299, | |
296 | (300, | |
297 | (301, | |
298 | (302, | |
299 | (303, (304, (305, (2, '1')))))))))))))))))), | |
300 | (4, ''))), | |
301 | (6, ''))))), | |
302 | (4, ''), | |
303 | (0, '')))) | |
304 | self.check_bad_tree(tree, "def f():\n return 1\n yield 1") | |
305 | ||
306 | def test_print_chevron_comma(self): | |
307 | # Illegal input: print >>fp, | |
308 | tree = \ | |
309 | (257, | |
310 | (264, | |
311 | (265, | |
312 | (266, | |
313 | (268, | |
314 | (1, 'print'), | |
315 | (35, '>>'), | |
316 | (290, | |
317 | (291, | |
318 | (292, | |
319 | (293, | |
320 | (295, | |
321 | (296, | |
322 | (297, | |
323 | (298, (299, (300, (301, (302, (303, (1, 'fp')))))))))))))), | |
324 | (12, ','))), | |
325 | (4, ''))), | |
326 | (0, '')) | |
327 | self.check_bad_tree(tree, "print >>fp,") | |
328 | ||
329 | def test_a_comma_comma_c(self): | |
330 | # Illegal input: a,,c | |
331 | tree = \ | |
332 | (258, | |
333 | (311, | |
334 | (290, | |
335 | (291, | |
336 | (292, | |
337 | (293, | |
338 | (295, | |
339 | (296, | |
340 | (297, | |
341 | (298, (299, (300, (301, (302, (303, (1, 'a')))))))))))))), | |
342 | (12, ','), | |
343 | (12, ','), | |
344 | (290, | |
345 | (291, | |
346 | (292, | |
347 | (293, | |
348 | (295, | |
349 | (296, | |
350 | (297, | |
351 | (298, (299, (300, (301, (302, (303, (1, 'c'))))))))))))))), | |
352 | (4, ''), | |
353 | (0, '')) | |
354 | self.check_bad_tree(tree, "a,,c") | |
355 | ||
356 | def test_illegal_operator(self): | |
357 | # Illegal input: a $= b | |
358 | tree = \ | |
359 | (257, | |
360 | (264, | |
361 | (265, | |
362 | (266, | |
363 | (267, | |
364 | (312, | |
365 | (291, | |
366 | (292, | |
367 | (293, | |
368 | (294, | |
369 | (296, | |
370 | (297, | |
371 | (298, | |
372 | (299, | |
373 | (300, (301, (302, (303, (304, (1, 'a'))))))))))))))), | |
374 | (268, (37, '$=')), | |
375 | (312, | |
376 | (291, | |
377 | (292, | |
378 | (293, | |
379 | (294, | |
380 | (296, | |
381 | (297, | |
382 | (298, | |
383 | (299, | |
384 | (300, (301, (302, (303, (304, (1, 'b'))))))))))))))))), | |
385 | (4, ''))), | |
386 | (0, '')) | |
387 | self.check_bad_tree(tree, "a $= b") | |
388 | ||
389 | def test_malformed_global(self): | |
390 | #doesn't have global keyword in ast | |
391 | tree = (257, | |
392 | (264, | |
393 | (265, | |
394 | (266, | |
395 | (282, (1, 'foo'))), (4, ''))), | |
396 | (4, ''), | |
397 | (0, '')) | |
398 | self.check_bad_tree(tree, "malformed global ast") | |
399 | ||
400 | def test_main(): | |
401 | test_support.run_unittest( | |
402 | RoundtripLegalSyntaxTestCase, | |
403 | IllegalSyntaxTestCase | |
404 | ) | |
405 | ||
406 | ||
407 | if __name__ == "__main__": | |
408 | test_main() |