예제 #1
0
    def testSyntaxErrorOffset(self):
        check = self.check
        check('def fact(x):\n\treturn x!\n', 2, 10)
        check('1 +\n', 1, 4)
        check('def spam():\n  print(1)\n print(2)', 3, 10)
        check('Python = "Python" +', 1, 20)
        check('Python = "\u1e54\xfd\u0163\u0125\xf2\xf1" +', 1, 20)
        check(b'# -*- coding: cp1251 -*-\nPython = "\xcf\xb3\xf2\xee\xed" +',
              2, 19, encoding='cp1251')
        check(b'Python = "\xcf\xb3\xf2\xee\xed" +', 1, 18)
        check('x = "a', 1, 7)
        check('lambda x: x = 2', 1, 1)

        # Errors thrown by compile.c
        check('class foo:return 1', 1, 11)
        check('def f():\n  continue', 2, 3)
        check('def f():\n  break', 2, 3)
        check('try:\n  pass\nexcept:\n  pass\nexcept ValueError:\n  pass', 2, 3)

        # Errors thrown by tokenizer.c
        check('(0x+1)', 1, 3)
        check('x = 0xI', 1, 6)
        check('0010 + 2', 1, 4)
        check('x = 32e-+4', 1, 8)
        check('x = 0o9', 1, 6)
        check('\u03b1 = 0xI', 1, 6)
        check(b'\xce\xb1 = 0xI', 1, 6)
        check(b'# -*- coding: iso8859-7 -*-\n\xe1 = 0xI', 2, 6,
              encoding='iso8859-7')
        check(b"""if 1:
            def foo():
                '''

            def bar():
                pass

            def baz():
                '''quux'''
            """, 9, 20)

        # Errors thrown by symtable.c
        check('x = [(yield i) for i in range(3)]', 1, 5)
        check('def f():\n  from _ import *', 1, 1)
        check('def f(x, x):\n  pass', 1, 1)
        check('def f(x):\n  nonlocal x', 2, 3)
        check('def f(x):\n  x = 1\n  global x', 3, 3)
        check('nonlocal x', 1, 1)
        check('def f():\n  global x\n  nonlocal x', 2, 3)

        # Errors thrown by future.c
        check('from __future__ import doesnt_exist', 1, 1)
        check('from __future__ import braces', 1, 1)
        check('x=1\nfrom __future__ import division', 2, 1)
        check('foo(1=2)', 1, 5)
        check('def f():\n  x, y: int', 2, 3)
        check('[*x for x in xs]', 1, 2)
        check('foo(x for x in range(10), 100)', 1, 5)
        check('(yield i) = 2', 1, 1 if support.use_old_parser() else 2)
        check('def f(*):\n  pass', 1, 7 if support.use_old_parser() else 8)
        check('for 1 in []: pass', 1, 5 if support.use_old_parser() else 7)
예제 #2
0
 def test_all_keywords_fail_to_be_used_as_names(self):
     all_keywords = set(keyword.kwlist)
     if use_old_parser():
         all_keywords.discard('__peg_parser__')
     for key in all_keywords:
         with self.assertRaises(SyntaxError):
             exec(f"{key} = 42")
    def test_invalid_syntax_errors_async(self):
        if use_old_parser():
            check_syntax_error(
                self, "async def f(a, b = 5, /, c): pass",
                "non-default argument follows default argument")
            check_syntax_error(
                self, "async def f(a = 5, b, /, c): pass",
                "non-default argument follows default argument")
            check_syntax_error(
                self, "async def f(a = 5, b=1, /, c, d=2): pass",
                "non-default argument follows default argument")
            check_syntax_error(
                self, "async def f(a = 5, b, /): pass",
                "non-default argument follows default argument")

        check_syntax_error(self, "async def f(*args, /): pass")
        check_syntax_error(self, "async def f(*args, a, /): pass")
        check_syntax_error(self, "async def f(**kwargs, /): pass")
        check_syntax_error(self, "async def f(/, a = 1): pass")
        check_syntax_error(self, "async def f(/, a): pass")
        check_syntax_error(self, "async def f(/): pass")
        check_syntax_error(self, "async def f(*, a, /): pass")
        check_syntax_error(self, "async def f(*, /, a): pass")
        check_syntax_error(self, "async def f(a, /, a): pass",
                           "duplicate argument 'a' in function definition")
        check_syntax_error(self, "async def f(a, /, *, a): pass",
                           "duplicate argument 'a' in function definition")
        check_syntax_error(self, "async def f(a, b/2, c): pass")
        check_syntax_error(self, "async def f(a, /, c, /): pass")
        check_syntax_error(self, "async def f(a, /, c, /, d): pass")
        check_syntax_error(self, "async def f(a, /, c, /, d, *, e): pass")
        check_syntax_error(self, "async def f(a, *, c, /, d, e): pass")
    def test_invalid_syntax_lambda(self):
        if use_old_parser():
            check_syntax_error(
                self, "lambda a, b = 5, /, c: None",
                "non-default argument follows default argument")
            check_syntax_error(
                self, "lambda a = 5, b, /, c: None",
                "non-default argument follows default argument")
            check_syntax_error(
                self, "lambda a = 5, b, /: None",
                "non-default argument follows default argument")

        check_syntax_error(self, "lambda *args, /: None")
        check_syntax_error(self, "lambda *args, a, /: None")
        check_syntax_error(self, "lambda **kwargs, /: None")
        check_syntax_error(self, "lambda /, a = 1: None")
        check_syntax_error(self, "lambda /, a: None")
        check_syntax_error(self, "lambda /: None")
        check_syntax_error(self, "lambda *, a, /: None")
        check_syntax_error(self, "lambda *, /, a: None")
        check_syntax_error(self, "lambda a, /, a: None",
                           "duplicate argument 'a' in function definition")
        check_syntax_error(self, "lambda a, /, *, a: None",
                           "duplicate argument 'a' in function definition")
        check_syntax_error(self, "lambda a, /, b, /: None")
        check_syntax_error(self, "lambda a, /, b, /, c: None")
        check_syntax_error(self, "lambda a, /, b, /, c, *, d: None")
        check_syntax_error(self, "lambda a, *, b, /, c: None")
