diff options
Diffstat (limited to 'Lib/test/test_parser.py')
-rw-r--r-- | Lib/test/test_parser.py | 133 |
1 files changed, 127 insertions, 6 deletions
diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 9ab4171..b39d37b 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -1,9 +1,10 @@ import parser -import os import unittest import sys import operator +import struct from test import support +from test.script_helper import assert_python_failure # # First, we test that we can generate trees from valid source fragments, @@ -34,7 +35,7 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): code = suite.compile() scope = {} exec(code, {}, scope) - self.assertTrue(isinstance(scope["x"], str)) + self.assertIsInstance(scope["x"], str) def check_suite(self, s): self.roundtrip(parser.suite, s) @@ -58,6 +59,16 @@ 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, 2, 3]") @@ -97,6 +108,8 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): self.check_expr("lambda x, *y, **z: 0") self.check_expr("(x for x in range(10))") self.check_expr("foo(x for x in range(10))") + self.check_expr("...") + self.check_expr("a[...]") def test_simple_expression(self): # expr_stmt @@ -147,6 +160,27 @@ 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") @@ -227,7 +261,7 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): def test_position(self): # An absolutely minimal test of position information. Better # tests would be a big project. - code = "def f(x):\n return x + 1\n" + code = "def f(x):\n return x + 1" st1 = parser.suite(code) st2 = st1.totuple(line_info=1, col_info=1) @@ -261,6 +295,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 @@ -512,6 +583,16 @@ class CompileTestCase(unittest.TestCase): st = parser.suite('a = "\\u1"') self.assertRaises(SyntaxError, parser.compilest, st) + def test_issue_9011(self): + # Issue 9011: compilation of an unary minus expression changed + # the meaning of the ST, so that a second compilation produced + # incorrect results. + st = parser.expr('-3') + code1 = parser.compilest(st) + self.assertEqual(eval(code1), -3) + code2 = parser.compilest(st) + self.assertEqual(eval(code2), -3) + class ParserStackLimitTestCase(unittest.TestCase): """try to push the parser to/over its limits. see http://bugs.python.org/issue1881 for a discussion @@ -527,9 +608,11 @@ class ParserStackLimitTestCase(unittest.TestCase): def test_trigger_memory_error(self): e = self._nested_expression(100) - print("Expecting 's_push: parser stack overflow' in next line", - file=sys.stderr) - self.assertRaises(MemoryError, parser.expr, e) + rc, out, err = assert_python_failure('-c', e) + # parsing the expression will result in an error message + # followed by a MemoryError (see #11963) + self.assertIn(b's_push: parser stack overflow', err) + self.assertIn(b'MemoryError', err) class STObjectTestCase(unittest.TestCase): """Test operations on ST objects themselves""" @@ -595,6 +678,44 @@ class STObjectTestCase(unittest.TestCase): self.assertRaises(TypeError, operator.lt, st1, 1815) self.assertRaises(TypeError, operator.gt, b'waterloo', st2) + check_sizeof = support.check_sizeof + + @support.cpython_only + def test_sizeof(self): + def XXXROUNDUP(n): + if n <= 1: + return n + if n <= 128: + return (n + 3) & ~3 + return 1 << (n - 1).bit_length() + + basesize = support.calcobjsize('Pii') + nodesize = struct.calcsize('hP3iP0h') + def sizeofchildren(node): + if node is None: + return 0 + res = 0 + hasstr = len(node) > 1 and isinstance(node[-1], str) + if hasstr: + res += len(node[-1]) + 1 + children = node[1:-1] if hasstr else node[1:] + if children: + res += XXXROUNDUP(len(children)) * nodesize + for child in children: + res += sizeofchildren(child) + return res + + def check_st_sizeof(st): + self.check_sizeof(st, basesize + nodesize + + sizeofchildren(st.totuple())) + + check_st_sizeof(parser.expr('2 + 3')) + check_st_sizeof(parser.expr('2 + 3 + 4')) + check_st_sizeof(parser.suite('x = 2 + 3')) + check_st_sizeof(parser.suite('')) + check_st_sizeof(parser.suite('# -*- coding: utf-8 -*-')) + check_st_sizeof(parser.expr('[' + '2,' * 1000 + ']')) + # XXX tests for pickling and unpickling of ST objects should go here |