summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_parser.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_parser.py')
-rw-r--r--Lib/test/test_parser.py133
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