예제 #5
0
 def test_guido_as_bdfl(self):
     code = '2 {0} 3'
     compile(code.format('!='), '<BDFL test>', 'exec')
     with self.assertRaises(SyntaxError) as cm:
         compile(code.format('<>'), '<FLUFL test>', 'exec')
     self.assertRegex(str(cm.exception), "invalid syntax")
     self.assertIn('2 <> 3', cm.exception.text)
     self.assertEqual(cm.exception.filename, '<FLUFL test>')
     self.assertEqual(cm.exception.lineno, 1)
     # The old parser reports the end of the token and the new
     # parser reports the start of the token
     self.assertEqual(cm.exception.offset, 4 if support.use_old_parser() else 3)
예제 #6
0
    def test_format_specifier_expressions(self):
        width = 10
        precision = 4
        value = decimal.Decimal('12.34567')
        self.assertEqual(f'result: {value:{width}.{precision}}',
                         'result:      12.35')
        self.assertEqual(f'result: {value:{width!r}.{precision}}',
                         'result:      12.35')
        self.assertEqual(f'result: {value:{width:0}.{precision:1}}',
                         'result:      12.35')
        self.assertEqual(f'result: {value:{1}{0:0}.{precision:1}}',
                         'result:      12.35')
        self.assertEqual(f'result: {value:{ 1}{ 0:0}.{ precision:1}}',
                         'result:      12.35')
        self.assertEqual(f'{10:#{1}0x}', '       0xa')
        self.assertEqual(f'{10:{"#"}1{0}{"x"}}', '       0xa')
        self.assertEqual(f'{-10:-{"#"}1{0}x}', '      -0xa')
        self.assertEqual(f'{-10:{"-"}#{1}0{"x"}}', '      -0xa')
        self.assertEqual(f'{10:#{3 != {4:5} and width}x}', '       0xa')

        self.assertAllRaise(
            SyntaxError,
            "f-string: expecting '}'",
            [
                """f'{"s"!r{":10"}}'""",

                # This looks like a nested format spec.
            ])

        err_msg = "invalid syntax" if use_old_parser(
        ) else "f-string: invalid syntax"
        self.assertAllRaise(
            SyntaxError,
            err_msg,
            [  # Invalid syntax inside a nested spec.
                "f'{4:{/5}}'",
            ])

        self.assertAllRaise(
            SyntaxError,
            "f-string: expressions nested too deeply",
            [  # Can't nest format specifiers.
                "f'result: {value:{width:{0}}.{precision:1}}'",
            ])

        self.assertAllRaise(
            SyntaxError,
            'f-string: invalid conversion character',
            [  # No expansion inside conversion or for
                #  the : or ! itself.
                """f'{"s"!{"r"}}'""",
            ])
예제 #7
0
    def test_lambda(self):
        x = 5
        self.assertEqual(f'{(lambda y:x*y)("8")!r}', "'88888'")
        self.assertEqual(f'{(lambda y:x*y)("8")!r:10}', "'88888'   ")
        self.assertEqual(f'{(lambda y:x*y)("8"):10}', "88888     ")

        # lambda doesn't work without parens, because the colon
        #  makes the parser think it's a format_spec
        err_msg = "invalid syntax" if use_old_parser(
        ) else "f-string: invalid syntax"
        self.assertAllRaise(SyntaxError, err_msg, [
            "f'{lambda x:x}'",
        ])
예제 #8
0
    def test_eval_bytes_invalid_escape(self):
        for b in range(1, 128):
            if b in b"""\n\r"'01234567\\abfnrtvx""":
                continue
            with self.assertWarns(DeprecationWarning):
                self.assertEqual(eval(r"b'\%c'" % b), b'\\' + bytes([b]))

        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter('always', category=DeprecationWarning)
            eval("b'''\n\\z'''")
        self.assertEqual(len(w), 1)
        self.assertEqual(w[0].filename, '<string>')
        if use_old_parser():
            self.assertEqual(w[0].lineno, 1)

        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter('error', category=DeprecationWarning)
            with self.assertRaises(SyntaxError) as cm:
                eval("b'''\n\\z'''")
            exc = cm.exception
        self.assertEqual(w, [])
        self.assertEqual(exc.filename, '<string>')
        if use_old_parser():
            self.assertEqual(exc.lineno, 1)
예제 #9
0
    def test_barry_as_bdfl(self):
        code = "from __future__ import barry_as_FLUFL\n2 {0} 3"
        compile(code.format('<>'), '<BDFL test>', 'exec',
                __future__.CO_FUTURE_BARRY_AS_BDFL)
        with self.assertRaises(SyntaxError) as cm:
            compile(code.format('!='), '<FLUFL test>', 'exec',
                    __future__.CO_FUTURE_BARRY_AS_BDFL)
        self.assertRegex(str(cm.exception),
                         "with Barry as BDFL, use '<>' instead of '!='")
        self.assertIn('2 != 3', cm.exception.text)
        self.assertEqual(cm.exception.filename, '<FLUFL test>')

        self.assertTrue(cm.exception.lineno, 2)
        # The old parser reports the end of the token and the new
        # parser reports the start of the token
        self.assertEqual(cm.exception.offset, 4 if support.use_old_parser() else 3)
예제 #10
0
파일: test_fstring.py 프로젝트: Sythage/-
    def test_ast_line_numbers_nested(self):
        expr = """
a = 10
f'{a * f"-{x()}-"}'"""
        t = ast.parse(expr)
        self.assertEqual(type(t), ast.Module)
        self.assertEqual(len(t.body), 2)
        # check `a = 10`
        self.assertEqual(type(t.body[0]), ast.Assign)
        self.assertEqual(t.body[0].lineno, 2)
        # check `f'...'`
        self.assertEqual(type(t.body[1]), ast.Expr)
        self.assertEqual(type(t.body[1].value), ast.JoinedStr)
        self.assertEqual(len(t.body[1].value.values), 1)
        self.assertEqual(type(t.body[1].value.values[0]), ast.FormattedValue)
        self.assertEqual(t.body[1].lineno, 3)
        self.assertEqual(t.body[1].value.lineno, 3)
        self.assertEqual(t.body[1].value.values[0].lineno, 3)
        # check the binop location
        binop = t.body[1].value.values[0].value
        self.assertEqual(type(binop), ast.BinOp)
        self.assertEqual(type(binop.left), ast.Name)
        self.assertEqual(type(binop.op), ast.Mult)
        self.assertEqual(type(binop.right), ast.JoinedStr)
        self.assertEqual(binop.lineno, 3)
        self.assertEqual(binop.left.lineno, 3)
        self.assertEqual(binop.right.lineno, 3)
        self.assertEqual(binop.col_offset, 3)
        self.assertEqual(binop.left.col_offset, 3)
        self.assertEqual(binop.right.col_offset, 7)
        # check the nested call location
        self.assertEqual(len(binop.right.values), 3)
        self.assertEqual(type(binop.right.values[0]), ast.Constant)
        self.assertEqual(type(binop.right.values[0].value), str)
        self.assertEqual(type(binop.right.values[1]), ast.FormattedValue)
        self.assertEqual(type(binop.right.values[2]), ast.Constant)
        self.assertEqual(type(binop.right.values[2].value), str)
        self.assertEqual(binop.right.values[0].lineno, 3)
        self.assertEqual(binop.right.values[1].lineno, 3)
        self.assertEqual(binop.right.values[2].lineno, 3)
        call = binop.right.values[1].value
        self.assertEqual(type(call), ast.Call)
        self.assertEqual(call.lineno, 3)
        if support.use_old_parser():
            self.assertEqual(call.col_offset, 11)
