test_parser.py revision f4189916e366045a44755d453c89d30e5006f84f
1import parser
2import unittest
3from 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
11class 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_class_defs(self):
131        self.check_suite("class foo():pass")
132
133    def test_import_from_statement(self):
134        self.check_suite("from sys.path import *")
135        self.check_suite("from sys.path import dirname")
136        self.check_suite("from sys.path import (dirname)")
137        self.check_suite("from sys.path import (dirname,)")
138        self.check_suite("from sys.path import dirname as my_dirname")
139        self.check_suite("from sys.path import (dirname as my_dirname)")
140        self.check_suite("from sys.path import (dirname as my_dirname,)")
141        self.check_suite("from sys.path import dirname, basename")
142        self.check_suite("from sys.path import (dirname, basename)")
143        self.check_suite("from sys.path import (dirname, basename,)")
144        self.check_suite(
145            "from sys.path import dirname as my_dirname, basename")
146        self.check_suite(
147            "from sys.path import (dirname as my_dirname, basename)")
148        self.check_suite(
149            "from sys.path import (dirname as my_dirname, basename,)")
150        self.check_suite(
151            "from sys.path import dirname, basename as my_basename")
152        self.check_suite(
153            "from sys.path import (dirname, basename as my_basename)")
154        self.check_suite(
155            "from sys.path import (dirname, basename as my_basename,)")
156
157    def test_basic_import_statement(self):
158        self.check_suite("import sys")
159        self.check_suite("import sys as system")
160        self.check_suite("import sys, math")
161        self.check_suite("import sys as system, math")
162        self.check_suite("import sys, math as my_math")
163
164    def test_pep263(self):
165        self.check_suite("# -*- coding: iso-8859-1 -*-\n"
166                         "pass\n")
167
168    def test_assert(self):
169        self.check_suite("assert alo < ahi and blo < bhi\n")
170
171#
172#  Second, we take *invalid* trees and make sure we get ParserError
173#  rejections for them.
174#
175
176class IllegalSyntaxTestCase(unittest.TestCase):
177
178    def check_bad_tree(self, tree, label):
179        try:
180            parser.sequence2st(tree)
181        except parser.ParserError:
182            pass
183        else:
184            self.fail("did not detect invalid tree for %r" % label)
185
186    def test_junk(self):
187        # not even remotely valid:
188        self.check_bad_tree((1, 2, 3), "<junk>")
189
190    def test_illegal_yield_1(self):
191        # Illegal yield statement: def f(): return 1; yield 1
192        tree = \
193        (257,
194         (264,
195          (285,
196           (259,
197            (1, 'def'),
198            (1, 'f'),
199            (260, (7, '('), (8, ')')),
200            (11, ':'),
201            (291,
202             (4, ''),
203             (5, ''),
204             (264,
205              (265,
206               (266,
207                (272,
208                 (275,
209                  (1, 'return'),
210                  (313,
211                   (292,
212                    (293,
213                     (294,
214                      (295,
215                       (297,
216                        (298,
217                         (299,
218                          (300,
219                           (301,
220                            (302, (303, (304, (305, (2, '1')))))))))))))))))),
221               (264,
222                (265,
223                 (266,
224                  (272,
225                   (276,
226                    (1, 'yield'),
227                    (313,
228                     (292,
229                      (293,
230                       (294,
231                        (295,
232                         (297,
233                          (298,
234                           (299,
235                            (300,
236                             (301,
237                              (302,
238                               (303, (304, (305, (2, '1')))))))))))))))))),
239                 (4, ''))),
240               (6, ''))))),
241           (4, ''),
242           (0, ''))))
243        self.check_bad_tree(tree, "def f():\n  return 1\n  yield 1")
244
245    def test_illegal_yield_2(self):
246        # Illegal return in generator: def f(): return 1; yield 1
247        tree = \
248        (257,
249         (264,
250          (265,
251           (266,
252            (278,
253             (1, 'from'),
254             (281, (1, '__future__')),
255             (1, 'import'),
256             (279, (1, 'generators')))),
257           (4, ''))),
258         (264,
259          (285,
260           (259,
261            (1, 'def'),
262            (1, 'f'),
263            (260, (7, '('), (8, ')')),
264            (11, ':'),
265            (291,
266             (4, ''),
267             (5, ''),
268             (264,
269              (265,
270               (266,
271                (272,
272                 (275,
273                  (1, 'return'),
274                  (313,
275                   (292,
276                    (293,
277                     (294,
278                      (295,
279                       (297,
280                        (298,
281                         (299,
282                          (300,
283                           (301,
284                            (302, (303, (304, (305, (2, '1')))))))))))))))))),
285               (264,
286                (265,
287                 (266,
288                  (272,
289                   (276,
290                    (1, 'yield'),
291                    (313,
292                     (292,
293                      (293,
294                       (294,
295                        (295,
296                         (297,
297                          (298,
298                           (299,
299                            (300,
300                             (301,
301                              (302,
302                               (303, (304, (305, (2, '1')))))))))))))))))),
303                 (4, ''))),
304               (6, ''))))),
305           (4, ''),
306           (0, ''))))
307        self.check_bad_tree(tree, "def f():\n  return 1\n  yield 1")
308
309    def test_print_chevron_comma(self):
310        # Illegal input: print >>fp,
311        tree = \
312        (257,
313         (264,
314          (265,
315           (266,
316            (268,
317             (1, 'print'),
318             (35, '>>'),
319             (290,
320              (291,
321               (292,
322                (293,
323                 (295,
324                  (296,
325                   (297,
326                    (298, (299, (300, (301, (302, (303, (1, 'fp')))))))))))))),
327             (12, ','))),
328           (4, ''))),
329         (0, ''))
330        self.check_bad_tree(tree, "print >>fp,")
331
332    def test_a_comma_comma_c(self):
333        # Illegal input: a,,c
334        tree = \
335        (258,
336         (311,
337          (290,
338           (291,
339            (292,
340             (293,
341              (295,
342               (296,
343                (297,
344                 (298, (299, (300, (301, (302, (303, (1, 'a')))))))))))))),
345          (12, ','),
346          (12, ','),
347          (290,
348           (291,
349            (292,
350             (293,
351              (295,
352               (296,
353                (297,
354                 (298, (299, (300, (301, (302, (303, (1, 'c'))))))))))))))),
355         (4, ''),
356         (0, ''))
357        self.check_bad_tree(tree, "a,,c")
358
359    def test_illegal_operator(self):
360        # Illegal input: a $= b
361        tree = \
362        (257,
363         (264,
364          (265,
365           (266,
366            (267,
367             (312,
368              (291,
369               (292,
370                (293,
371                 (294,
372                  (296,
373                   (297,
374                    (298,
375                     (299,
376                      (300, (301, (302, (303, (304, (1, 'a'))))))))))))))),
377             (268, (37, '$=')),
378             (312,
379              (291,
380               (292,
381                (293,
382                 (294,
383                  (296,
384                   (297,
385                    (298,
386                     (299,
387                      (300, (301, (302, (303, (304, (1, 'b'))))))))))))))))),
388           (4, ''))),
389         (0, ''))
390        self.check_bad_tree(tree, "a $= b")
391
392    def test_malformed_global(self):
393        #doesn't have global keyword in ast
394        tree = (257,
395                (264,
396                 (265,
397                  (266,
398                   (282, (1, 'foo'))), (4, ''))),
399                (4, ''),
400                (0, ''))
401        self.check_bad_tree(tree, "malformed global ast")
402
403def test_main():
404    test_support.run_unittest(
405        RoundtripLegalSyntaxTestCase,
406        IllegalSyntaxTestCase
407    )
408
409
410if __name__ == "__main__":
411    test_main()
412