diff options
Diffstat (limited to 'Lib/test/test_parser.py')
-rw-r--r-- | Lib/test/test_parser.py | 243 |
1 files changed, 161 insertions, 82 deletions
diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 12fa89cd464..70eb9c0cc2b 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -1,8 +1,9 @@ import parser import unittest import sys +import operator import struct -from test import test_support as support +from test import support # # First, we test that we can generate trees from valid source fragments, @@ -17,7 +18,7 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): t = st1.totuple() try: st2 = parser.sequence2st(t) - except parser.ParserError, why: + except parser.ParserError as why: self.fail("could not roundtrip %r: %s" % (s, why)) self.assertEqual(t, st2.totuple(), @@ -32,8 +33,8 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): suite = parser.suite("from __future__ import unicode_literals; x = ''") code = suite.compile() scope = {} - exec code in scope - self.assertIsInstance(scope["x"], unicode) + exec(code, {}, scope) + self.assertIsInstance(scope["x"], str) def check_suite(self, s): self.roundtrip(parser.suite, s) @@ -57,39 +58,25 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): " if (yield):\n" " yield x\n") + def test_nonlocal_statement(self): + self.check_suite("def f():\n" + " x = 0\n" + " def g():\n" + " nonlocal x\n") + self.check_suite("def f():\n" + " x = y = 0\n" + " def g():\n" + " nonlocal x, y\n") + def test_expressions(self): self.check_expr("foo(1)") - self.check_expr("{1:1}") - self.check_expr("{1:1, 2:2, 3:3}") - self.check_expr("{1:1, 2:2, 3:3,}") - self.check_expr("{1}") - self.check_expr("{1, 2, 3}") - self.check_expr("{1, 2, 3,}") - self.check_expr("[]") - self.check_expr("[1]") self.check_expr("[1, 2, 3]") - self.check_expr("[1, 2, 3,]") - self.check_expr("()") - self.check_expr("(1,)") - self.check_expr("(1, 2, 3)") - self.check_expr("(1, 2, 3,)") self.check_expr("[x**3 for x in range(20)]") self.check_expr("[x**3 for x in range(20) if x % 3]") self.check_expr("[x**3 for x in range(20) if x % 2 if x % 3]") - self.check_expr("[x+y for x in range(30) for y in range(20) if x % 2 if y % 3]") - #self.check_expr("[x for x in lambda: True, lambda: False if x()]") self.check_expr("list(x**3 for x in range(20))") self.check_expr("list(x**3 for x in range(20) if x % 3)") self.check_expr("list(x**3 for x in range(20) if x % 2 if x % 3)") - self.check_expr("list(x+y for x in range(30) for y in range(20) if x % 2 if y % 3)") - self.check_expr("{x**3 for x in range(30)}") - self.check_expr("{x**3 for x in range(30) if x % 3}") - self.check_expr("{x**3 for x in range(30) if x % 2 if x % 3}") - self.check_expr("{x+y for x in range(30) for y in range(20) if x % 2 if y % 3}") - self.check_expr("{x**3: y**2 for x, y in zip(range(30), range(30))}") - self.check_expr("{x**3: y**2 for x, y in zip(range(30), range(30)) if x % 3}") - self.check_expr("{x**3: y**2 for x, y in zip(range(30), range(30)) if x % 3 if y % 3}") - self.check_expr("{x:y for x in range(30) for y in range(20) if x % 2 if y % 3}") self.check_expr("foo(*args)") self.check_expr("foo(*args, **kw)") self.check_expr("foo(**kw)") @@ -118,17 +105,10 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): self.check_expr("lambda foo=bar, blaz=blat+2, **z: 0") self.check_expr("lambda foo=bar, blaz=blat+2, *y, **z: 0") self.check_expr("lambda x, *y, **z: 0") - self.check_expr("lambda x: 5 if x else 2") self.check_expr("(x for x in range(10))") self.check_expr("foo(x for x in range(10))") - - def test_print(self): - self.check_suite("print") - self.check_suite("print 1") - self.check_suite("print 1,") - self.check_suite("print >>fp") - self.check_suite("print >>fp, 1") - self.check_suite("print >>fp, 1,") + self.check_expr("...") + self.check_expr("a[...]") def test_simple_expression(self): # expr_stmt @@ -179,8 +159,30 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): self.check_suite("@funcattrs()\n" "def f(): pass") + # keyword-only arguments + self.check_suite("def f(*, a): pass") + self.check_suite("def f(*, a = 5): pass") + self.check_suite("def f(*, a = 5, b): pass") + self.check_suite("def f(*, a, b = 5): pass") + self.check_suite("def f(*, a, b = 5, **kwds): pass") + self.check_suite("def f(*args, a): pass") + self.check_suite("def f(*args, a = 5): pass") + self.check_suite("def f(*args, a = 5, b): pass") + self.check_suite("def f(*args, a, b = 5): pass") + self.check_suite("def f(*args, a, b = 5, **kwds): pass") + + # function annotations + self.check_suite("def f(a: int): pass") + self.check_suite("def f(a: int = 5): pass") + self.check_suite("def f(*args: list): pass") + self.check_suite("def f(**kwds: dict): pass") + self.check_suite("def f(*, a: int): pass") + self.check_suite("def f(*, a: int = 5): pass") + self.check_suite("def f() -> int: pass") + def test_class_defs(self): self.check_suite("class foo():pass") + self.check_suite("class foo(object):pass") self.check_suite("@class_decorator\n" "class foo():pass") self.check_suite("@class_decorator(arg)\n" @@ -189,7 +191,6 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): "@decorator2\n" "class foo():pass") - def test_import_from_statement(self): self.check_suite("from sys.path import *") self.check_suite("from sys.path import dirname") @@ -225,8 +226,14 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): def test_relative_imports(self): self.check_suite("from . import name") self.check_suite("from .. import name") + # check all the way up to '....', since '...' is tokenized + # differently from '.' (it's an ellipsis token). + self.check_suite("from ... import name") + self.check_suite("from .... import name") self.check_suite("from .pkg import name") self.check_suite("from ..pkg import name") + self.check_suite("from ...pkg import name") + self.check_suite("from ....pkg import name") def test_pep263(self): self.check_suite("# -*- coding: iso-8859-1 -*-\n" @@ -250,12 +257,6 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): self.check_suite("try: pass\nexcept: pass\nelse: pass\n" "finally: pass\n") - def test_except_clause(self): - self.check_suite("try: pass\nexcept: pass\n") - self.check_suite("try: pass\nexcept A: pass\n") - self.check_suite("try: pass\nexcept A, e: pass\n") - self.check_suite("try: pass\nexcept A as e: pass\n") - def test_position(self): # An absolutely minimal test of position information. Better # tests would be a big project. @@ -293,6 +294,43 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): (0, '', 2, -1)], terminals) + def test_extended_unpacking(self): + self.check_suite("*a = y") + self.check_suite("x, *b, = m") + self.check_suite("[*a, *b] = y") + self.check_suite("for [*x, b] in x: pass") + + def test_raise_statement(self): + self.check_suite("raise\n") + self.check_suite("raise e\n") + self.check_suite("try:\n" + " suite\n" + "except Exception as e:\n" + " raise ValueError from e\n") + + def test_set_displays(self): + self.check_expr('{2}') + self.check_expr('{2,}') + self.check_expr('{2, 3}') + self.check_expr('{2, 3,}') + + def test_dict_displays(self): + self.check_expr('{}') + self.check_expr('{a:b}') + self.check_expr('{a:b,}') + self.check_expr('{a:b, c:d}') + self.check_expr('{a:b, c:d,}') + + def test_set_comprehensions(self): + self.check_expr('{x for x in seq}') + self.check_expr('{f(x) for x in seq}') + self.check_expr('{f(x) for x in seq if condition(x)}') + + def test_dict_comprehensions(self): + self.check_expr('{x:x for x in seq}') + self.check_expr('{x**2:x[3] for x in seq if condition(x)}') + self.check_expr('{x:x for x in seq1 for y in seq2 if condition(x, y)}') + # # Second, we take *invalid* trees and make sure we get ParserError @@ -432,29 +470,6 @@ class IllegalSyntaxTestCase(unittest.TestCase): (0, '')))) self.check_bad_tree(tree, "def f():\n return 1\n yield 1") - def test_print_chevron_comma(self): - # Illegal input: print >>fp, - tree = \ - (257, - (264, - (265, - (266, - (268, - (1, 'print'), - (35, '>>'), - (290, - (291, - (292, - (293, - (295, - (296, - (297, - (298, (299, (300, (301, (302, (303, (1, 'fp')))))))))))))), - (12, ','))), - (4, ''))), - (0, '')) - self.check_bad_tree(tree, "print >>fp,") - def test_a_comma_comma_c(self): # Illegal input: a,,c tree = \ @@ -527,18 +542,18 @@ class IllegalSyntaxTestCase(unittest.TestCase): self.check_bad_tree(tree, "malformed global ast") def test_missing_import_source(self): - # from import a + # from import fred tree = \ (257, - (267, - (268, - (269, - (281, - (283, (1, 'from'), (1, 'import'), - (286, (284, (1, 'fred')))))), + (268, + (269, + (270, + (282, + (284, (1, 'from'), (1, 'import'), + (287, (285, (1, 'fred')))))), (4, ''))), (4, ''), (0, '')) - self.check_bad_tree(tree, "from import a") + self.check_bad_tree(tree, "from import fred") class CompileTestCase(unittest.TestCase): @@ -554,7 +569,7 @@ class CompileTestCase(unittest.TestCase): st = parser.suite('x = 2; y = x + 3') code = parser.compilest(st) globs = {} - exec code in globs + exec(code, globs) self.assertEqual(globs['y'], 5) def test_compile_error(self): @@ -562,9 +577,9 @@ class CompileTestCase(unittest.TestCase): self.assertRaises(SyntaxError, parser.compilest, st) def test_compile_badunicode(self): - st = parser.suite('a = u"\U12345678"') + st = parser.suite('a = "\\U12345678"') self.assertRaises(SyntaxError, parser.compilest, st) - st = parser.suite('a = u"\u1"') + st = parser.suite('a = "\\u1"') self.assertRaises(SyntaxError, parser.compilest, st) def test_issue_9011(self): @@ -577,27 +592,90 @@ class CompileTestCase(unittest.TestCase): code2 = parser.compilest(st) self.assertEqual(eval(code2), -3) - class ParserStackLimitTestCase(unittest.TestCase): - """try to push the parser to/over it's limits. + """try to push the parser to/over its limits. see http://bugs.python.org/issue1881 for a discussion """ def _nested_expression(self, level): return "["*level+"]"*level def test_deeply_nested_list(self): - e = self._nested_expression(99) + # XXX used to be 99 levels in 2.x + e = self._nested_expression(93) st = parser.expr(e) st.compile() def test_trigger_memory_error(self): e = self._nested_expression(100) - print >>sys.stderr, "Expecting 's_push: parser stack overflow' in next line" + print("Expecting 's_push: parser stack overflow' in next line", + file=sys.stderr) + sys.stderr.flush() self.assertRaises(MemoryError, parser.expr, e) class STObjectTestCase(unittest.TestCase): """Test operations on ST objects themselves""" + def test_comparisons(self): + # ST objects should support order and equality comparisons + st1 = parser.expr('2 + 3') + st2 = parser.suite('x = 2; y = x + 3') + st3 = parser.expr('list(x**3 for x in range(20))') + st1_copy = parser.expr('2 + 3') + st2_copy = parser.suite('x = 2; y = x + 3') + st3_copy = parser.expr('list(x**3 for x in range(20))') + + # exercise fast path for object identity + self.assertEqual(st1 == st1, True) + self.assertEqual(st2 == st2, True) + self.assertEqual(st3 == st3, True) + # slow path equality + self.assertEqual(st1, st1_copy) + self.assertEqual(st2, st2_copy) + self.assertEqual(st3, st3_copy) + self.assertEqual(st1 == st2, False) + self.assertEqual(st1 == st3, False) + self.assertEqual(st2 == st3, False) + self.assertEqual(st1 != st1, False) + self.assertEqual(st2 != st2, False) + self.assertEqual(st3 != st3, False) + self.assertEqual(st1 != st1_copy, False) + self.assertEqual(st2 != st2_copy, False) + self.assertEqual(st3 != st3_copy, False) + self.assertEqual(st2 != st1, True) + self.assertEqual(st1 != st3, True) + self.assertEqual(st3 != st2, True) + # we don't particularly care what the ordering is; just that + # it's usable and self-consistent + self.assertEqual(st1 < st2, not (st2 <= st1)) + self.assertEqual(st1 < st3, not (st3 <= st1)) + self.assertEqual(st2 < st3, not (st3 <= st2)) + self.assertEqual(st1 < st2, st2 > st1) + self.assertEqual(st1 < st3, st3 > st1) + self.assertEqual(st2 < st3, st3 > st2) + self.assertEqual(st1 <= st2, st2 >= st1) + self.assertEqual(st3 <= st1, st1 >= st3) + self.assertEqual(st2 <= st3, st3 >= st2) + # transitivity + bottom = min(st1, st2, st3) + top = max(st1, st2, st3) + mid = sorted([st1, st2, st3])[1] + self.assertTrue(bottom < mid) + self.assertTrue(bottom < top) + self.assertTrue(mid < top) + self.assertTrue(bottom <= mid) + self.assertTrue(bottom <= top) + self.assertTrue(mid <= top) + self.assertTrue(bottom <= bottom) + self.assertTrue(mid <= mid) + self.assertTrue(top <= top) + # interaction with other types + self.assertEqual(st1 == 1588.602459, False) + self.assertEqual('spanish armada' != st2, True) + self.assertRaises(TypeError, operator.ge, st3, None) + self.assertRaises(TypeError, operator.le, False, st1) + self.assertRaises(TypeError, operator.lt, st1, 1815) + self.assertRaises(TypeError, operator.gt, b'waterloo', st2) + check_sizeof = support.check_sizeof @support.cpython_only @@ -639,6 +717,7 @@ class STObjectTestCase(unittest.TestCase): # XXX tests for pickling and unpickling of ST objects should go here + def test_main(): support.run_unittest( RoundtripLegalSyntaxTestCase, |