예제 #11
0
    def test_parens_in_expressions(self):
        self.assertEqual(f'{3,}', '(3,)')

        # Add these because when an expression is evaluated, parens
        #  are added around it. But we shouldn't go from an invalid
        #  expression to a valid one. The added parens are just
        #  supposed to allow whitespace (including newlines).
        err_msg = "invalid syntax" if use_old_parser(
        ) else "f-string: invalid syntax"
        self.assertAllRaise(
            SyntaxError,
            err_msg,
            [
                "f'{,}'",
                "f'{,}'",  # this is (,), which is an error
            ])

        self.assertAllRaise(SyntaxError, r"f-string: unmatched '\)'", [
            "f'{3)+(4}'",
        ])

        self.assertAllRaise(SyntaxError, 'EOL while scanning string literal', [
            "f'{\n}'",
        ])
예제 #12
0
class SyntaxTestCase(unittest.TestCase):
    def _check_error(self,
                     code,
                     errtext,
                     filename="<testcase>",
                     mode="exec",
                     subclass=None,
                     lineno=None,
                     offset=None):
        """Check that compiling code raises SyntaxError with errtext.

        errtest is a regular expression that must be present in the
        test of the exception raised.  If subclass is specified it
        is the expected subclass of SyntaxError (e.g. IndentationError).
        """
        try:
            compile(code, filename, mode)
        except SyntaxError as err:
            if subclass and not isinstance(err, subclass):
                self.fail("SyntaxError is not a %s" % subclass.__name__)
            mo = re.search(errtext, str(err))
            if mo is None:
                self.fail("SyntaxError did not contain %r" % (errtext, ))
            self.assertEqual(err.filename, filename)
            if lineno is not None:
                self.assertEqual(err.lineno, lineno)
            if offset is not None:
                self.assertEqual(err.offset, offset)
        else:
            self.fail("compile() did not raise SyntaxError")

    def test_curly_brace_after_primary_raises_immediately(self):
        self._check_error("f{", "invalid syntax", mode="single")

    def test_assign_call(self):
        self._check_error("f() = 1", "assign")

    @unittest.skipIf(support.use_old_parser(),
                     "The old parser cannot generate these error messages")
    def test_assign_del(self):
        self._check_error("del (,)", "invalid syntax")
        self._check_error("del 1", "delete literal")
        self._check_error("del (1, 2)", "delete literal")
        self._check_error("del None", "delete None")
        self._check_error("del *x", "delete starred")
        self._check_error("del (*x)", "use starred expression")
        self._check_error("del (*x,)", "delete starred")
        self._check_error("del [*x,]", "delete starred")
        self._check_error("del f()", "delete function call")
        self._check_error("del f(a, b)", "delete function call")
        self._check_error("del o.f()", "delete function call")
        self._check_error("del a[0]()", "delete function call")
        self._check_error("del x, f()", "delete function call")
        self._check_error("del f(), x", "delete function call")
        self._check_error("del [a, b, ((c), (d,), e.f())]",
                          "delete function call")
        self._check_error("del (a if True else b)", "delete conditional")
        self._check_error("del +a", "delete operator")
        self._check_error("del a, +b", "delete operator")
        self._check_error("del a + b", "delete operator")
        self._check_error("del (a + b, c)", "delete operator")
        self._check_error("del (c[0], a + b)", "delete operator")
        self._check_error("del a.b.c + 2", "delete operator")
        self._check_error("del a.b.c[0] + 2", "delete operator")
        self._check_error("del (a, b, (c, d.e.f + 2))", "delete operator")
        self._check_error("del [a, b, (c, d.e.f[0] + 2)]", "delete operator")
        self._check_error("del (a := 5)", "delete named expression")
        # We don't have a special message for this, but make sure we don't
        # report "cannot delete name"
        self._check_error("del a += b", "invalid syntax")

    def test_global_param_err_first(self):
        source = """if 1:
            def error(a):
                global a  # SyntaxError
            def error2():
                b = 1
                global b  # SyntaxError
            """
        self._check_error(source, "parameter and global", lineno=3)

    def test_nonlocal_param_err_first(self):
        source = """if 1:
            def error(a):
                nonlocal a  # SyntaxError
            def error2():
                b = 1
                global b  # SyntaxError
            """
        self._check_error(source, "parameter and nonlocal", lineno=3)

    def test_break_outside_loop(self):
        self._check_error("break", "outside loop")

    def test_yield_outside_function(self):
        self._check_error("if 0: yield", "outside function")
        self._check_error("if 0: yield\nelse:  x=1", "outside function")
        self._check_error("if 1: pass\nelse: yield", "outside function")
        self._check_error("while 0: yield", "outside function")
        self._check_error("while 0: yield\nelse:  x=1", "outside function")
        self._check_error("class C:\n  if 0: yield", "outside function")
        self._check_error("class C:\n  if 1: pass\n  else: yield",
                          "outside function")
        self._check_error("class C:\n  while 0: yield", "outside function")
        self._check_error("class C:\n  while 0: yield\n  else:  x = 1",
                          "outside function")

    def test_return_outside_function(self):
        self._check_error("if 0: return", "outside function")
        self._check_error("if 0: return\nelse:  x=1", "outside function")
        self._check_error("if 1: pass\nelse: return", "outside function")
        self._check_error("while 0: return", "outside function")
        self._check_error("class C:\n  if 0: return", "outside function")
        self._check_error("class C:\n  while 0: return", "outside function")
        self._check_error("class C:\n  while 0: return\n  else:  x=1",
                          "outside function")
        self._check_error("class C:\n  if 0: return\n  else: x= 1",
                          "outside function")
        self._check_error("class C:\n  if 1: pass\n  else: return",
                          "outside function")

    def test_break_outside_loop(self):
        self._check_error("if 0: break", "outside loop")
        self._check_error("if 0: break\nelse:  x=1", "outside loop")
        self._check_error("if 1: pass\nelse: break", "outside loop")
        self._check_error("class C:\n  if 0: break", "outside loop")
        self._check_error("class C:\n  if 1: pass\n  else: break",
                          "outside loop")

    def test_continue_outside_loop(self):
        self._check_error("if 0: continue", "not properly in loop")
        self._check_error("if 0: continue\nelse:  x=1", "not properly in loop")
        self._check_error("if 1: pass\nelse: continue", "not properly in loop")
        self._check_error("class C:\n  if 0: continue", "not properly in loop")
        self._check_error("class C:\n  if 1: pass\n  else: continue",
                          "not properly in loop")

    def test_unexpected_indent(self):
        self._check_error("foo()\n bar()\n",
                          "unexpected indent",
                          subclass=IndentationError)

    def test_no_indent(self):
        self._check_error("if 1:\nfoo()",
                          "expected an indented block",
                          subclass=IndentationError)

    def test_bad_outdent(self):
        self._check_error("if 1:\n  foo()\n bar()",
                          "unindent does not match .* level",
                          subclass=IndentationError)

    def test_kwargs_last(self):
        self._check_error("int(base=10, '2')",
                          "positional argument follows keyword argument")

    def test_kwargs_last2(self):
        self._check_error(
            "int(**{'base': 10}, '2')", "positional argument follows "
            "keyword argument unpacking")

    def test_kwargs_last3(self):
        self._check_error(
            "int(**{'base': 10}, *['2'])",
            "iterable argument unpacking follows "
            "keyword argument unpacking")

    def test_empty_line_after_linecont(self):
        # See issue-40847
        s = r"""\
pass
        \

pass
"""
        try:
            compile(s, '<string>', 'exec')
        except SyntaxError:
            self.fail(
                "Empty line after a line continuation character is valid.")

    def test_barry_as_flufl_with_syntax_errors(self):
        # The "barry_as_flufl" rule can produce some "bugs-at-a-distance" if
        # is reading the wrong token in the presence of syntax errors later
        # in the file. See bpo-42214 for more information.
        code = """
def func1():
    if a != b:
        raise ValueError

def func2():
    try
        return 1
    finally:
        pass
"""
        self._check_error(code, "invalid syntax")

    def test_invalid_line_continuation_left_recursive(self):
        # Check bpo-42218: SyntaxErrors following left-recursive rules
        # (t_primary_raw in this case) need to be tested explicitly
        self._check_error(
            "A.\u018a\\ ",
            "unexpected character after line continuation character")
        self._check_error("A.\u03bc\\\n", "unexpected EOF while parsing")
