test_parser.py revision 1a4ddaecc732c207fa69890db87ac4b47da867b8
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_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
173class 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
400def test_main():
401    test_support.run_unittest(
402        RoundtripLegalSyntaxTestCase,
403        IllegalSyntaxTestCase
404    )
405
406
407if __name__ == "__main__":
408    test_main()
409