예제 #13
0
            ("Inner loop", "[i for i in range(5) for j in (i := range(5))]"),
            ("Nested comprehension", "[i for i in [j for j in (k := range(5))]]"),
            ("Nested comprehension condition", "[i for i in [j for j in range(5) if (j := True)]]"),
            ("Nested comprehension body", "[i for i in [(j := True) for j in range(5)]]"),
        ]
        msg = "assignment expression cannot be used in a comprehension iterable expression"
        for case, code in cases:
            with self.subTest(case=case):
                with self.assertRaisesRegex(SyntaxError, msg):
                    exec(code, {}) # Module scope
                with self.assertRaisesRegex(SyntaxError, msg):
                    exec(code, {}, {}) # Class scope
                with self.assertRaisesRegex(SyntaxError, msg):
                    exec(f"lambda: {code}", {}) # Function scope

    @unittest.skipIf(use_old_parser(), "Old parser does not support walruses in set comprehensions")
    def test_named_expression_invalid_rebinding_set_comprehension_iteration_variable(self):
        cases = [
            ("Local reuse", 'i', "{i := 0 for i in range(5)}"),
            ("Nested reuse", 'j', "{{(j := 0) for i in range(5)} for j in range(5)}"),
            ("Reuse inner loop target", 'j', "{(j := 0) for i in range(5) for j in range(5)}"),
            ("Unpacking reuse", 'i', "{i := 0 for i, j in {(0, 1)}}"),
            ("Reuse in loop condition", 'i', "{i+1 for i in range(5) if (i := 0)}"),
            ("Unreachable reuse", 'i', "{False or (i:=0) for i in range(5)}"),
            ("Unreachable nested reuse", 'i',
                "{(i, j) for i in range(5) for j in range(5) if True or (i:=10)}"),
        ]
        for case, target, code in cases:
            msg = f"assignment expression cannot rebind comprehension iteration variable '{target}'"
            with self.subTest(case=case):
                with self.assertRaisesRegex(SyntaxError, msg):
예제 #14
0
        self.assertEqual(f'{d[a]}', 'integer')
        self.assertEqual('{d[a]}'.format(d=d), 'string')
        self.assertEqual('{d[0]}'.format(d=d), 'integer')

    def test_errors(self):
        # see issue 26287
        self.assertAllRaise(TypeError, 'unsupported',
                            [r"f'{(lambda: 0):x}'",
                             r"f'{(0,):x}'",
                             ])
        self.assertAllRaise(ValueError, 'Unknown format code',
                            [r"f'{1000:j}'",
                             r"f'{1000:j}'",
                            ])

    @unittest.skipIf(use_old_parser(), "The old parser only supports <fstring> as the filename")
    def test_filename_in_syntaxerror(self):
        # see issue 38964
        with temp_cwd() as cwd:
            file_path = os.path.join(cwd, 't.py')
            with open(file_path, 'w') as f:
                f.write('f"{a b}"') # This generates a SyntaxError
            _, _, stderr = assert_python_failure(file_path)
        self.assertIn(file_path, stderr.decode('utf-8'))

    def test_loop(self):
        for i in range(1000):
            self.assertEqual(f'i:{i}', 'i:' + str(i))

    def test_dict(self):
        d = {'"': 'dquote',
예제 #15
0
            "FUR''",
            "Fur''",
            "fb''",
            "fB''",
            "Fb''",
            "FB''",
            "bf''",
            "bF''",
            "Bf''",
            "BF''",
        ]
        double_quote_cases = [
            case.replace("'", '"') for case in single_quote_cases
        ]
        error_msg = ('invalid syntax'
                     if use_old_parser() else 'unexpected EOF while parsing')
        self.assertAllRaise(SyntaxError, error_msg,
                            single_quote_cases + double_quote_cases)

    def test_leading_trailing_spaces(self):
        self.assertEqual(f'{ 3}', '3')
        self.assertEqual(f'{  3}', '3')
        self.assertEqual(f'{3 }', '3')
        self.assertEqual(f'{3  }', '3')

        self.assertEqual(f'expr={ {x: y for x, y in [(1, 2), ]}}',
                         'expr={1: 2}')
        self.assertEqual(f'expr={ {x: y for x, y in [(1, 2), ]} }',
                         'expr={1: 2}')

    def test_not_equal(self):
예제 #16
0
class BaseExceptionReportingTests:

    def get_exception(self, exception_or_callable):
        if isinstance(exception_or_callable, Exception):
            return exception_or_callable
        try:
            exception_or_callable()
        except Exception as e:
            return e

    def zero_div(self):
        1/0 # In zero_div

    def check_zero_div(self, msg):
        lines = msg.splitlines()
        self.assertTrue(lines[-3].startswith('  File'))
        self.assertIn('1/0 # In zero_div', lines[-2])
        self.assertTrue(lines[-1].startswith('ZeroDivisionError'), lines[-1])

    def test_simple(self):
        try:
            1/0 # Marker
        except ZeroDivisionError as _:
            e = _
        lines = self.get_report(e).splitlines()
        self.assertEqual(len(lines), 4)
        self.assertTrue(lines[0].startswith('Traceback'))
        self.assertTrue(lines[1].startswith('  File'))
        self.assertIn('1/0 # Marker', lines[2])
        self.assertTrue(lines[3].startswith('ZeroDivisionError'))

    def test_cause(self):
        def inner_raise():
            try:
                self.zero_div()
            except ZeroDivisionError as e:
                raise KeyError from e
        def outer_raise():
            inner_raise() # Marker
        blocks = boundaries.split(self.get_report(outer_raise))
        self.assertEqual(len(blocks), 3)
        self.assertEqual(blocks[1], cause_message)
        self.check_zero_div(blocks[0])
        self.assertIn('inner_raise() # Marker', blocks[2])

    def test_context(self):
        def inner_raise():
            try:
                self.zero_div()
            except ZeroDivisionError:
                raise KeyError
        def outer_raise():
            inner_raise() # Marker
        blocks = boundaries.split(self.get_report(outer_raise))
        self.assertEqual(len(blocks), 3)
        self.assertEqual(blocks[1], context_message)
        self.check_zero_div(blocks[0])
        self.assertIn('inner_raise() # Marker', blocks[2])

    def test_context_suppression(self):
        try:
            try:
                raise Exception
            except:
                raise ZeroDivisionError from None
        except ZeroDivisionError as _:
            e = _
        lines = self.get_report(e).splitlines()
        self.assertEqual(len(lines), 4)
        self.assertTrue(lines[0].startswith('Traceback'))
        self.assertTrue(lines[1].startswith('  File'))
        self.assertIn('ZeroDivisionError from None', lines[2])
        self.assertTrue(lines[3].startswith('ZeroDivisionError'))

    def test_cause_and_context(self):
        # When both a cause and a context are set, only the cause should be
        # displayed and the context should be muted.
        def inner_raise():
            try:
                self.zero_div()
            except ZeroDivisionError as _e:
                e = _e
            try:
                xyzzy
            except NameError:
                raise KeyError from e
        def outer_raise():
            inner_raise() # Marker
        blocks = boundaries.split(self.get_report(outer_raise))
        self.assertEqual(len(blocks), 3)
        self.assertEqual(blocks[1], cause_message)
        self.check_zero_div(blocks[0])
        self.assertIn('inner_raise() # Marker', blocks[2])

    def test_cause_recursive(self):
        def inner_raise():
            try:
                try:
                    self.zero_div()
                except ZeroDivisionError as e:
                    z = e
                    raise KeyError from e
            except KeyError as e:
                raise z from e
        def outer_raise():
            inner_raise() # Marker
        blocks = boundaries.split(self.get_report(outer_raise))
        self.assertEqual(len(blocks), 3)
        self.assertEqual(blocks[1], cause_message)
        # The first block is the KeyError raised from the ZeroDivisionError
        self.assertIn('raise KeyError from e', blocks[0])
        self.assertNotIn('1/0', blocks[0])
        # The second block (apart from the boundary) is the ZeroDivisionError
        # re-raised from the KeyError
        self.assertIn('inner_raise() # Marker', blocks[2])
        self.check_zero_div(blocks[2])

    @unittest.skipIf(support.use_old_parser(), "Pegen is arguably better here, so no need to fix this")
    def test_syntax_error_offset_at_eol(self):
        # See #10186.
        def e():
            raise SyntaxError('', ('', 0, 5, 'hello'))
        msg = self.get_report(e).splitlines()
        self.assertEqual(msg[-2], "        ^")
        def e():
            exec("x = 5 | 4 |")
        msg = self.get_report(e).splitlines()
        self.assertEqual(msg[-2], '               ^')

    def test_syntax_error_no_lineno(self):
        # See #34463.

        # Without filename
        e = SyntaxError('bad syntax')
        msg = self.get_report(e).splitlines()
        self.assertEqual(msg,
            ['SyntaxError: bad syntax'])
        e.lineno = 100
        msg = self.get_report(e).splitlines()
        self.assertEqual(msg,
            ['  File "<string>", line 100', 'SyntaxError: bad syntax'])

        # With filename
        e = SyntaxError('bad syntax')
        e.filename = 'myfile.py'

        msg = self.get_report(e).splitlines()
        self.assertEqual(msg,
            ['SyntaxError: bad syntax (myfile.py)'])
        e.lineno = 100
        msg = self.get_report(e).splitlines()
        self.assertEqual(msg,
            ['  File "myfile.py", line 100', 'SyntaxError: bad syntax'])

    def test_message_none(self):
        # A message that looks like "None" should not be treated specially
        err = self.get_report(Exception(None))
        self.assertIn('Exception: None\n', err)
        err = self.get_report(Exception('None'))
        self.assertIn('Exception: None\n', err)
        err = self.get_report(Exception())
        self.assertIn('Exception\n', err)
        err = self.get_report(Exception(''))
        self.assertIn('Exception\n', err)

    def test_exception_modulename_not_unicode(self):
        class X(Exception):
            def __str__(self):
                return "I am X"

        X.__module__ = 42

        err = self.get_report(X())
        exp = f'<unknown>.{X.__qualname__}: I am X\n'
        self.assertEqual(exp, err)

    def test_syntax_error_various_offsets(self):
        for offset in range(-5, 10):
            for add in [0, 2]:
                text = " "*add + "text%d" % offset
                expected = ['  File "file.py", line 1']
                if offset < 1:
                    expected.append("    %s" % text.lstrip())
                elif offset <= 6:
                    expected.append("    %s" % text.lstrip())
                    expected.append("    %s^" % (" "*(offset-1)))
                else:
                    expected.append("    %s" % text.lstrip())
                    expected.append("    %s^" % (" "*5))
                expected.append("SyntaxError: msg")
                expected.append("")
                err = self.get_report(SyntaxError("msg", ("file.py", 1, offset+add, text)))
                exp = "\n".join(expected)
                self.assertEqual(exp, err)

    def test_format_exception_only_qualname(self):
        class A:
            class B:
                class X(Exception):
                    def __str__(self):
                        return "I am X"
                    pass
        err = self.get_report(A.B.X())
        str_value = 'I am X'
        str_name = '.'.join([A.B.X.__module__, A.B.X.__qualname__])
        exp = "%s: %s\n" % (str_name, str_value)
        self.assertEqual(exp, err)
예제 #17
0
 def test_invalid_syntax_error_message(self):
     err_msg = "invalid syntax" if use_old_parser(
     ) else "f-string: invalid syntax"
     with self.assertRaisesRegex(SyntaxError, err_msg):
         compile("f'{a $ b}'", "?", "exec")
예제 #18
0
    >>> z,(*x),y = 1, 2, 4 # doctest:+ELLIPSIS
    Traceback (most recent call last):
      ...
    SyntaxError: can't use starred expression here

    >>> z,(*x) = 1, 2 # doctest:+ELLIPSIS
    Traceback (most recent call last):
      ...
    SyntaxError: can't use starred expression here

    >>> ((*x),y) = 1, 2 # doctest:+ELLIPSIS
    Traceback (most recent call last):
      ...
    SyntaxError: can't use starred expression here
"""

if use_old_parser():
    __test__ = {'doctests': doctests}
else:
    __test__ = {'doctests': doctests + new_parser_doctests}


def test_main(verbose=False):
    from test import support
    from test import test_unpack_ex
    support.run_doctest(test_unpack_ex, verbose)


if __name__ == "__main__":
    test_main(verbose=True)
예제 #19
0
        self.assertEqual(f'{d[a]}', 'integer')
        self.assertEqual('{d[a]}'.format(d=d), 'string')
        self.assertEqual('{d[0]}'.format(d=d), 'integer')

    def test_errors(self):
        # see issue 26287
        self.assertAllRaise(TypeError, 'unsupported', [
            r"f'{(lambda: 0):x}'",
            r"f'{(0,):x}'",
        ])
        self.assertAllRaise(ValueError, 'Unknown format code', [
            r"f'{1000:j}'",
            r"f'{1000:j}'",
        ])

    @unittest.skipIf(use_old_parser(),
                     "The old parser only supports <fstring> as the filename")
    def test_filename_in_syntaxerror(self):
        # see issue 38964
        with temp_cwd() as cwd:
            file_path = os.path.join(cwd, 't.py')
            with open(file_path, 'w') as f:
                f.write('f"{a b}"')  # This generates a SyntaxError
            _, _, stderr = assert_python_failure(file_path)
        self.assertIn(file_path, stderr.decode('utf-8'))

    def test_loop(self):
        for i in range(1000):
            self.assertEqual(f'i:{i}', 'i:' + str(i))

    def test_dict(self):
예제 #20
0
class SyntaxTestCase(unittest.TestCase):
    def _check_error(self,
                     code,
                     errtext,
                     filename="<testcase>",
                     mode="exec",
                     subclass=None,
                     lineno=None,
                     offset=None):
        """Check that compiling code raises SyntaxError with errtext.

        errtest is a regular expression that must be present in the
        test of the exception raised.  If subclass is specified it
        is the expected subclass of SyntaxError (e.g. IndentationError).
        """
        try:
            compile(code, filename, mode)
        except SyntaxError as err:
            if subclass and not isinstance(err, subclass):
                self.fail("SyntaxError is not a %s" % subclass.__name__)
            mo = re.search(errtext, str(err))
            if mo is None:
                self.fail("SyntaxError did not contain %r" % (errtext, ))
            self.assertEqual(err.filename, filename)
            if lineno is not None:
                self.assertEqual(err.lineno, lineno)
            if offset is not None:
                self.assertEqual(err.offset, offset)
        else:
            self.fail("compile() did not raise SyntaxError")

    def test_assign_call(self):
        self._check_error("f() = 1", "assign")

    @unittest.skipIf(support.use_old_parser(),
                     "The old parser cannot generate these error messages")
    def test_assign_del(self):
        self._check_error("del (,)", "invalid syntax")
        self._check_error("del 1", "delete literal")
        self._check_error("del (1, 2)", "delete literal")
        self._check_error("del None", "delete None")
        self._check_error("del *x", "delete starred")
        self._check_error("del (*x)", "delete starred")
        self._check_error("del (*x,)", "delete starred")
        self._check_error("del [*x,]", "delete starred")
        self._check_error("del f()", "delete function call")
        self._check_error("del f(a, b)", "delete function call")
        self._check_error("del o.f()", "delete function call")
        self._check_error("del a[0]()", "delete function call")
        self._check_error("del x, f()", "delete function call")
        self._check_error("del f(), x", "delete function call")
        self._check_error("del [a, b, ((c), (d,), e.f())]",
                          "delete function call")
        self._check_error("del (a if True else b)", "delete conditional")
        self._check_error("del +a", "delete operator")
        self._check_error("del a, +b", "delete operator")
        self._check_error("del a + b", "delete operator")
        self._check_error("del (a + b, c)", "delete operator")
        self._check_error("del (c[0], a + b)", "delete operator")
        self._check_error("del a.b.c + 2", "delete operator")
        self._check_error("del a.b.c[0] + 2", "delete operator")
        self._check_error("del (a, b, (c, d.e.f + 2))", "delete operator")
        self._check_error("del [a, b, (c, d.e.f[0] + 2)]", "delete operator")
        self._check_error("del (a := 5)", "delete named expression")
        # We don't have a special message for this, but make sure we don't
        # report "cannot delete name"
        self._check_error("del a += b", "invalid syntax")

    def test_global_param_err_first(self):
        source = """if 1:
            def error(a):
                global a  # SyntaxError
            def error2():
                b = 1
                global b  # SyntaxError
            """
        self._check_error(source, "parameter and global", lineno=3)

    def test_nonlocal_param_err_first(self):
        source = """if 1:
            def error(a):
                nonlocal a  # SyntaxError
            def error2():
                b = 1
                global b  # SyntaxError
            """
        self._check_error(source, "parameter and nonlocal", lineno=3)

    def test_break_outside_loop(self):
        self._check_error("break", "outside loop")

    def test_yield_outside_function(self):
        self._check_error("if 0: yield", "outside function")
        self._check_error("if 0: yield\nelse:  x=1", "outside function")
        self._check_error("if 1: pass\nelse: yield", "outside function")
        self._check_error("while 0: yield", "outside function")
        self._check_error("while 0: yield\nelse:  x=1", "outside function")
        self._check_error("class C:\n  if 0: yield", "outside function")
        self._check_error("class C:\n  if 1: pass\n  else: yield",
                          "outside function")
        self._check_error("class C:\n  while 0: yield", "outside function")
        self._check_error("class C:\n  while 0: yield\n  else:  x = 1",
                          "outside function")

    def test_return_outside_function(self):
        self._check_error("if 0: return", "outside function")
        self._check_error("if 0: return\nelse:  x=1", "outside function")
        self._check_error("if 1: pass\nelse: return", "outside function")
        self._check_error("while 0: return", "outside function")
        self._check_error("class C:\n  if 0: return", "outside function")
        self._check_error("class C:\n  while 0: return", "outside function")
        self._check_error("class C:\n  while 0: return\n  else:  x=1",
                          "outside function")
        self._check_error("class C:\n  if 0: return\n  else: x= 1",
                          "outside function")
        self._check_error("class C:\n  if 1: pass\n  else: return",
                          "outside function")

    def test_break_outside_loop(self):
        self._check_error("if 0: break", "outside loop")
        self._check_error("if 0: break\nelse:  x=1", "outside loop")
        self._check_error("if 1: pass\nelse: break", "outside loop")
        self._check_error("class C:\n  if 0: break", "outside loop")
        self._check_error("class C:\n  if 1: pass\n  else: break",
                          "outside loop")

    def test_continue_outside_loop(self):
        self._check_error("if 0: continue", "not properly in loop")
        self._check_error("if 0: continue\nelse:  x=1", "not properly in loop")
        self._check_error("if 1: pass\nelse: continue", "not properly in loop")
        self._check_error("class C:\n  if 0: continue", "not properly in loop")
        self._check_error("class C:\n  if 1: pass\n  else: continue",
                          "not properly in loop")

    def test_unexpected_indent(self):
        self._check_error("foo()\n bar()\n",
                          "unexpected indent",
                          subclass=IndentationError)

    def test_no_indent(self):
        self._check_error("if 1:\nfoo()",
                          "expected an indented block",
                          subclass=IndentationError)

    def test_bad_outdent(self):
        self._check_error("if 1:\n  foo()\n bar()",
                          "unindent does not match .* level",
                          subclass=IndentationError)

    def test_kwargs_last(self):
        self._check_error("int(base=10, '2')",
                          "positional argument follows keyword argument")

    def test_kwargs_last2(self):
        self._check_error(
            "int(**{'base': 10}, '2')", "positional argument follows "
            "keyword argument unpacking")

    def test_kwargs_last3(self):
        self._check_error(
            "int(**{'base': 10}, *['2'])",
            "iterable argument unpacking follows "
            "keyword argument unpacking")
예제 #21
0
class SyntaxTestCase(unittest.TestCase):
    def _check_error(self,
                     code,
                     errtext,
                     filename="<testcase>",
                     mode="exec",
                     subclass=None,
                     lineno=None,
                     offset=None):
        """Check that compiling code raises SyntaxError with errtext.

        errtest is a regular expression that must be present in the
        test of the exception raised.  If subclass is specified it
        is the expected subclass of SyntaxError (e.g. IndentationError).
        """
        try:
            compile(code, filename, mode)
        except SyntaxError as err:
            if subclass and not isinstance(err, subclass):
                self.fail("SyntaxError is not a %s" % subclass.__name__)
            mo = re.search(errtext, str(err))
            if mo is None:
                self.fail("SyntaxError did not contain %r" % (errtext, ))
            self.assertEqual(err.filename, filename)
            if lineno is not None:
                self.assertEqual(err.lineno, lineno)
            if offset is not None:
                self.assertEqual(err.offset, offset)
        else:
            self.fail("compile() did not raise SyntaxError")

    def test_curly_brace_after_primary_raises_immediately(self):
        self._check_error("f{", "invalid syntax", mode="single")

    def test_assign_call(self):
        self._check_error("f() = 1", "assign")

    @unittest.skipIf(support.use_old_parser(),
                     "The old parser cannot generate these error messages")
    def test_assign_del(self):
        self._check_error("del (,)", "invalid syntax")
        self._check_error("del 1", "delete literal")
        self._check_error("del (1, 2)", "delete literal")
        self._check_error("del None", "delete None")
        self._check_error("del *x", "delete starred")
        self._check_error("del (*x)", "use starred expression")
        self._check_error("del (*x,)", "delete starred")
        self._check_error("del [*x,]", "delete starred")
        self._check_error("del f()", "delete function call")
        self._check_error("del f(a, b)", "delete function call")
        self._check_error("del o.f()", "delete function call")
        self._check_error("del a[0]()", "delete function call")
        self._check_error("del x, f()", "delete function call")
        self._check_error("del f(), x", "delete function call")
        self._check_error("del [a, b, ((c), (d,), e.f())]",
                          "delete function call")
        self._check_error("del (a if True else b)", "delete conditional")
        self._check_error("del +a", "delete operator")
        self._check_error("del a, +b", "delete operator")
        self._check_error("del a + b", "delete operator")
        self._check_error("del (a + b, c)", "delete operator")
        self._check_error("del (c[0], a + b)", "delete operator")
        self._check_error("del a.b.c + 2", "delete operator")
        self._check_error("del a.b.c[0] + 2", "delete operator")
        self._check_error("del (a, b, (c, d.e.f + 2))", "delete operator")
        self._check_error("del [a, b, (c, d.e.f[0] + 2)]", "delete operator")
        self._check_error("del (a := 5)", "delete named expression")
        # We don't have a special message for this, but make sure we don't
        # report "cannot delete name"
        self._check_error("del a += b", "invalid syntax")

    def test_global_param_err_first(self):
        source = """if 1:
            def error(a):
                global a  # SyntaxError
            def error2():
                b = 1
                global b  # SyntaxError
            """
        self._check_error(source, "parameter and global", lineno=3)

    def test_nonlocal_param_err_first(self):
        source = """if 1:
            def error(a):
                nonlocal a  # SyntaxError
            def error2():
                b = 1
                global b  # SyntaxError
            """
        self._check_error(source, "parameter and nonlocal", lineno=3)

    def test_break_outside_loop(self):
        self._check_error("break", "outside loop")

    def test_yield_outside_function(self):
        self._check_error("if 0: yield", "outside function")
        self._check_error("if 0: yield\nelse:  x=1", "outside function")
        self._check_error("if 1: pass\nelse: yield", "outside function")
        self._check_error("while 0: yield", "outside function")
        self._check_error("while 0: yield\nelse:  x=1", "outside function")
        self._check_error("class C:\n  if 0: yield", "outside function")
        self._check_error("class C:\n  if 1: pass\n  else: yield",
                          "outside function")
        self._check_error("class C:\n  while 0: yield", "outside function")
        self._check_error("class C:\n  while 0: yield\n  else:  x = 1",
                          "outside function")

    def test_return_outside_function(self):
        self._check_error("if 0: return", "outside function")
        self._check_error("if 0: return\nelse:  x=1", "outside function")
        self._check_error("if 1: pass\nelse: return", "outside function")
        self._check_error("while 0: return", "outside function")
        self._check_error("class C:\n  if 0: return", "outside function")
        self._check_error("class C:\n  while 0: return", "outside function")
        self._check_error("class C:\n  while 0: return\n  else:  x=1",
                          "outside function")
        self._check_error("class C:\n  if 0: return\n  else: x= 1",
                          "outside function")
        self._check_error("class C:\n  if 1: pass\n  else: return",
                          "outside function")

    def test_break_outside_loop(self):
        self._check_error("if 0: break", "outside loop")
        self._check_error("if 0: break\nelse:  x=1", "outside loop")
        self._check_error("if 1: pass\nelse: break", "outside loop")
        self._check_error("class C:\n  if 0: break", "outside loop")
        self._check_error("class C:\n  if 1: pass\n  else: break",
                          "outside loop")

    def test_continue_outside_loop(self):
        self._check_error("if 0: continue", "not properly in loop")
        self._check_error("if 0: continue\nelse:  x=1", "not properly in loop")
        self._check_error("if 1: pass\nelse: continue", "not properly in loop")
        self._check_error("class C:\n  if 0: continue", "not properly in loop")
        self._check_error("class C:\n  if 1: pass\n  else: continue",
                          "not properly in loop")

    def test_unexpected_indent(self):
        self._check_error("foo()\n bar()\n",
                          "unexpected indent",
                          subclass=IndentationError)

    def test_no_indent(self):
        self._check_error("if 1:\nfoo()",
                          "expected an indented block",
                          subclass=IndentationError)

    def test_bad_outdent(self):
        self._check_error("if 1:\n  foo()\n bar()",
                          "unindent does not match .* level",
                          subclass=IndentationError)

    def test_kwargs_last(self):
        self._check_error("int(base=10, '2')",
                          "positional argument follows keyword argument")

    def test_kwargs_last2(self):
        self._check_error(
            "int(**{'base': 10}, '2')", "positional argument follows "
            "keyword argument unpacking")

    def test_kwargs_last3(self):
        self._check_error(
            "int(**{'base': 10}, *['2'])",
            "iterable argument unpacking follows "
            "keyword argument unpacking")

    def test_empty_line_after_linecont(self):
        # See issue-40847
        s = r"""\
pass
        \

pass
"""
        try:
            compile(s, '<string>', 'exec')
        except SyntaxError:
            self.fail(
                "Empty line after a line continuation character is valid.")

    @support.cpython_only
    def test_nested_named_except_blocks(self):
        code = ""
        for i in range(12):
            code += f"{'    '*i}try:\n"
            code += f"{'    '*(i+1)}raise Exception\n"
            code += f"{'    '*i}except Exception as e:\n"
        code += f"{' '*4*12}pass"
        self._check_error(code, "too many statically nested blocks")

    def test_barry_as_flufl_with_syntax_errors(self):
        # The "barry_as_flufl" rule can produce some "bugs-at-a-distance" if
        # is reading the wrong token in the presence of syntax errors later
        # in the file. See bpo-42214 for more information.
        code = """
def func1():
    if a != b:
        raise ValueError

def func2():
    try
        return 1
    finally:
        pass
"""
        self._check_error(code, "invalid syntax")

    def test_invalid_line_continuation_error_position(self):
        self._check_error(
            r"a = 3 \ 4",
            "unexpected character after line continuation character",
            lineno=1,
            offset=8)
        self._check_error(
            '1,\\#\n2',
            "unexpected character after line continuation character",
            lineno=1,
            offset=4)
        self._check_error(
            '\nfgdfgf\n1,\\#\n2\n',
            "unexpected character after line continuation character",
            lineno=3,
            offset=4)

    def test_invalid_line_continuation_left_recursive(self):
        # Check bpo-42218: SyntaxErrors following left-recursive rules
        # (t_primary_raw in this case) need to be tested explicitly
        self._check_error(
            "A.\u018a\\ ",
            "unexpected character after line continuation character")
        self._check_error("A.\u03bc\\\n", "unexpected EOF while parsing")

    @support.cpython_only
    def test_syntax_error_on_deeply_nested_blocks(self):
        # This raises a SyntaxError, it used to raise a SystemError. Context
        # for this change can be found on issue #27514

        # In 2.5 there was a missing exception and an assert was triggered in a
        # debug build.  The number of blocks must be greater than CO_MAXBLOCKS.
        # SF #1565514

        source = """
while 1:
 while 2:
  while 3:
   while 4:
    while 5:
     while 6:
      while 8:
       while 9:
        while 10:
         while 11:
          while 12:
           while 13:
            while 14:
             while 15:
              while 16:
               while 17:
                while 18:
                 while 19:
                  while 20:
                   while 21:
                    while 22:
                     break
"""
        self._check_error(source, "too many statically nested blocks")

    @support.cpython_only
    def test_error_on_parser_stack_overflow(self):
        source = "-" * 100000 + "4"
        for mode in ["exec", "eval", "single"]:
            with self.subTest(mode=mode):
                with self.assertRaises(MemoryError):
                    compile(source, "<string>", mode)