From e3bfe69ff41faa31bfcdd88792e191977b6358af Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Mon, 18 May 2026 16:39:30 +0300 Subject: [PATCH 01/10] Update `test_grammar.py` to 3.14.5 --- Lib/test/test_grammar.py | 569 ++++++++++++++++++++++----------------- 1 file changed, 328 insertions(+), 241 deletions(-) diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 91eb6cc58f3..d16c626010c 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -1,11 +1,13 @@ # Python test set -- part 1, grammar. # This just tests whether the parser accepts them all. -from test.support import check_syntax_error +from test.support import check_syntax_error, skip_wasi_stack_overflow from test.support import import_helper +import annotationlib import inspect import unittest import sys +import textwrap import warnings # testing import * from sys import * @@ -112,7 +114,7 @@ def test_underscore_literals(self): # Sanity check: no literal begins with an underscore self.assertRaises(NameError, eval, "_0") - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_bad_numerical_literals(self): check = self.check_syntax_error check("0b12", "invalid digit '2' in binary literal") @@ -135,7 +137,7 @@ def test_bad_numerical_literals(self): check("1e2_", "invalid decimal literal") check("1e+", "invalid decimal literal") - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_end_of_numerical_literals(self): def check(test, error=False): with self.subTest(expr=test): @@ -216,6 +218,27 @@ def test_string_literals(self): ' self.assertEqual(x, y) + def test_string_prefixes(self): + def check(s): + parsed = eval(s) + self.assertIs(type(parsed), str) + self.assertGreater(len(parsed), 0) + + check("u'abc'") + check("r'abc\t'") + check("rf'abc\a {1 + 1}'") + check("fr'abc\a {1 + 1}'") + + def test_bytes_prefixes(self): + def check(s): + parsed = eval(s) + self.assertIs(type(parsed), bytes) + self.assertGreater(len(parsed), 0) + + check("b'abc'") + check("br'abc\t'") + check("rb'abc\a'") + def test_ellipsis(self): x = ... self.assertTrue(x is Ellipsis) @@ -228,17 +251,20 @@ def test_eof_error(self): compile(s, "", "exec") self.assertIn("was never closed", str(cm.exception)) -var_annot_global: int # a global annotated is necessary for test_var_annot + @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: SyntaxError not raised + @skip_wasi_stack_overflow() + def test_max_level(self): + # Macro defined in Parser/lexer/state.h + MAXLEVEL = 200 + + result = eval("(" * MAXLEVEL + ")" * MAXLEVEL) + self.assertEqual(result, ()) -# custom namespace for testing __annotations__ + with self.assertRaises(SyntaxError) as cm: + eval("(" * (MAXLEVEL + 1) + ")" * (MAXLEVEL + 1)) + self.assertStartsWith(str(cm.exception), 'too many nested parentheses') -class CNS: - def __init__(self): - self._dct = {} - def __setitem__(self, item, value): - self._dct[item.lower()] = value - def __getitem__(self, item): - return self._dct[item] +var_annot_global: int # a global annotated is necessary for test_var_annot class GrammarTests(unittest.TestCase): @@ -272,7 +298,7 @@ def one(): my_lst[one()-1]: int = 5 self.assertEqual(my_lst, [5]) - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_var_annot_syntax_errors(self): # parser pass check_syntax_error(self, "def f: int") @@ -371,24 +397,12 @@ class F(C, A): self.assertEqual(E.__annotations__, {}) self.assertEqual(F.__annotations__, {}) - - @unittest.expectedFailure # TODO: RUSTPYTHON - def test_var_annot_metaclass_semantics(self): - class CMeta(type): - @classmethod - def __prepare__(metacls, name, bases, **kwds): - return {'__annotations__': CNS()} - class CC(metaclass=CMeta): - XX: 'ANNOT' - self.assertEqual(CC.__annotations__['xx'], 'ANNOT') - - @unittest.expectedFailure # TODO: RUSTPYTHON def test_var_annot_module_semantics(self): self.assertEqual(test.__annotations__, {}) self.assertEqual(ann_module.__annotations__, - {1: 2, 'x': int, 'y': str, 'f': typing.Tuple[int, int], 'u': int | float}) + {'x': int, 'y': str, 'f': typing.Tuple[int, int], 'u': int | float}) self.assertEqual(ann_module.M.__annotations__, - {'123': 123, 'o': type}) + {'o': type}) self.assertEqual(ann_module2.__annotations__, {}) def test_var_annot_in_module(self): @@ -402,55 +416,14 @@ def test_var_annot_in_module(self): with self.assertRaises(NameError): ann_module3.D_bad_ann(5) - @unittest.expectedFailure # TODO: RUSTPYTHON def test_var_annot_simple_exec(self): - gns = {}; lns= {} + gns = {}; lns = {} exec("'docstring'\n" - "__annotations__[1] = 2\n" "x: int = 5\n", gns, lns) - self.assertEqual(lns["__annotations__"], {1: 2, 'x': int}) - with self.assertRaises(KeyError): - gns['__annotations__'] - - @unittest.expectedFailure # TODO: RUSTPYTHON - def test_var_annot_custom_maps(self): - # tests with custom locals() and __annotations__ - ns = {'__annotations__': CNS()} - exec('X: int; Z: str = "Z"; (w): complex = 1j', ns) - self.assertEqual(ns['__annotations__']['x'], int) - self.assertEqual(ns['__annotations__']['z'], str) - with self.assertRaises(KeyError): - ns['__annotations__']['w'] - nonloc_ns = {} - class CNS2: - def __init__(self): - self._dct = {} - def __setitem__(self, item, value): - nonlocal nonloc_ns - self._dct[item] = value - nonloc_ns[item] = value - def __getitem__(self, item): - return self._dct[item] - exec('x: int = 1', {}, CNS2()) - self.assertEqual(nonloc_ns['__annotations__']['x'], int) - - @unittest.expectedFailure # TODO: RUSTPYTHON - def test_var_annot_refleak(self): - # complex case: custom locals plus custom __annotations__ - # this was causing refleak - cns = CNS() - nonloc_ns = {'__annotations__': cns} - class CNS2: - def __init__(self): - self._dct = {'__annotations__': cns} - def __setitem__(self, item, value): - nonlocal nonloc_ns - self._dct[item] = value - nonloc_ns[item] = value - def __getitem__(self, item): - return self._dct[item] - exec('X: str', {}, CNS2()) - self.assertEqual(nonloc_ns['__annotations__']['x'], str) + self.assertNotIn('__annotate__', gns) + + gns.update(lns) # __annotate__ looks at globals + self.assertEqual(lns["__annotate__"](annotationlib.Format.VALUE), {'x': int}) def test_var_annot_rhs(self): ns = {} @@ -778,7 +751,7 @@ def test_expr_stmt(self): # Check the heuristic for print & exec covers significant cases # As well as placing some limits on false positives - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_former_statements_refer_to_builtins(self): keywords = "print", "exec" # Cases where we want the custom error @@ -905,188 +878,294 @@ def g3(): self.assertEqual(y, (1, 2, 3), "unparenthesized star expr return") check_syntax_error(self, "class foo:return 1") - def test_break_in_finally(self): - count = 0 - while count < 2: - count += 1 - try: - pass - finally: - break - self.assertEqual(count, 1) + def test_control_flow_in_finally(self): - count = 0 - while count < 2: - count += 1 - try: - continue - finally: - break - self.assertEqual(count, 1) + def run_case(self, src, expected): + with warnings.catch_warnings(): + warnings.simplefilter('ignore', SyntaxWarning) + g, l = {}, { 'self': self } + exec(textwrap.dedent(src), g, l) + self.assertEqual(expected, l['result']) - count = 0 - while count < 2: - count += 1 - try: - 1/0 - finally: - break - self.assertEqual(count, 1) - for count in [0, 1]: - self.assertEqual(count, 0) - try: - pass - finally: - break - self.assertEqual(count, 0) + # *********** Break in finally *********** - for count in [0, 1]: - self.assertEqual(count, 0) - try: - continue - finally: - break - self.assertEqual(count, 0) + run_case( + self, + """ + result = 0 + while result < 2: + result += 1 + try: + pass + finally: + break + """, + 1) + + run_case( + self, + """ + result = 0 + while result < 2: + result += 1 + try: + continue + finally: + break + """, + 1) + + run_case( + self, + """ + result = 0 + while result < 2: + result += 1 + try: + 1/0 + finally: + break + """, + 1) + + run_case( + self, + """ + for result in [0, 1]: + self.assertEqual(result, 0) + try: + pass + finally: + break + """, + 0) + + run_case( + self, + """ + for result in [0, 1]: + self.assertEqual(result, 0) + try: + continue + finally: + break + """, + 0) + + run_case( + self, + """ + for result in [0, 1]: + self.assertEqual(result, 0) + try: + 1/0 + finally: + break + """, + 0) - for count in [0, 1]: - self.assertEqual(count, 0) - try: - 1/0 - finally: + + # *********** Continue in finally *********** + + run_case( + self, + """ + result = 0 + while result < 2: + result += 1 + try: + pass + finally: + continue break - self.assertEqual(count, 0) + """, + 2) - def test_continue_in_finally(self): - count = 0 - while count < 2: - count += 1 - try: - pass - finally: - continue - break - self.assertEqual(count, 2) - count = 0 - while count < 2: - count += 1 - try: + run_case( + self, + """ + result = 0 + while result < 2: + result += 1 + try: + break + finally: + continue + """, + 2) + + run_case( + self, + """ + result = 0 + while result < 2: + result += 1 + try: + 1/0 + finally: + continue break - finally: - continue - self.assertEqual(count, 2) + """, + 2) - count = 0 - while count < 2: - count += 1 - try: - 1/0 - finally: - continue - break - self.assertEqual(count, 2) + run_case( + self, + """ + for result in [0, 1]: + try: + pass + finally: + continue + break + """, + 1) - for count in [0, 1]: - try: - pass - finally: - continue - break - self.assertEqual(count, 1) + run_case( + self, + """ + for result in [0, 1]: + try: + break + finally: + continue + """, + 1) - for count in [0, 1]: - try: + run_case( + self, + """ + for result in [0, 1]: + try: + 1/0 + finally: + continue break - finally: - continue - self.assertEqual(count, 1) + """, + 1) - for count in [0, 1]: - try: - 1/0 - finally: - continue - break - self.assertEqual(count, 1) - def test_return_in_finally(self): - def g1(): - try: - pass - finally: - return 1 - self.assertEqual(g1(), 1) + # *********** Return in finally *********** - def g2(): - try: - return 2 - finally: - return 3 - self.assertEqual(g2(), 3) + run_case( + self, + """ + def f(): + try: + pass + finally: + return 1 + result = f() + """, + 1) + + run_case( + self, + """ + def f(): + try: + return 2 + finally: + return 3 + result = f() + """, + 3) + + run_case( + self, + """ + def f(): + try: + 1/0 + finally: + return 4 + result = f() + """, + 4) - def g3(): - try: - 1/0 - finally: - return 4 - self.assertEqual(g3(), 4) + # See issue #37830 + run_case( + self, + """ + def break_in_finally_after_return1(x): + for count in [0, 1]: + count2 = 0 + while count2 < 20: + count2 += 10 + try: + return count + count2 + finally: + if x: + break + return 'end', count, count2 + + self.assertEqual(break_in_finally_after_return1(False), 10) + self.assertEqual(break_in_finally_after_return1(True), ('end', 1, 10)) + result = True + """, + True) + + + run_case( + self, + """ + def break_in_finally_after_return2(x): + for count in [0, 1]: + for count2 in [10, 20]: + try: + return count + count2 + finally: + if x: + break + return 'end', count, count2 + + self.assertEqual(break_in_finally_after_return2(False), 10) + self.assertEqual(break_in_finally_after_return2(True), ('end', 1, 10)) + result = True + """, + True) - def test_break_in_finally_after_return(self): # See issue #37830 - def g1(x): - for count in [0, 1]: - count2 = 0 - while count2 < 20: - count2 += 10 + run_case( + self, + """ + def continue_in_finally_after_return1(x): + count = 0 + while count < 100: + count += 1 try: - return count + count2 + return count finally: if x: - break - return 'end', count, count2 - self.assertEqual(g1(False), 10) - self.assertEqual(g1(True), ('end', 1, 10)) - - def g2(x): - for count in [0, 1]: - for count2 in [10, 20]: + continue + return 'end', count + + self.assertEqual(continue_in_finally_after_return1(False), 1) + self.assertEqual(continue_in_finally_after_return1(True), ('end', 100)) + result = True + """, + True) + + run_case( + self, + """ + def continue_in_finally_after_return2(x): + for count in [0, 1]: try: - return count + count2 + return count finally: if x: - break - return 'end', count, count2 - self.assertEqual(g2(False), 10) - self.assertEqual(g2(True), ('end', 1, 10)) - - def test_continue_in_finally_after_return(self): - # See issue #37830 - def g1(x): - count = 0 - while count < 100: - count += 1 - try: - return count - finally: - if x: - continue - return 'end', count - self.assertEqual(g1(False), 1) - self.assertEqual(g1(True), ('end', 100)) + continue + return 'end', count - def g2(x): - for count in [0, 1]: - try: - return count - finally: - if x: - continue - return 'end', count - self.assertEqual(g2(False), 0) - self.assertEqual(g2(True), ('end', 1)) + self.assertEqual(continue_in_finally_after_return2(False), 0) + self.assertEqual(continue_in_finally_after_return2(True), ('end', 1)) + result = True + """, + True) - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_yield(self): # Allowed as standalone statement def g(): yield 1 @@ -1126,7 +1205,7 @@ def g(): rest = 4, 5, 6; yield 1, 2, 3, *rest # Check annotation refleak on SyntaxError check_syntax_error(self, "def g(a:(yield)): pass") - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_yield_in_comprehensions(self): # Check yield in comprehensions def g(): [x for x in [(yield 1)]] @@ -1223,7 +1302,7 @@ def test_assert_failures(self): else: self.fail("AssertionError not raised by 'assert False'") - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_assert_syntax_warnings(self): # Ensure that we warn users if they provide a non-zero length tuple as # the assertion test. @@ -1238,7 +1317,7 @@ def test_assert_syntax_warnings(self): compile('assert x, "msg"', '', 'exec') compile('assert False, "msg"', '', 'exec') - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_assert_warning_promotes_to_syntax_error(self): # If SyntaxWarning is configured to be an error, it actually raises a # SyntaxError. @@ -1338,6 +1417,9 @@ def test_try(self): else: pass try: 1/0 except (EOFError, TypeError, ZeroDivisionError): pass + # TODO: RUSTPYTHON; SyntaxError: multiple exception types must be parenthesized + # try: 1/0 + # except EOFError, TypeError, ZeroDivisionError: pass try: 1/0 except (EOFError, TypeError, ZeroDivisionError) as msg: pass try: pass @@ -1346,8 +1428,6 @@ def test_try(self): compile("try:\n pass\nexcept Exception as a.b:\n pass", "?", "exec") compile("try:\n pass\nexcept Exception as a[b]:\n pass", "?", "exec") - # TODO: RUSTPYTHON - ''' def test_try_star(self): ### try_stmt: 'try': suite (except_star_clause : suite) + ['else' ':' suite] ### except_star_clause: 'except*' expr ['as' NAME] @@ -1363,6 +1443,9 @@ def test_try_star(self): else: pass try: 1/0 except* (EOFError, TypeError, ZeroDivisionError): pass + # TODO: RUSTPYTHON; SyntaxError: multiple exception types must be parenthesized + # try: 1/0 + # except* EOFError, TypeError, ZeroDivisionError: pass try: 1/0 except* (EOFError, TypeError, ZeroDivisionError) as msg: pass try: pass @@ -1371,7 +1454,6 @@ def test_try_star(self): compile("try:\n pass\nexcept* Exception as a.b:\n pass", "?", "exec") compile("try:\n pass\nexcept* Exception as a[b]:\n pass", "?", "exec") compile("try:\n pass\nexcept*:\n pass", "?", "exec") - ''' def test_suite(self): # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT @@ -1416,7 +1498,7 @@ def test_comparison(self): if 1 not in (): pass if 1 < 1 > 1 == 1 >= 1 <= 1 != 1 in 1 not in x is x is not x: pass - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_comparison_is_literal(self): def check(test, msg): self.check_syntax_warning(test, msg) @@ -1446,7 +1528,7 @@ def check(test, msg): compile('True is x', '', 'exec') compile('... is x', '', 'exec') - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_warn_missed_comma(self): def check(test): self.check_syntax_warning(test, msg) @@ -1471,6 +1553,8 @@ def check(test): check('[None (3, 4)]') check('[True (3, 4)]') check('[... (3, 4)]') + check('[t"{x}" (3, 4)]') + check('[t"x={x}" (3, 4)]') msg=r'is not subscriptable; perhaps you missed a comma\?' check('[{1, 2} [i, j]]') @@ -1483,6 +1567,8 @@ def check(test): check('[None [i, j]]') check('[True [i, j]]') check('[... [i, j]]') + check('[t"{x}" [i, j]]') + check('[t"x={x}" [i, j]]') msg=r'indices must be integers or slices, not tuple; perhaps you missed a comma\?' check('[(1, 2) [i, j]]') @@ -1513,6 +1599,9 @@ def check(test): check('[[1, 2] [f"{x}"]]') check('[[1, 2] [f"x={x}"]]') check('[[1, 2] ["abc"]]') + msg=r'indices must be integers or slices, not string.templatelib.Template;' + check('[[1, 2] [t"{x}"]]') + check('[[1, 2] [t"x={x}"]]') msg=r'indices must be integers or slices, not' check('[[1, 2] [b"abc"]]') check('[[1, 2] [12.3]]') @@ -1623,8 +1712,6 @@ def test_atoms(self): ### testlist: test (',' test)* [','] # These have been exercised enough above - # TODO: RUSTPYTHON - ''' def test_classdef(self): # 'class' NAME ['(' [testlist] ')'] ':' suite class B: pass @@ -1649,7 +1736,8 @@ class G: pass class H: pass @d := class_decorator class I: pass - @lambda c: class_decorator(c) + # TODO: RUSTPYTHON; SyntaxError: the symbol 'class_decorator' must be present in the symbol table + # @lambda c: class_decorator(c) class J: pass @[..., class_decorator, ...][1] class K: pass @@ -1657,7 +1745,6 @@ class K: pass class L: pass @[class_decorator][0].__call__.__call__ class M: pass - ''' def test_dictcomps(self): # dictorsetmaker: ( (test ':' test (comp_for | From 1c87dddd9b20250b8e8a9c44524ed0932c502b10 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 19 May 2026 10:02:26 +0300 Subject: [PATCH 02/10] Fix failing test --- Lib/test/test_grammar.py | 10 ++++------ crates/codegen/src/compile.rs | 9 --------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index d16c626010c..cf90de7b115 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -1417,9 +1417,8 @@ def test_try(self): else: pass try: 1/0 except (EOFError, TypeError, ZeroDivisionError): pass - # TODO: RUSTPYTHON; SyntaxError: multiple exception types must be parenthesized - # try: 1/0 - # except EOFError, TypeError, ZeroDivisionError: pass + try: 1/0 + except EOFError, TypeError, ZeroDivisionError: pass try: 1/0 except (EOFError, TypeError, ZeroDivisionError) as msg: pass try: pass @@ -1443,9 +1442,8 @@ def test_try_star(self): else: pass try: 1/0 except* (EOFError, TypeError, ZeroDivisionError): pass - # TODO: RUSTPYTHON; SyntaxError: multiple exception types must be parenthesized - # try: 1/0 - # except* EOFError, TypeError, ZeroDivisionError: pass + try: 1/0 + except* EOFError, TypeError, ZeroDivisionError: pass try: 1/0 except* (EOFError, TypeError, ZeroDivisionError) as msg: pass try: pass diff --git a/crates/codegen/src/compile.rs b/crates/codegen/src/compile.rs index 81349c2f078..421ff84d1c6 100644 --- a/crates/codegen/src/compile.rs +++ b/crates/codegen/src/compile.rs @@ -4446,15 +4446,6 @@ impl Compiler { // Compile exception type if let Some(exc_type) = type_ { - // Check for unparenthesized tuple - if let ast::Expr::Tuple(ast::ExprTuple { elts, range, .. }) = exc_type.as_ref() - && let Some(first) = elts.first() - && range.start().to_u32() == first.range().start().to_u32() - { - return Err(self.error(CodegenErrorType::SyntaxError( - "multiple exception types must be parenthesized".to_owned(), - ))); - } self.compile_expression(exc_type)?; } else { return Err(self.error(CodegenErrorType::SyntaxError( From c05010824279490275e87d3053f502356fc673c0 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 19 May 2026 11:39:44 +0300 Subject: [PATCH 03/10] Update `test_syntax.py` to 3.14.5 --- Lib/test/test_syntax.py | 775 ++++++++++++++++++++++++++++++++++------ 1 file changed, 675 insertions(+), 100 deletions(-) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 98246ac2214..de8c94fe8d2 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -59,6 +59,18 @@ Traceback (most recent call last): SyntaxError: cannot assign to __debug__ +>>> def __debug__(): pass +Traceback (most recent call last): +SyntaxError: cannot assign to __debug__ + +>>> async def __debug__(): pass +Traceback (most recent call last): +SyntaxError: cannot assign to __debug__ + +>>> class __debug__: pass +Traceback (most recent call last): +SyntaxError: cannot assign to __debug__ + >>> del __debug__ Traceback (most recent call last): SyntaxError: cannot delete __debug__ @@ -156,6 +168,18 @@ Traceback (most recent call last): SyntaxError: expected 'else' after 'if' expression +>>> x = 1 if 1 else pass +Traceback (most recent call last): +SyntaxError: expected expression after 'else', but statement is given + +>>> x = pass if 1 else 1 +Traceback (most recent call last): +SyntaxError: expected expression before 'if', but statement is given + +>>> x = pass if 1 else pass +Traceback (most recent call last): +SyntaxError: expected expression before 'if', but statement is given + >>> if True: ... print("Hello" ... @@ -300,6 +324,12 @@ Traceback (most recent call last): SyntaxError: did you forget parentheses around the comprehension target? +# Incorrectly closed strings + +>>> "The interesting object "The important object" is very important" +Traceback (most recent call last): +SyntaxError: invalid syntax. Is this intended to be part of the string? + # Missing commas in literals collections should not # produce special error messages regarding missing # parentheses, but about missing commas instead @@ -605,8 +635,7 @@ Traceback (most recent call last): SyntaxError: parameter without a default follows parameter with a default ->>> # TODO: RUSTPYTHON ->>> import ast; ast.parse(''' # doctest: +SKIP +>>> import ast; ast.parse(''' ... def f( ... *, # type: int ... a, # type: int @@ -655,8 +684,7 @@ SyntaxError: Generator expression must be parenthesized >>> f((x for x in L), 1) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ->>> # TODO: RUSTPYTHON ->>> class C(x for x in L): # doctest: +SKIP +>>> class C(x for x in L): ... pass Traceback (most recent call last): SyntaxError: invalid syntax @@ -777,8 +805,7 @@ >>> f(x.y=1) Traceback (most recent call last): SyntaxError: expression cannot contain assignment, perhaps you meant "=="? ->>> # TODO: RUSTPYTHON ->>> f((x)=2) # doctest: +SKIP +>>> f((x)=2) Traceback (most recent call last): SyntaxError: expression cannot contain assignment, perhaps you meant "=="? >>> f(True=1) @@ -793,8 +820,10 @@ >>> f(__debug__=1) Traceback (most recent call last): SyntaxError: cannot assign to __debug__ ->>> # TODO: RUSTPYTHON ->>> __debug__: int # doctest: +SKIP +>>> __debug__: int +Traceback (most recent call last): +SyntaxError: cannot assign to __debug__ +>>> x.__debug__: int Traceback (most recent call last): SyntaxError: cannot assign to __debug__ >>> f(a=) @@ -836,7 +865,7 @@ SyntaxError: 'function call' is an illegal expression for augmented assignment -Test continue in finally in weird combinations. +Test control flow in finally continue in for loop under finally should be ok. @@ -850,51 +879,63 @@ >>> test() 9 -continue in a finally should be ok. +break in for loop under finally should be ok. >>> def test(): - ... for abc in range(10): - ... try: - ... pass - ... finally: - ... continue - ... print(abc) + ... try: + ... pass + ... finally: + ... for abc in range(10): + ... break + ... print(abc) >>> test() - 9 + 0 + +return in function under finally should be ok. >>> def test(): - ... for abc in range(10): - ... try: - ... pass - ... finally: - ... try: - ... continue - ... except: - ... pass - ... print(abc) + ... try: + ... pass + ... finally: + ... def f(): + ... return 42 + ... print(f()) >>> test() - 9 + 42 + +combine for loop and function def + +return in function under finally should be ok. >>> def test(): - ... for abc in range(10): - ... try: - ... pass - ... finally: - ... try: - ... pass - ... except: - ... continue - ... print(abc) + ... try: + ... pass + ... finally: + ... for i in range(10): + ... def f(): + ... return 42 + ... print(f()) >>> test() - 9 + 42 + + >>> def test(): + ... try: + ... pass + ... finally: + ... def f(): + ... for i in range(10): + ... return 42 + ... print(f()) + >>> test() + 42 A continue outside loop should not be allowed. >>> def foo(): ... try: - ... pass - ... finally: ... continue + ... finally: + ... pass Traceback (most recent call last): ... SyntaxError: 'continue' not properly in loop @@ -914,6 +955,18 @@ ... SyntaxError: 'break' outside loop +elif can't come after an else. + + >>> if a % 2 == 0: + ... pass + ... else: + ... pass + ... elif a % 2 == 1: + ... pass + Traceback (most recent call last): + ... + SyntaxError: 'elif' block follows an 'else' block + Misuse of the nonlocal and global statement can lead to a few unique syntax errors. >>> def f(): @@ -1155,7 +1208,7 @@ >>> with block ad something: ... pass Traceback (most recent call last): - SyntaxError: invalid syntax + SyntaxError: invalid syntax. Did you mean 'and'? >>> try ... pass @@ -1193,6 +1246,24 @@ Traceback (most recent call last): SyntaxError: expected ':' + >>> match x: + ... case a, __debug__, b: + ... pass + Traceback (most recent call last): + SyntaxError: cannot assign to __debug__ + + >>> match x: + ... case a, b, *__debug__: + ... pass + Traceback (most recent call last): + SyntaxError: cannot assign to __debug__ + + >>> match x: + ... case Foo(a, __debug__=1, b=2): + ... pass + Traceback (most recent call last): + SyntaxError: cannot assign to __debug__ + >>> if x = 3: ... pass Traceback (most recent call last): @@ -1286,6 +1357,15 @@ Traceback (most recent call last): SyntaxError: expected 'except' or 'finally' block +Custom error message for __debug__ as exception variable + + >>> try: + ... pass + ... except TypeError as __debug__: + ... pass + Traceback (most recent call last): + SyntaxError: cannot assign to __debug__ + Custom error message for try block mixing except and except* >>> try: @@ -1328,6 +1408,53 @@ Traceback (most recent call last): SyntaxError: cannot have both 'except' and 'except*' on the same 'try' +Better error message for using `except as` with not a name: + + >>> try: + ... pass + ... except TypeError as obj.attr: + ... pass + Traceback (most recent call last): + SyntaxError: cannot use except statement with attribute + + >>> try: + ... pass + ... except TypeError as obj[1]: + ... pass + Traceback (most recent call last): + SyntaxError: cannot use except statement with subscript + + >>> try: + ... pass + ... except* TypeError as (obj, name): + ... pass + Traceback (most recent call last): + SyntaxError: cannot use except* statement with tuple + + >>> try: + ... pass + ... except* TypeError as 1: + ... pass + Traceback (most recent call last): + SyntaxError: cannot use except* statement with literal + +Regression tests for gh-133999: + + >>> try: pass + ... except TypeError as name: raise from None + Traceback (most recent call last): + SyntaxError: invalid syntax + + >>> try: pass + ... except* TypeError as name: raise from None + Traceback (most recent call last): + SyntaxError: invalid syntax + + >>> match 1: + ... case 1 | 2 as abc: raise from None + Traceback (most recent call last): + SyntaxError: invalid syntax + Ensure that early = are not matched by the parser as invalid comparisons >>> f(2, 4, x=34); 1 $ 2 Traceback (most recent call last): @@ -1533,6 +1660,19 @@ Traceback (most recent call last): IndentationError: expected an indented block after class definition on line 1 + >>> class C(__debug__=42): ... + Traceback (most recent call last): + SyntaxError: cannot assign to __debug__ + + >>> class Meta(type): + ... def __new__(*args, **kwargs): + ... pass + + >>> class C(metaclass=Meta, __debug__=42): + ... pass + Traceback (most recent call last): + SyntaxError: cannot assign to __debug__ + >>> match something: ... pass Traceback (most recent call last): @@ -1563,30 +1703,14 @@ SyntaxError: invalid syntax Check that an multiple exception types with missing parentheses -raise a custom exception - - >>> # TODO: RUSTPYTHON - >>> try: # doctest: +SKIP - ... pass - ... except A, B: - ... pass - Traceback (most recent call last): - SyntaxError: multiple exception types must be parenthesized - - >>> # TODO: RUSTPYTHON - >>> try: # doctest: +SKIP - ... pass - ... except A, B, C: - ... pass - Traceback (most recent call last): - SyntaxError: multiple exception types must be parenthesized +raise a custom exception only when using 'as' >>> try: ... pass ... except A, B, C as blech: ... pass Traceback (most recent call last): - SyntaxError: multiple exception types must be parenthesized + SyntaxError: multiple exception types must be parenthesized when using 'as' >>> try: ... pass @@ -1595,29 +1719,15 @@ ... finally: ... pass Traceback (most recent call last): - SyntaxError: multiple exception types must be parenthesized - + SyntaxError: multiple exception types must be parenthesized when using 'as' - >>> try: - ... pass - ... except* A, B: - ... pass - Traceback (most recent call last): - SyntaxError: multiple exception types must be parenthesized - - >>> try: - ... pass - ... except* A, B, C: - ... pass - Traceback (most recent call last): - SyntaxError: multiple exception types must be parenthesized >>> try: ... pass ... except* A, B, C as blech: ... pass Traceback (most recent call last): - SyntaxError: multiple exception types must be parenthesized + SyntaxError: multiple exception types must be parenthesized when using 'as' >>> try: ... pass @@ -1626,7 +1736,7 @@ ... finally: ... pass Traceback (most recent call last): - SyntaxError: multiple exception types must be parenthesized + SyntaxError: multiple exception types must be parenthesized when using 'as' Custom exception for 'except*' without an exception type @@ -1639,6 +1749,136 @@ Traceback (most recent call last): SyntaxError: expected one or more exception types +Check custom exceptions for keywords with typos + +>>> fur a in b: +... pass +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'for'? + +>>> for a in b: +... pass +... elso: +... pass +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'else'? + +>>> whille True: +... pass +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'while'? + +>>> while True: +... pass +... elso: +... pass +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'else'? + +>>> iff x > 5: +... pass +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'if'? + +>>> if x: +... pass +... elseif y: +... pass +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'elif'? + +>>> if x: +... pass +... elif y: +... pass +... elso: +... pass +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'else'? + +>>> tyo: +... pass +... except y: +... pass +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'try'? + +>>> classe MyClass: +... pass +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'class'? + +>>> impor math +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'import'? + +>>> form x import y +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'from'? + +>>> defn calculate_sum(a, b): +... return a + b +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'def'? + +>>> def foo(): +... returm result +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'return'? + +>>> lamda x: x ** 2 +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'lambda'? + +>>> def foo(): +... yeld i +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'yield'? + +>>> def foo(): +... globel counter +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'global'? + +>>> frum math import sqrt +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'from'? + +>>> asynch def fetch_data(): +... pass +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'async'? + +>>> async def foo(): +... awaid fetch_data() +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'await'? + +>>> raisee ValueError("Error") +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'raise'? + +>>> [ +... x for x +... in range(3) +... of x +... ] +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'if'? + +>>> [ +... 123 fur x +... in range(3) +... if x +... ] +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'for'? + + +>>> for x im n: +... pass +Traceback (most recent call last): +SyntaxError: invalid syntax. Did you mean 'in'? >>> f(a=23, a=234) Traceback (most recent call last): @@ -1661,6 +1901,86 @@ Traceback (most recent call last): SyntaxError: cannot assign to f-string expression here. Maybe you meant '==' instead of '='? +>>> ub'' +Traceback (most recent call last): +SyntaxError: 'u' and 'b' prefixes are incompatible + +>>> bu"привет" +Traceback (most recent call last): +SyntaxError: 'u' and 'b' prefixes are incompatible + +>>> ur'' +Traceback (most recent call last): +SyntaxError: 'u' and 'r' prefixes are incompatible + +>>> ru"\t" +Traceback (most recent call last): +SyntaxError: 'u' and 'r' prefixes are incompatible + +>>> uf'{1 + 1}' +Traceback (most recent call last): +SyntaxError: 'u' and 'f' prefixes are incompatible + +>>> fu"" +Traceback (most recent call last): +SyntaxError: 'u' and 'f' prefixes are incompatible + +>>> ut'{1}' +Traceback (most recent call last): +SyntaxError: 'u' and 't' prefixes are incompatible + +>>> tu"234" +Traceback (most recent call last): +SyntaxError: 'u' and 't' prefixes are incompatible + +>>> bf'{x!r}' +Traceback (most recent call last): +SyntaxError: 'b' and 'f' prefixes are incompatible + +>>> fb"text" +Traceback (most recent call last): +SyntaxError: 'b' and 'f' prefixes are incompatible + +>>> bt"text" +Traceback (most recent call last): +SyntaxError: 'b' and 't' prefixes are incompatible + +>>> tb'' +Traceback (most recent call last): +SyntaxError: 'b' and 't' prefixes are incompatible + +>>> tf"{0.3:.02f}" +Traceback (most recent call last): +SyntaxError: 'f' and 't' prefixes are incompatible + +>>> ft'{x=}' +Traceback (most recent call last): +SyntaxError: 'f' and 't' prefixes are incompatible + +>>> tfu"{x=}" +Traceback (most recent call last): +SyntaxError: 'u' and 'f' prefixes are incompatible + +>>> turf"{x=}" +Traceback (most recent call last): +SyntaxError: 'u' and 'r' prefixes are incompatible + +>>> burft"{x=}" +Traceback (most recent call last): +SyntaxError: 'u' and 'b' prefixes are incompatible + +>>> brft"{x=}" +Traceback (most recent call last): +SyntaxError: 'b' and 'f' prefixes are incompatible + +>>> t'{x}' = 42 +Traceback (most recent call last): +SyntaxError: cannot assign to t-string expression here. Maybe you meant '==' instead of '='? + +>>> t'{x}-{y}' = 42 +Traceback (most recent call last): +SyntaxError: cannot assign to t-string expression here. Maybe you meant '==' instead of '='? + >>> (x, y, z=3, d, e) Traceback (most recent call last): SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? @@ -1721,6 +2041,95 @@ Traceback (most recent call last): SyntaxError: Did you mean to use 'from ... import ...' instead? +>>> import __debug__ +Traceback (most recent call last): +SyntaxError: cannot assign to __debug__ + +>>> import a as __debug__ +Traceback (most recent call last): +SyntaxError: cannot assign to __debug__ + +>>> import a.b.c as __debug__ +Traceback (most recent call last): +SyntaxError: cannot assign to __debug__ + +>>> from a import __debug__ +Traceback (most recent call last): +SyntaxError: cannot assign to __debug__ + +>>> from a import b as __debug__ +Traceback (most recent call last): +SyntaxError: cannot assign to __debug__ + +>>> import a as b.c +Traceback (most recent call last): +SyntaxError: cannot use attribute as import target + +>>> import a.b as (a, b) +Traceback (most recent call last): +SyntaxError: cannot use tuple as import target + +>>> import a, a.b as 1 +Traceback (most recent call last): +SyntaxError: cannot use literal as import target + +>>> import a.b as 'a', a +Traceback (most recent call last): +SyntaxError: cannot use literal as import target + +>>> from a import (b as c.d) +Traceback (most recent call last): +SyntaxError: cannot use attribute as import target + +>>> from a import b as 1 +Traceback (most recent call last): +SyntaxError: cannot use literal as import target + +>>> from a import ( +... b as f()) +Traceback (most recent call last): +SyntaxError: cannot use function call as import target + +>>> from a import ( +... b as [], +... ) +Traceback (most recent call last): +SyntaxError: cannot use list as import target + +>>> from a import ( +... b, +... c as () +... ) +Traceback (most recent call last): +SyntaxError: cannot use tuple as import target + +>>> from a import b, с as d[e] +Traceback (most recent call last): +SyntaxError: cannot use subscript as import target + +>>> from a import с as d[e], b +Traceback (most recent call last): +SyntaxError: cannot use subscript as import target + +# Check that we don't raise a "cannot use name as import target" error +# if there is an error in an unrelated statement after ';' + +>>> import a as b; None = 1 +Traceback (most recent call last): +SyntaxError: cannot assign to None + +>>> import a, b as c; d = 1; None = 1 +Traceback (most recent call last): +SyntaxError: cannot assign to None + +>>> from a import b as c; None = 1 +Traceback (most recent call last): +SyntaxError: cannot assign to None + +>>> from a import b, c as d; e = 1; None = 1 +Traceback (most recent call last): +SyntaxError: cannot assign to None + # Check that we dont raise the "trailing comma" error if there is more # input to the left of the valid part that we parsed. @@ -1830,8 +2239,7 @@ Invalid pattern matching constructs: - >>> # TODO: RUSTPYTHON - >>> match ...: # doctest: +SKIP + >>> match ...: ... case 42 as _: ... ... Traceback (most recent call last): @@ -1841,7 +2249,31 @@ ... case 42 as 1+2+4: ... ... Traceback (most recent call last): - SyntaxError: invalid pattern target + SyntaxError: cannot use expression as pattern target + + >>> match ...: + ... case 42 as a.b: + ... ... + Traceback (most recent call last): + SyntaxError: cannot use attribute as pattern target + + >>> match ...: + ... case 42 as (a, b): + ... ... + Traceback (most recent call last): + SyntaxError: cannot use tuple as pattern target + + >>> match ...: + ... case 42 as (a + 1): + ... ... + Traceback (most recent call last): + SyntaxError: cannot use expression as pattern target + + >>> match ...: + ... case (32 as x) | (42 as a()): + ... ... + Traceback (most recent call last): + SyntaxError: cannot use function call as pattern target >>> match ...: ... case Foo(z=1, y=2, x): @@ -2180,8 +2612,7 @@ def f(x: *b) ... SyntaxError: yield expression cannot be used within a ParamSpec default - >>> # TODO: RUSTPYTHON - >>> type A = (x := 3) # doctest: +SKIP + >>> type A = (x := 3) Traceback (most recent call last): ... SyntaxError: named expression cannot be used within a type alias @@ -2201,6 +2632,14 @@ def f(x: *b) ... SyntaxError: yield expression cannot be used within a type alias + >>> type __debug__ = int + Traceback (most recent call last): + SyntaxError: cannot assign to __debug__ + + >>> class A[__debug__]: pass + Traceback (most recent call last): + SyntaxError: cannot assign to __debug__ + >>> class A[T]((x := 3)): ... Traceback (most recent call last): ... @@ -2253,7 +2692,88 @@ def f(x: *b) from test import support -class SyntaxTestCase(unittest.TestCase): +class SyntaxWarningTest(unittest.TestCase): + def check_warning(self, code, errtext, filename="", mode="exec"): + """Check that compiling code raises SyntaxWarning with errtext. + + errtest is a regular expression that must be present in the + text of the warning raised. + """ + with self.assertWarnsRegex(SyntaxWarning, errtext): + compile(code, filename, mode) + + def test_return_in_finally(self): + source = textwrap.dedent(""" + def f(): + try: + pass + finally: + return 42 + """) + self.check_warning(source, "'return' in a 'finally' block") + + source = textwrap.dedent(""" + def f(): + try: + pass + finally: + try: + return 42 + except: + pass + """) + self.check_warning(source, "'return' in a 'finally' block") + + source = textwrap.dedent(""" + def f(): + try: + pass + finally: + try: + pass + except: + return 42 + """) + self.check_warning(source, "'return' in a 'finally' block") + + def test_break_and_continue_in_finally(self): + for kw in ('break', 'continue'): + + source = textwrap.dedent(f""" + for abc in range(10): + try: + pass + finally: + {kw} + """) + self.check_warning(source, f"'{kw}' in a 'finally' block") + + source = textwrap.dedent(f""" + for abc in range(10): + try: + pass + finally: + try: + {kw} + except: + pass + """) + self.check_warning(source, f"'{kw}' in a 'finally' block") + + source = textwrap.dedent(f""" + for abc in range(10): + try: + pass + finally: + try: + pass + except: + {kw} + """) + self.check_warning(source, f"'{kw}' in a 'finally' block") + + +class SyntaxErrorTestCase(unittest.TestCase): def _check_error(self, code, errtext, filename="", mode="exec", subclass=None, @@ -2261,7 +2781,7 @@ def _check_error(self, code, errtext, """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 + text of the exception raised. If subclass is specified it is the expected subclass of SyntaxError (e.g. IndentationError). """ try: @@ -2285,7 +2805,6 @@ def _check_error(self, code, errtext, else: self.fail("compile() did not raise SyntaxError") - @unittest.expectedFailure # TODO: RUSTPYTHON def test_expression_with_assignment(self): self._check_error( "print(end1 + end2 = ' ')", @@ -2299,7 +2818,6 @@ def test_curly_brace_after_primary_raises_immediately(self): def test_assign_call(self): self._check_error("f() = 1", "assign") - @unittest.expectedFailure # TODO: RUSTPYTHON def test_assign_del(self): self._check_error("del (,)", "invalid syntax") self._check_error("del 1", "cannot delete literal") @@ -2390,7 +2908,6 @@ def test_break_outside_loop(self): self._check_error("with object() as obj:\n break", msg, lineno=2) - @unittest.expectedFailure # TODO: RUSTPYTHON def test_continue_outside_loop(self): msg = "not properly in loop" self._check_error("if 0: continue", msg, lineno=1) @@ -2415,36 +2932,30 @@ def test_bad_outdent(self): "unindent does not match .* level", subclass=IndentationError) - @unittest.expectedFailure # TODO: RUSTPYTHON def test_kwargs_last(self): self._check_error("int(base=10, '2')", "positional argument follows keyword argument") - @unittest.expectedFailure # TODO: RUSTPYTHON def test_kwargs_last2(self): self._check_error("int(**{'base': 10}, '2')", "positional argument follows " "keyword argument unpacking") - @unittest.expectedFailure # TODO: RUSTPYTHON def test_kwargs_last3(self): self._check_error("int(**{'base': 10}, *['2'])", "iterable argument unpacking follows " "keyword argument unpacking") - @unittest.expectedFailure # TODO: RUSTPYTHON def test_generator_in_function_call(self): self._check_error("foo(x, y for y in range(3) for z in range(2) if z , p)", "Generator expression must be parenthesized", lineno=1, end_lineno=1, offset=11, end_offset=53) - @unittest.expectedFailure # TODO: RUSTPYTHON def test_except_then_except_star(self): self._check_error("try: pass\nexcept ValueError: pass\nexcept* TypeError: pass", r"cannot have both 'except' and 'except\*' on the same 'try'", lineno=3, end_lineno=3, offset=1, end_offset=8) - @unittest.expectedFailure # TODO: RUSTPYTHON def test_except_star_then_except(self): self._check_error("try: pass\nexcept* ValueError: pass\nexcept TypeError: pass", r"cannot have both 'except' and 'except\*' on the same 'try'", @@ -2575,7 +3086,6 @@ async def bug(): with self.subTest(f"out of range: {n=}"): self._check_error(get_code(n), "too many statically nested blocks") - @unittest.expectedFailure # TODO: RUSTPYTHON; Wrong error message 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 @@ -2593,7 +3103,6 @@ def func2(): """ self._check_error(code, "expected ':'") - @unittest.expectedFailure # TODO: RUSTPYTHON def test_invalid_line_continuation_error_position(self): self._check_error(r"a = 3 \ 4", "unexpected character after line continuation character", @@ -2605,7 +3114,6 @@ def test_invalid_line_continuation_error_position(self): "unexpected character after line continuation character", lineno=3, offset=4) - @unittest.expectedFailure # TODO: RUSTPYTHON 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 @@ -2614,7 +3122,6 @@ def test_invalid_line_continuation_left_recursive(self): self._check_error("A.\u03bc\\\n", "unexpected EOF while parsing") - @unittest.expectedFailure # TODO: RUSTPYTHON def test_error_parenthesis(self): for paren in "([{": self._check_error(paren + "1 + 2", f"\\{paren}' was never closed") @@ -2640,7 +3147,6 @@ def test_error_parenthesis(self): s = b'# coding=latin\n(aaaaaaaaaaaaaaaaa\naaaaaaaaaaa\xb5' self._check_error(s, r"'\(' was never closed") - @unittest.expectedFailure # TODO: RUSTPYTHON def test_error_string_literal(self): self._check_error("'blech", r"unterminated string literal \(.*\)$") @@ -2654,7 +3160,6 @@ def test_error_string_literal(self): self._check_error("'''blech", "unterminated triple-quoted string literal") self._check_error('"""blech', "unterminated triple-quoted string literal") - @unittest.expectedFailure # TODO: RUSTPYTHON def test_invisible_characters(self): self._check_error('print\x17("Hello")', "invalid non-printable character") self._check_error(b"with(0,,):\n\x01", "invalid non-printable character") @@ -2677,7 +3182,6 @@ def case(x): """ compile(code, "", "exec") - @unittest.expectedFailure # TODO: RUSTPYTHON def test_multiline_compiler_error_points_to_the_end(self): self._check_error( "call(\na=1,\na=1\n)", @@ -2730,6 +3234,7 @@ def test_error_on_parser_stack_overflow(self): compile(source, "", mode) @support.cpython_only + @support.skip_wasi_stack_overflow() def test_deep_invalid_rule(self): # Check that a very deep invalid rule in the PEG # parser doesn't have exponential backtracking. @@ -2737,10 +3242,80 @@ def test_deep_invalid_rule(self): with self.assertRaises(SyntaxError): compile(source, "", "exec") + def test_except_stmt_invalid_as_expr(self): + self._check_error( + textwrap.dedent( + """ + try: + pass + except ValueError as obj.attr: + pass + """ + ), + errtext="cannot use except statement with attribute", + lineno=4, + end_lineno=4, + offset=22, + end_offset=22 + len("obj.attr"), + ) + + def test_match_stmt_invalid_as_expr(self): + self._check_error( + textwrap.dedent( + """ + match 1: + case x as obj.attr: + ... + """ + ), + errtext="cannot use attribute as pattern target", + lineno=3, + end_lineno=3, + offset=15, + end_offset=15 + len("obj.attr"), + ) + + def test_ifexp_else_stmt(self): + msg = "expected expression after 'else', but statement is given" + + for stmt in [ + "pass", + "return", + "return 2", + "raise Exception('a')", + "del a", + "yield 2", + "assert False", + "break", + "continue", + "import", + "import ast", + "from", + "from ast import *" + ]: + self._check_error(f"x = 1 if 1 else {stmt}", msg) + + def test_ifexp_body_stmt_else_expression(self): + msg = "expected expression before 'if', but statement is given" + + for stmt in [ + "pass", + "break", + "continue" + ]: + self._check_error(f"x = {stmt} if 1 else 1", msg) + + def test_ifexp_body_stmt_else_stmt(self): + msg = "expected expression before 'if', but statement is given" + for lhs_stmt, rhs_stmt in [ + ("pass", "pass"), + ("break", "pass"), + ("continue", "import ast") + ]: + self._check_error(f"x = {lhs_stmt} if 1 else {rhs_stmt}", msg) def load_tests(loader, tests, pattern): - # TODO: RUSTPYTHON Eventually remove the optionflags for ingoring exception details. - tests.addTest(doctest.DocTestSuite(optionflags=doctest.IGNORE_EXCEPTION_DETAIL)) + tests.addTest(doctest.DocTestSuite()) return tests From d6061e6182619baf0e9122b5b6752df7748805eb Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 19 May 2026 12:24:06 +0300 Subject: [PATCH 04/10] Some patches and fixes --- Lib/test/test_syntax.py | 97 +++++++++++++++++++------------------- crates/vm/src/vm/vm_new.rs | 38 ++++++++++++++- 2 files changed, 85 insertions(+), 50 deletions(-) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index de8c94fe8d2..2a4f02459b8 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -2061,72 +2061,72 @@ Traceback (most recent call last): SyntaxError: cannot assign to __debug__ ->>> import a as b.c +>>> import a as b.c # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot use attribute as import target ->>> import a.b as (a, b) +>>> import a.b as (a, b) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot use tuple as import target ->>> import a, a.b as 1 +>>> import a, a.b as 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot use literal as import target ->>> import a.b as 'a', a +>>> import a.b as 'a', a # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot use literal as import target ->>> from a import (b as c.d) +>>> from a import (b as c.d) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot use attribute as import target ->>> from a import b as 1 +>>> from a import b as 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot use literal as import target ->>> from a import ( +>>> from a import ( # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... b as f()) Traceback (most recent call last): SyntaxError: cannot use function call as import target ->>> from a import ( +>>> from a import ( # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... b as [], ... ) Traceback (most recent call last): SyntaxError: cannot use list as import target ->>> from a import ( +>>> from a import ( # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... b, ... c as () ... ) Traceback (most recent call last): SyntaxError: cannot use tuple as import target ->>> from a import b, с as d[e] +>>> from a import b, с as d[e] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot use subscript as import target ->>> from a import с as d[e], b +>>> from a import с as d[e], b # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot use subscript as import target # Check that we don't raise a "cannot use name as import target" error # if there is an error in an unrelated statement after ';' ->>> import a as b; None = 1 +>>> import a as b; None = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to None ->>> import a, b as c; d = 1; None = 1 +>>> import a, b as c; d = 1; None = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to None ->>> from a import b as c; None = 1 +>>> from a import b as c; None = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to None ->>> from a import b, c as d; e = 1; None = 1 +>>> from a import b, c as d; e = 1; None = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to None @@ -2164,31 +2164,31 @@ # 'not' after operators: ->>> 3 + not 3 +>>> 3 + not 3 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'not' after an operator must be parenthesized ->>> 3 * not 3 +>>> 3 * not 3 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'not' after an operator must be parenthesized ->>> + not 3 +>>> + not 3 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'not' after an operator must be parenthesized ->>> - not 3 +>>> - not 3 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'not' after an operator must be parenthesized ->>> ~ not 3 +>>> ~ not 3 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'not' after an operator must be parenthesized ->>> 3 + - not 3 +>>> 3 + - not 3 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'not' after an operator must be parenthesized ->>> 3 + not -1 +>>> 3 + not -1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'not' after an operator must be parenthesized @@ -2233,43 +2233,43 @@ Traceback (most recent call last): SyntaxError: cannot assign to __debug__ - >>> import ä £ + >>> import ä £ # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid character '£' (U+00A3) Invalid pattern matching constructs: - >>> match ...: + >>> match ...: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... case 42 as _: ... ... Traceback (most recent call last): SyntaxError: cannot use '_' as a target - >>> match ...: + >>> match ...: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... case 42 as 1+2+4: ... ... Traceback (most recent call last): SyntaxError: cannot use expression as pattern target - >>> match ...: + >>> match ...: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... case 42 as a.b: ... ... Traceback (most recent call last): SyntaxError: cannot use attribute as pattern target - >>> match ...: + >>> match ...: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... case 42 as (a, b): ... ... Traceback (most recent call last): SyntaxError: cannot use tuple as pattern target - >>> match ...: + >>> match ...: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... case 42 as (a + 1): ... ... Traceback (most recent call last): SyntaxError: cannot use expression as pattern target - >>> match ...: + >>> match ...: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... case (32 as x) | (42 as a()): ... ... Traceback (most recent call last): @@ -2307,7 +2307,7 @@ Traceback (most recent call last): ... SyntaxError: invalid syntax - >>> A[:(*b)] + >>> A[:(*b)] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: cannot use starred expression here @@ -2326,7 +2326,7 @@ Traceback (most recent call last): ... SyntaxError: invalid syntax - >>> A[(*b):] + >>> A[(*b):] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: cannot use starred expression here @@ -2360,22 +2360,22 @@ A[*(1:2)] - >>> A[*(1:2)] + >>> A[*(1:2)] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: Invalid star expression - >>> A[*(1:2)] = 1 + >>> A[*(1:2)] = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: Invalid star expression - >>> del A[*(1:2)] + >>> del A[*(1:2)] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: Invalid star expression A[*:] and A[:*] - >>> A[*:] + >>> A[*:] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: Invalid star expression @@ -2386,7 +2386,7 @@ A[*] - >>> A[*] + >>> A[*] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: Invalid star expression @@ -2636,51 +2636,51 @@ def f(x: *b) Traceback (most recent call last): SyntaxError: cannot assign to __debug__ - >>> class A[__debug__]: pass + >>> class A[__debug__]: pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to __debug__ - >>> class A[T]((x := 3)): ... + >>> class A[T]((x := 3)): ... # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: named expression cannot be used within the definition of a generic - >>> class A[T]((yield 3)): ... + >>> class A[T]((yield 3)): ... # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: yield expression cannot be used within the definition of a generic - >>> class A[T]((await 3)): ... + >>> class A[T]((await 3)): ... # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: await expression cannot be used within the definition of a generic - >>> class A[T]((yield from [])): ... + >>> class A[T]((yield from [])): ... # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: yield expression cannot be used within the definition of a generic - >>> f(**x, *y) + >>> f(**x, *y) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: iterable argument unpacking follows keyword argument unpacking - >>> f(**x, *) + >>> f(**x, *) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Invalid star expression - >>> f(x, *:) + >>> f(x, *:) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Invalid star expression - >>> f(x, *) + >>> f(x, *) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Invalid star expression - >>> f(x = 5, *) + >>> f(x = 5, *) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Invalid star expression - >>> f(x = 5, *:) + >>> f(x = 5, *:) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Invalid star expression """ @@ -3315,7 +3315,8 @@ def test_ifexp_body_stmt_else_stmt(self): self._check_error(f"x = {lhs_stmt} if 1 else {rhs_stmt}", msg) def load_tests(loader, tests, pattern): - tests.addTest(doctest.DocTestSuite()) + from test.support.rustpython import DocTestChecker # TODO: RUSTPYTHON + tests.addTest(doctest.DocTestSuite(checker=DocTestChecker())) # TODO: RUSTPYTHON return tests diff --git a/crates/vm/src/vm/vm_new.rs b/crates/vm/src/vm/vm_new.rs index 63de652ac7a..66aae450d94 100644 --- a/crates/vm/src/vm/vm_new.rs +++ b/crates/vm/src/vm/vm_new.rs @@ -609,11 +609,45 @@ impl VirtualMachine { msg = "cannot mix bytes and nonbytes literals".to_owned(); } #[cfg(feature = "parser")] + crate::compiler::CompileError::Parse(rustpython_compiler::ParseError { + error: ruff_python_parser::ParseErrorType::EmptyTypeParams, + .. + }) => { + msg = "Type parameter list cannot be empty".to_owned(); + }, + #[cfg(feature = "parser")] + crate::compiler::CompileError::Parse(rustpython_compiler::ParseError { + error: ruff_python_parser::ParseErrorType::InvalidStarPatternUsage, + .. + }) => { + msg = "cannot use starred expression here".to_owned(); + narrow_caret = true; + } + #[cfg(feature = "parser")] + crate::compiler::CompileError::Parse(rustpython_compiler::ParseError { + error: ruff_python_parser::ParseErrorType::ExpectedKeywordParam, + .. + }) => { + msg = "named arguments must follow bare *".to_owned(); + } + #[cfg(feature = "parser")] + crate::compiler::CompileError::Parse(rustpython_compiler::ParseError { + error: ruff_python_parser::ParseErrorType::EmptyImportNames, + .. + }) => { + msg = "Expected one or more names after 'import'".to_owned(); + } + #[cfg(feature = "parser")] crate::compiler::CompileError::Parse(rustpython_compiler::ParseError { error: ruff_python_parser::ParseErrorType::OtherError(s), .. - }) if s.starts_with("Expected an identifier, but found a keyword") => { - msg = "invalid syntax".to_owned(); + }) => { + if s.starts_with("Expected an identifier, but found a keyword") { + msg = "invalid syntax".to_owned(); + } + else if s.eq_ignore_ascii_case("positional patterns cannot follow keyword patterns") { + msg = "positional patterns follow keyword patterns".to_owned(); + } } _ => {} } From 00e3d2b07988cbaff1391055142dd8beb6939f37 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 19 May 2026 12:46:44 +0300 Subject: [PATCH 05/10] more markers --- Lib/test/test_syntax.py | 266 ++++++++++++++++++++-------------------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 2a4f02459b8..4f2653d7640 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -1093,27 +1093,27 @@ Missing ':' before suites: - >>> def f() + >>> def f() # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> def f[T]() + >>> def f[T]() # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> class A + >>> class A # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> class A[T] + >>> class A[T] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> class A[T]() + >>> class A[T]() # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' @@ -1123,7 +1123,7 @@ Traceback (most recent call last): SyntaxError: invalid syntax - >>> if 1 + >>> if 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... elif 1: ... pass @@ -1132,7 +1132,7 @@ Traceback (most recent call last): SyntaxError: expected ':' - >>> if 1: + >>> if 1: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... elif 1 ... pass @@ -1141,7 +1141,7 @@ Traceback (most recent call last): SyntaxError: expected ':' - >>> if 1: + >>> if 1: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... elif 1: ... pass @@ -1150,7 +1150,7 @@ Traceback (most recent call last): SyntaxError: expected ':' - >>> for x in range(10) + >>> for x in range(10) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' @@ -1160,47 +1160,47 @@ Traceback (most recent call last): SyntaxError: invalid syntax - >>> while True + >>> while True # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> with blech as something + >>> with blech as something # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> with blech + >>> with blech # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> with blech, block as something + >>> with blech, block as something # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> with blech, block as something, bluch + >>> with blech, block as something, bluch # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> with (blech as something) + >>> with (blech as something) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> with (blech) + >>> with (blech) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> with (blech, block as something) + >>> with (blech, block as something) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> with (blech, block as something, bluch) + >>> with (blech, block as something, bluch) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' @@ -1210,19 +1210,19 @@ Traceback (most recent call last): SyntaxError: invalid syntax. Did you mean 'and'? - >>> try + >>> try # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... except ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> match x + >>> match x # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... case list(): ... pass Traceback (most recent call last): @@ -1234,13 +1234,13 @@ Traceback (most recent call last): SyntaxError: invalid syntax - >>> match x: + >>> match x: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... case list() ... pass Traceback (most recent call last): SyntaxError: expected ':' - >>> match x: + >>> match x: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... case [y] if y > 0 ... pass Traceback (most recent call last): @@ -1264,22 +1264,22 @@ Traceback (most recent call last): SyntaxError: cannot assign to __debug__ - >>> if x = 3: + >>> if x = 3: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? - >>> while x = 3: + >>> while x = 3: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? - >>> if x.a = 3: + >>> if x.a = 3: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: cannot assign to attribute here. Maybe you meant '==' instead of '='? - >>> while x.a = 3: + >>> while x.a = 3: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: cannot assign to attribute here. Maybe you meant '==' instead of '='? @@ -1287,71 +1287,71 @@ Missing parens after function definition - >>> def f: + >>> def f: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected '(' - >>> async def f: + >>> async def f: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected '(' - >>> def f -> int: + >>> def f -> int: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected '(' - >>> async def f -> int: # type: int + >>> async def f -> int: # type: int # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected '(' - >>> async def f[T]: + >>> async def f[T]: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected '(' - >>> def f[T] -> str: + >>> def f[T] -> str: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected '(' Parenthesized arguments in function definitions - >>> def f(x, (y, z), w): + >>> def f(x, (y, z), w): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: Function parameters cannot be parenthesized - >>> def f((x, y, z, w)): + >>> def f((x, y, z, w)) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: Function parameters cannot be parenthesized - >>> def f(x, (y, z, w)): + >>> def f(x, (y, z, w)): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: Function parameters cannot be parenthesized - >>> def f((x, y, z), w): + >>> def f((x, y, z), w): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: Function parameters cannot be parenthesized - >>> lambda x, (y, z), w: None + >>> lambda x, (y, z), w: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Lambda expression parameters cannot be parenthesized - >>> lambda (x, y, z, w): None + >>> lambda (x, y, z, w): None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Lambda expression parameters cannot be parenthesized - >>> lambda x, (y, z, w): None + >>> lambda x, (y, z, w): None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Lambda expression parameters cannot be parenthesized - >>> lambda (x, y, z), w: None + >>> lambda (x, y, z), w: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Lambda expression parameters cannot be parenthesized Custom error messages for try blocks that are not followed by except/finally - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... x = 34 ... Traceback (most recent call last): @@ -1361,7 +1361,7 @@ >>> try: ... pass - ... except TypeError as __debug__: + ... except TypeError as __debug__: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: cannot assign to __debug__ @@ -1410,28 +1410,28 @@ Better error message for using `except as` with not a name: - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... except TypeError as obj.attr: ... pass Traceback (most recent call last): SyntaxError: cannot use except statement with attribute - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... except TypeError as obj[1]: ... pass Traceback (most recent call last): SyntaxError: cannot use except statement with subscript - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... except* TypeError as (obj, name): ... pass Traceback (most recent call last): SyntaxError: cannot use except* statement with tuple - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... except* TypeError as 1: ... pass @@ -1441,17 +1441,17 @@ Regression tests for gh-133999: >>> try: pass - ... except TypeError as name: raise from None + ... except TypeError as name: raise from None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax >>> try: pass - ... except* TypeError as name: raise from None + ... except* TypeError as name: raise from None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax >>> match 1: - ... case 1 | 2 as abc: raise from None + ... case 1 | 2 as abc: raise from None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax @@ -1468,33 +1468,33 @@ Traceback (most recent call last): SyntaxError: invalid syntax - >>> dict(x=34, x=1, y=2); x $ y + >>> dict(x=34, x=1, y=2); x $ y # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax Incomplete dictionary literals - >>> {1:2, 3:4, 5} + >>> {1:2, 3:4, 5} # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: ':' expected after dictionary key - >>> {1:2, 3:4, 5:} + >>> {1:2, 3:4, 5:} # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expression expected after dictionary key and ':' - >>> {1: *12+1, 23: 1} + >>> {1: *12+1, 23: 1} # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot use a starred expression in a dictionary value - >>> {1: *12+1} + >>> {1: *12+1} # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot use a starred expression in a dictionary value - >>> {1: 23, 1: *12+1} + >>> {1: 23, 1: *12+1} # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot use a starred expression in a dictionary value - >>> {1:} + >>> {1:} # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expression expected after dictionary key and ':' @@ -1506,7 +1506,7 @@ # Ensure that the error is not raised for invalid expressions - >>> {1: 2, 3: foo(,), 4: 5} + >>> {1: 2, 3: foo(,), 4: 5} # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax @@ -1516,48 +1516,48 @@ Specialized indentation errors: - >>> while condition: + >>> while condition: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'while' statement on line 1 - >>> for x in range(10): + >>> for x in range(10): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'for' statement on line 1 - >>> for x in range(10): + >>> for x in range(10): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... else: ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'else' statement on line 3 - >>> async for x in range(10): + >>> async for x in range(10): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'for' statement on line 1 - >>> async for x in range(10): + >>> async for x in range(10): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... else: ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'else' statement on line 3 - >>> if something: + >>> if something: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'if' statement on line 1 - >>> if something: + >>> if something: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... elif something_else: ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'elif' statement on line 3 - >>> if something: + >>> if something: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... elif something_else: ... pass @@ -1566,33 +1566,33 @@ Traceback (most recent call last): IndentationError: expected an indented block after 'else' statement on line 5 - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'try' statement on line 1 - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... something() ... except: ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'except' statement on line 3 - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... something() ... except A: ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'except' statement on line 3 - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... something() ... except* A: ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'except*' statement on line 3 - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... something() ... except A: ... pass @@ -1601,7 +1601,7 @@ Traceback (most recent call last): IndentationError: expected an indented block after 'finally' statement on line 5 - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... something() ... except* A: ... pass @@ -1610,57 +1610,57 @@ Traceback (most recent call last): IndentationError: expected an indented block after 'finally' statement on line 5 - >>> with A: + >>> with A: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'with' statement on line 1 - >>> with A as a, B as b: + >>> with A as a, B as b: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'with' statement on line 1 - >>> with (A as a, B as b): + >>> with (A as a, B as b): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'with' statement on line 1 - >>> async with A: + >>> async with A: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'with' statement on line 1 - >>> async with A as a, B as b: + >>> async with A as a, B as b: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'with' statement on line 1 - >>> async with (A as a, B as b): + >>> async with (A as a, B as b): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'with' statement on line 1 - >>> def foo(x, /, y, *, z=2): + >>> def foo(x, /, y, *, z=2): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after function definition on line 1 - >>> def foo[T](x, /, y, *, z=2): + >>> def foo[T](x, /, y, *, z=2): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after function definition on line 1 - >>> class Blech(A): + >>> class Blech(A): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after class definition on line 1 - >>> class Blech[T](A): + >>> class Blech[T](A): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after class definition on line 1 - >>> class C(__debug__=42): ... + >>> class C(__debug__=42): ... # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to __debug__ @@ -1668,23 +1668,23 @@ ... def __new__(*args, **kwargs): ... pass - >>> class C(metaclass=Meta, __debug__=42): + >>> class C(metaclass=Meta, __debug__=42): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: cannot assign to __debug__ - >>> match something: + >>> match something: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'match' statement on line 1 - >>> match something: + >>> match something: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... case []: ... pass Traceback (most recent call last): IndentationError: expected an indented block after 'case' statement on line 2 - >>> match something: + >>> match something: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... case []: ... ... ... case {}: @@ -1693,11 +1693,11 @@ IndentationError: expected an indented block after 'case' statement on line 4 Make sure that the old "raise X, Y[, Z]" form is gone: - >>> raise X, Y + >>> raise X, Y # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: invalid syntax - >>> raise X, Y, Z + >>> raise X, Y, Z # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: invalid syntax @@ -1705,14 +1705,14 @@ Check that an multiple exception types with missing parentheses raise a custom exception only when using 'as' - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... except A, B, C as blech: ... pass Traceback (most recent call last): SyntaxError: multiple exception types must be parenthesized when using 'as' - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... except A, B, C as blech: ... pass @@ -1722,14 +1722,14 @@ SyntaxError: multiple exception types must be parenthesized when using 'as' - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... except* A, B, C as blech: ... pass Traceback (most recent call last): SyntaxError: multiple exception types must be parenthesized when using 'as' - >>> try: + >>> try: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... except* A, B, C as blech: ... pass @@ -1880,164 +1880,164 @@ Traceback (most recent call last): SyntaxError: invalid syntax. Did you mean 'in'? ->>> f(a=23, a=234) +>>> f(a=23, a=234) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: keyword argument repeated: a ->>> {1, 2, 3} = 42 +>>> {1, 2, 3} = 42 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to set display here. Maybe you meant '==' instead of '='? ->>> {1: 2, 3: 4} = 42 +>>> {1: 2, 3: 4} = 42 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to dict literal here. Maybe you meant '==' instead of '='? ->>> f'{x}' = 42 +>>> f'{x}' = 42 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to f-string expression here. Maybe you meant '==' instead of '='? ->>> f'{x}-{y}' = 42 +>>> f'{x}-{y}' = 42 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to f-string expression here. Maybe you meant '==' instead of '='? ->>> ub'' +>>> ub'' # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'u' and 'b' prefixes are incompatible ->>> bu"привет" +>>> bu"привет" # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'u' and 'b' prefixes are incompatible ->>> ur'' +>>> ur'' # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'u' and 'r' prefixes are incompatible ->>> ru"\t" +>>> ru"\t" # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'u' and 'r' prefixes are incompatible ->>> uf'{1 + 1}' +>>> uf'{1 + 1}' # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'u' and 'f' prefixes are incompatible ->>> fu"" +>>> fu"" # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'u' and 'f' prefixes are incompatible ->>> ut'{1}' +>>> ut'{1}' # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'u' and 't' prefixes are incompatible ->>> tu"234" +>>> tu"234" # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'u' and 't' prefixes are incompatible ->>> bf'{x!r}' +>>> bf'{x!r}' # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'b' and 'f' prefixes are incompatible ->>> fb"text" +>>> fb"text" # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'b' and 'f' prefixes are incompatible ->>> bt"text" +>>> bt"text" # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'b' and 't' prefixes are incompatible ->>> tb'' +>>> tb'' # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'b' and 't' prefixes are incompatible ->>> tf"{0.3:.02f}" +>>> tf"{0.3:.02f}" # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'f' and 't' prefixes are incompatible ->>> ft'{x=}' +>>> ft'{x=}' # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'f' and 't' prefixes are incompatible ->>> tfu"{x=}" +>>> tfu"{x=}" # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'u' and 'f' prefixes are incompatible ->>> turf"{x=}" +>>> turf"{x=}" # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'u' and 'r' prefixes are incompatible ->>> burft"{x=}" +>>> burft"{x=}" # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'u' and 'b' prefixes are incompatible ->>> brft"{x=}" +>>> brft"{x=}" # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'b' and 'f' prefixes are incompatible ->>> t'{x}' = 42 +>>> t'{x}' = 42 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to t-string expression here. Maybe you meant '==' instead of '='? ->>> t'{x}-{y}' = 42 +>>> t'{x}-{y}' = 42 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to t-string expression here. Maybe you meant '==' instead of '='? ->>> (x, y, z=3, d, e) +>>> (x, y, z=3, d, e) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? ->>> [x, y, z=3, d, e] +>>> [x, y, z=3, d, e] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? ->>> [z=3] +>>> [z=3] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? ->>> {x, y, z=3, d, e} +>>> {x, y, z=3, d, e} # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? ->>> {z=3} +>>> {z=3} # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? ->>> from t import x, +>>> from t import x, # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: trailing comma not allowed without surrounding parentheses ->>> from t import x,y, +>>> from t import x,y, # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: trailing comma not allowed without surrounding parentheses ->>> import a from b +>>> import a from b # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Did you mean to use 'from ... import ...' instead? ->>> import a.y.z from b.y.z +>>> import a.y.z from b.y.z # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Did you mean to use 'from ... import ...' instead? ->>> import a from b as bar +>>> import a from b as bar # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Did you mean to use 'from ... import ...' instead? ->>> import a.y.z from b.y.z as bar +>>> import a.y.z from b.y.z as bar # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Did you mean to use 'from ... import ...' instead? ->>> import a, b,c from b +>>> import a, b,c from b # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Did you mean to use 'from ... import ...' instead? ->>> import a.y.z, b.y.z, c.y.z from b.y.z +>>> import a.y.z, b.y.z, c.y.z from b.y.z # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Did you mean to use 'from ... import ...' instead? ->>> import a,b,c from b as bar +>>> import a,b,c from b as bar # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Did you mean to use 'from ... import ...' instead? ->>> import a.y.z, b.y.z, c.y.z from b.y.z as bar +>>> import a.y.z, b.y.z, c.y.z from b.y.z as bar # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Did you mean to use 'from ... import ...' instead? From 8267b2a2ee50e45f0f4bc233093075304580394e Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 19 May 2026 12:53:14 +0300 Subject: [PATCH 06/10] More --- Lib/test/test_syntax.py | 62 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 4f2653d7640..b94d5cc0e13 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -200,15 +200,15 @@ Traceback (most recent call last): SyntaxError: assignment to yield expression not possible ->>> a, b += 1, 2 +>>> a, b += 1, 2 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'tuple' is an illegal expression for augmented assignment ->>> (a, b) += 1, 2 +>>> (a, b) += 1, 2 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'tuple' is an illegal expression for augmented assignment ->>> [a, b] += 1, 2 +>>> [a, b] += 1, 2 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'list' is an illegal expression for augmented assignment @@ -784,7 +784,7 @@ ... 290, 291, 292, 293, 294, 295, 296, 297, 298, 299) # doctest: +ELLIPSIS (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ..., 297, 298, 299) ->>> f(lambda x: x[0] = 3) +>>> f(lambda x: x[0] = 3) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expression cannot contain assignment, perhaps you meant "=="? @@ -796,25 +796,25 @@ The grammar accepts any test (basically, any expression) in the keyword slot of a call site. Test a few different options. ->>> f(x()=2) +>>> f(x()=2) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expression cannot contain assignment, perhaps you meant "=="? ->>> f(a or b=1) +>>> f(a or b=1) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expression cannot contain assignment, perhaps you meant "=="? ->>> f(x.y=1) +>>> f(x.y=1) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expression cannot contain assignment, perhaps you meant "=="? ->>> f((x)=2) +>>> f((x)=2) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expression cannot contain assignment, perhaps you meant "=="? ->>> f(True=1) +>>> f(True=1) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to True ->>> f(False=1) +>>> f(False=1) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to False ->>> f(None=1) +>>> f(None=1) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to None >>> f(__debug__=1) @@ -826,42 +826,42 @@ >>> x.__debug__: int Traceback (most recent call last): SyntaxError: cannot assign to __debug__ ->>> f(a=) +>>> f(a=) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected argument value expression ->>> f(a, b, c=) +>>> f(a, b, c=) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected argument value expression ->>> f(a, b, c=, d) +>>> f(a, b, c=, d) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected argument value expression ->>> f(*args=[0]) +>>> f(*args=[0]) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to iterable argument unpacking ->>> f(a, b, *args=[0]) +>>> f(a, b, *args=[0]) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to iterable argument unpacking ->>> f(**kwargs={'a': 1}) +>>> f(**kwargs={'a': 1}) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to keyword argument unpacking ->>> f(a, b, *args, **kwargs={'a': 1}) +>>> f(a, b, *args, **kwargs={'a': 1}) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to keyword argument unpacking More set_context(): ->>> (x for x in x) += 1 +>>> (x for x in x) += 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'generator expression' is an illegal expression for augmented assignment ->>> None += 1 +>>> None += 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'None' is an illegal expression for augmented assignment >>> __debug__ += 1 Traceback (most recent call last): SyntaxError: cannot assign to __debug__ ->>> f() += 1 -Traceback (most recent call last): +>>> f() += 1 # TODO: RUSTPYTHON; Raises an exception # doctest: +SKIP +Traceback (most recent call last): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE SyntaxError: 'function call' is an illegal expression for augmented assignment @@ -931,7 +931,7 @@ A continue outside loop should not be allowed. - >>> def foo(): + >>> def foo(): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... try: ... continue ... finally: @@ -957,7 +957,7 @@ elif can't come after an else. - >>> if a % 2 == 0: + >>> if a % 2 == 0: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... else: ... pass @@ -1013,7 +1013,7 @@ ... SyntaxError: name 'x' is parameter and nonlocal - >>> def f(): + >>> def f(): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... global x ... nonlocal x Traceback (most recent call last): @@ -1027,7 +1027,7 @@ SyntaxError: no binding for nonlocal 'x' found From SF bug #1705365 - >>> nonlocal x + >>> nonlocal x # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): ... SyntaxError: nonlocal declaration not allowed at module level @@ -1045,7 +1045,7 @@ a complex 'if' (one with 'elif') would fail to notice an invalid suite, leading to spurious errors. - >>> if 1: + >>> if 1: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... x() = 1 ... elif 1: ... pass @@ -1053,7 +1053,7 @@ ... SyntaxError: cannot assign to function call here. Maybe you meant '==' instead of '='? - >>> if 1: + >>> if 1: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... elif 1: ... x() = 1 @@ -1061,7 +1061,7 @@ ... SyntaxError: cannot assign to function call here. Maybe you meant '==' instead of '='? - >>> if 1: + >>> if 1: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... x() = 1 ... elif 1: ... pass @@ -1071,7 +1071,7 @@ ... SyntaxError: cannot assign to function call here. Maybe you meant '==' instead of '='? - >>> if 1: + >>> if 1: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... elif 1: ... x() = 1 @@ -1081,7 +1081,7 @@ ... SyntaxError: cannot assign to function call here. Maybe you meant '==' instead of '='? - >>> if 1: + >>> if 1: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass ... elif 1: ... pass From 34757b56d63e93cdefb5009564188440c8aea697 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 19 May 2026 13:03:37 +0300 Subject: [PATCH 07/10] Done doctest patches --- Lib/test/test_syntax.py | 244 ++++++++++++++++++++-------------------- 1 file changed, 122 insertions(+), 122 deletions(-) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index b94d5cc0e13..95cecdf225f 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -31,7 +31,7 @@ Traceback (most recent call last): SyntaxError: invalid syntax ->>> None = 1 +>>> None = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to None @@ -39,11 +39,11 @@ Traceback (most recent call last): SyntaxError: invalid syntax ->>> True = 1 +>>> True = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to True ->>> (True := 1) +>>> (True := 1) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot use assignment expressions with True @@ -59,15 +59,15 @@ Traceback (most recent call last): SyntaxError: cannot assign to __debug__ ->>> def __debug__(): pass +>>> def __debug__(): pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to __debug__ ->>> async def __debug__(): pass +>>> async def __debug__(): pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to __debug__ ->>> class __debug__: pass +>>> class __debug__: pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to __debug__ @@ -75,39 +75,39 @@ Traceback (most recent call last): SyntaxError: cannot delete __debug__ ->>> f() = 1 +>>> f() = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to function call here. Maybe you meant '==' instead of '='? ->>> yield = 1 +>>> yield = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: assignment to yield expression not possible ->>> del f() +>>> del f() # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot delete function call ->>> a + 1 = 2 +>>> a + 1 = 2 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to expression here. Maybe you meant '==' instead of '='? ->>> (x for x in x) = 1 +>>> (x for x in x) = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to generator expression ->>> 1 = 1 +>>> 1 = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to literal here. Maybe you meant '==' instead of '='? ->>> "abc" = 1 +>>> "abc" = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to literal here. Maybe you meant '==' instead of '='? ->>> b"" = 1 +>>> b"" = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to literal here. Maybe you meant '==' instead of '='? ->>> ... = 1 +>>> ... = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to ellipsis here. Maybe you meant '==' instead of '='? @@ -120,11 +120,11 @@ This test just checks a couple of cases rather than enumerating all of them. ->>> (a, "b", c) = (1, 2, 3) +>>> (a, "b", c) = (1, 2, 3) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to literal ->>> (a, True, c) = (1, 2, 3) +>>> (a, True, c) = (1, 2, 3) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to True @@ -132,7 +132,7 @@ Traceback (most recent call last): SyntaxError: cannot assign to __debug__ ->>> (a, *True, c) = (1, 2, 3) +>>> (a, *True, c) = (1, 2, 3) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to True @@ -140,43 +140,43 @@ Traceback (most recent call last): SyntaxError: cannot assign to __debug__ ->>> [a, b, c + 1] = [1, 2, 3] +>>> [a, b, c + 1] = [1, 2, 3] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to expression ->>> [a, b[1], c + 1] = [1, 2, 3] +>>> [a, b[1], c + 1] = [1, 2, 3] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to expression ->>> [a, b.c.d, c + 1] = [1, 2, 3] +>>> [a, b.c.d, c + 1] = [1, 2, 3] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to expression ->>> a if 1 else b = 1 +>>> a if 1 else b = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to conditional expression ->>> a = 42 if True +>>> a = 42 if True # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected 'else' after 'if' expression ->>> a = (42 if True) +>>> a = (42 if True) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected 'else' after 'if' expression ->>> a = [1, 42 if True, 4] +>>> a = [1, 42 if True, 4] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected 'else' after 'if' expression ->>> x = 1 if 1 else pass +>>> x = 1 if 1 else pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected expression after 'else', but statement is given ->>> x = pass if 1 else 1 +>>> x = pass if 1 else 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected expression before 'if', but statement is given ->>> x = pass if 1 else pass +>>> x = pass if 1 else pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected expression before 'if', but statement is given @@ -188,15 +188,15 @@ Traceback (most recent call last): SyntaxError: invalid syntax ->>> True = True = 3 +>>> True = True = 3 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to True ->>> x = y = True = z = 3 +>>> x = y = True = z = 3 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to True ->>> x = y = yield = 1 +>>> x = y = yield = 1 # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: assignment to yield expression not possible @@ -215,35 +215,35 @@ Invalid targets in `for` loops and `with` statements should also produce a specialized error message ->>> for a() in b: pass +>>> for a() in b: pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to function call ->>> for (a, b()) in b: pass +>>> for (a, b()) in b: pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to function call ->>> for [a, b()] in b: pass +>>> for [a, b()] in b: pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to function call ->>> for (*a, b, c+1) in b: pass +>>> for (*a, b, c+1) in b: pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to expression ->>> for (x, *(y, z.d())) in b: pass +>>> for (x, *(y, z.d())) in b: pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to function call ->>> for a, b() in c: pass +>>> for a, b() in c: pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to function call ->>> for a, b, (c + 1, d()): pass +>>> for a, b, (c + 1, d()): pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to expression ->>> for i < (): pass +>>> for i < (): pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax @@ -251,31 +251,31 @@ Traceback (most recent call last): SyntaxError: invalid syntax ->>> with a as b(): pass +>>> with a as b(): pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to function call ->>> with a as (b, c()): pass +>>> with a as (b, c()): pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to function call ->>> with a as [b, c()]: pass +>>> with a as [b, c()]: pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to function call ->>> with a as (*b, c, d+1): pass +>>> with a as (*b, c, d+1): pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to expression ->>> with a as (x, *(y, z.d())): pass +>>> with a as (x, *(y, z.d())): pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to function call ->>> with a as b, c as d(): pass +>>> with a as b, c as d(): pass # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to function call ->>> with a as b +>>> with a as b # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected ':' @@ -285,48 +285,48 @@ Comprehensions without 'in' keyword: ->>> [x for x if range(1)] +>>> [x for x if range(1)] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'in' expected after for-loop variables ->>> tuple(x for x if range(1)) +>>> tuple(x for x if range(1)) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'in' expected after for-loop variables ->>> [x for x() in a] +>>> [x for x() in a] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to function call ->>> [x for a, b, (c + 1, d()) in y] +>>> [x for a, b, (c + 1, d()) in y] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to expression ->>> [x for a, b, (c + 1, d()) if y] +>>> [x for a, b, (c + 1, d()) if y] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: 'in' expected after for-loop variables ->>> [x for x+1 in y] +>>> [x for x+1 in y] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to expression ->>> [x for x+1, x() in y] +>>> [x for x+1, x() in y] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: cannot assign to expression Comprehensions creating tuples without parentheses should produce a specialized error message: ->>> [x,y for x,y in range(100)] +>>> [x,y for x,y in range(100)] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: did you forget parentheses around the comprehension target? ->>> {x,y for x,y in range(100)} +>>> {x,y for x,y in range(100)} # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: did you forget parentheses around the comprehension target? # Incorrectly closed strings ->>> "The interesting object "The important object" is very important" +>>> "The interesting object "The important object" is very important" # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax. Is this intended to be part of the string? @@ -334,26 +334,26 @@ # produce special error messages regarding missing # parentheses, but about missing commas instead ->>> [1, 2 3] +>>> [1, 2 3] # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax. Perhaps you forgot a comma? ->>> {1, 2 3} +>>> {1, 2 3} # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax. Perhaps you forgot a comma? ->>> {1:2, 2:5 3:12} +>>> {1:2, 2:5 3:12} # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax. Perhaps you forgot a comma? ->>> (1, 2 3) +>>> (1, 2 3) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax. Perhaps you forgot a comma? # Make sure soft keywords constructs don't raise specialized # errors regarding missing commas or other spezialiced errors ->>> match x: +>>> match x: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... y = 3 Traceback (most recent call last): SyntaxError: invalid syntax @@ -370,7 +370,7 @@ Traceback (most recent call last): SyntaxError: invalid syntax ->>> match ...: +>>> match ...: # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... case {**rest, "key": value}: ... ... Traceback (most recent call last): @@ -385,7 +385,7 @@ # But prefixes of soft keywords should # still raise specialized errors ->>> (mat x) +>>> (mat x) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: invalid syntax. Perhaps you forgot a comma? @@ -398,12 +398,12 @@ From ast_for_arguments(): ->>> def f(x, y=1, z): +>>> def f(x, y=1, z): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: parameter without a default follows parameter with a default ->>> def f(x, /, y=1, z): +>>> def f(x, /, y=1, z): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: parameter without a default follows parameter with a default @@ -413,7 +413,7 @@ Traceback (most recent call last): SyntaxError: invalid syntax ->>> def f(*None): +>>> def f(*None): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: invalid syntax @@ -423,215 +423,215 @@ Traceback (most recent call last): SyntaxError: invalid syntax ->>> def foo(/,a,b=,c): +>>> def foo(/,a,b=,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: at least one argument must precede / ->>> def foo(a,/,/,b,c): +>>> def foo(a,/,/,b,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: / may appear only once ->>> def foo(a,/,a1,/,b,c): +>>> def foo(a,/,a1,/,b,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: / may appear only once ->>> def foo(a=1,/,/,*b,/,c): +>>> def foo(a=1,/,/,*b,/,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: / may appear only once ->>> def foo(a,/,a1=1,/,b,c): +>>> def foo(a,/,a1=1,/,b,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: / may appear only once ->>> def foo(a,*b,c,/,d,e): +>>> def foo(a,*b,c,/,d,e): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: / must be ahead of * ->>> def foo(a=1,*b,c=3,/,d,e): +>>> def foo(a=1,*b,c=3,/,d,e): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: / must be ahead of * ->>> def foo(a,*b=3,c): +>>> def foo(a,*b=3,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: var-positional argument cannot have default value ->>> def foo(a,*b: int=,c): +>>> def foo(a,*b: int=,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: var-positional argument cannot have default value ->>> def foo(a,**b=3): +>>> def foo(a,**b=3): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: var-keyword argument cannot have default value ->>> def foo(a,**b: int=3): +>>> def foo(a,**b: int=3): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: var-keyword argument cannot have default value ->>> def foo(a,*a, b, **c, d): +>>> def foo(a,*a, b, **c, d): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: arguments cannot follow var-keyword argument ->>> def foo(a,*a, b, **c, d=4): +>>> def foo(a,*a, b, **c, d=4): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: arguments cannot follow var-keyword argument ->>> def foo(a,*a, b, **c, *d): +>>> def foo(a,*a, b, **c, *d): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: arguments cannot follow var-keyword argument ->>> def foo(a,*a, b, **c, **d): +>>> def foo(a,*a, b, **c, **d): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: arguments cannot follow var-keyword argument ->>> def foo(a=1,/,**b,/,c): +>>> def foo(a=1,/,**b,/,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: arguments cannot follow var-keyword argument ->>> def foo(*b,*d): +>>> def foo(*b,*d): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: * argument may appear only once ->>> def foo(a,*b,c,*d,*e,c): +>>> def foo(a,*b,c,*d,*e,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: * argument may appear only once ->>> def foo(a,b,/,c,*b,c,*d,*e,c): +>>> def foo(a,b,/,c,*b,c,*d,*e,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: * argument may appear only once ->>> def foo(a,b,/,c,*b,c,*d,**e): +>>> def foo(a,b,/,c,*b,c,*d,**e): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: * argument may appear only once ->>> def foo(a=1,/*,b,c): +>>> def foo(a=1,/*,b,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected comma between / and * ->>> def foo(a=1,d=,c): +>>> def foo(a=1,d=,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected default value expression ->>> def foo(a,d=,c): +>>> def foo(a,d=,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected default value expression ->>> def foo(a,d: int=,c): +>>> def foo(a,d: int=,c): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: expected default value expression ->>> lambda /,a,b,c: None +>>> lambda /,a,b,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: at least one argument must precede / ->>> lambda a,/,/,b,c: None +>>> lambda a,/,/,b,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: / may appear only once ->>> lambda a,/,a1,/,b,c: None +>>> lambda a,/,a1,/,b,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: / may appear only once ->>> lambda a=1,/,/,*b,/,c: None +>>> lambda a=1,/,/,*b,/,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: / may appear only once ->>> lambda a,/,a1=1,/,b,c: None +>>> lambda a,/,a1=1,/,b,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: / may appear only once ->>> lambda a,*b,c,/,d,e: None +>>> lambda a,*b,c,/,d,e: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: / must be ahead of * ->>> lambda a=1,*b,c=3,/,d,e: None +>>> lambda a=1,*b,c=3,/,d,e: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: / must be ahead of * ->>> lambda a=1,/*,b,c: None +>>> lambda a=1,/*,b,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected comma between / and * ->>> lambda a,*b=3,c: None +>>> lambda a,*b=3,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: var-positional argument cannot have default value ->>> lambda a,**b=3: None +>>> lambda a,**b=3: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: var-keyword argument cannot have default value ->>> lambda a, *a, b, **c, d: None +>>> lambda a, *a, b, **c, d: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: arguments cannot follow var-keyword argument ->>> lambda a,*a, b, **c, d=4: None +>>> lambda a,*a, b, **c, d=4: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: arguments cannot follow var-keyword argument ->>> lambda a,*a, b, **c, *d: None +>>> lambda a,*a, b, **c, *d: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: arguments cannot follow var-keyword argument ->>> lambda a,*a, b, **c, **d: None +>>> lambda a,*a, b, **c, **d: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: arguments cannot follow var-keyword argument ->>> lambda a=1,/,**b,/,c: None +>>> lambda a=1,/,**b,/,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: arguments cannot follow var-keyword argument ->>> lambda *b,*d: None +>>> lambda *b,*d: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: * argument may appear only once ->>> lambda a,*b,c,*d,*e,c: None +>>> lambda a,*b,c,*d,*e,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: * argument may appear only once ->>> lambda a,b,/,c,*b,c,*d,*e,c: None +>>> lambda a,b,/,c,*b,c,*d,*e,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: * argument may appear only once ->>> lambda a,b,/,c,*b,c,*d,**e: None +>>> lambda a,b,/,c,*b,c,*d,**e: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: * argument may appear only once ->>> lambda a=1,d=,c: None +>>> lambda a=1,d=,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected default value expression ->>> lambda a,d=,c: None +>>> lambda a,d=,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: expected default value expression ->>> lambda a,d=3,c: None +>>> lambda a,d=3,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: parameter without a default follows parameter with a default ->>> lambda a,/,d=3,c: None +>>> lambda a,/,d=3,c: None # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: parameter without a default follows parameter with a default @@ -641,7 +641,7 @@ ... a, # type: int ... ): ... pass -... ''', type_comments=True) +... ''', type_comments=True) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: bare * has associated type comment @@ -661,30 +661,30 @@ >>> L = range(10) >>> f(x for x in L) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ->>> f(x for x in L, 1) +>>> f(x for x in L, 1) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Generator expression must be parenthesized ->>> f(x for x in L, y=1) +>>> f(x for x in L, y=1) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Generator expression must be parenthesized ->>> f(x for x in L, *[]) +>>> f(x for x in L, *[]) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Generator expression must be parenthesized ->>> f(x for x in L, **{}) +>>> f(x for x in L, **{}) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Generator expression must be parenthesized ->>> f(L, x for x in L) +>>> f(L, x for x in L) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Generator expression must be parenthesized ->>> f(x for x in L, y for y in L) +>>> f(x for x in L, y for y in L) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Generator expression must be parenthesized ->>> f(x for x in L,) +>>> f(x for x in L,) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE Traceback (most recent call last): SyntaxError: Generator expression must be parenthesized >>> f((x for x in L), 1) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ->>> class C(x for x in L): +>>> class C(x for x in L): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: invalid syntax From ee6b987565a24e712243ae7122b055f91b255727 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 19 May 2026 13:09:33 +0300 Subject: [PATCH 08/10] More markers --- Lib/test/test_syntax.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 95cecdf225f..af07f046a74 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -2702,6 +2702,7 @@ def check_warning(self, code, errtext, filename="", mode="exec"): with self.assertWarnsRegex(SyntaxWarning, errtext): compile(code, filename, mode) + @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: SyntaxWarning not triggered def test_return_in_finally(self): source = textwrap.dedent(""" def f(): @@ -2736,6 +2737,7 @@ def f(): """) self.check_warning(source, "'return' in a 'finally' block") + @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: SyntaxWarning not triggered def test_break_and_continue_in_finally(self): for kw in ('break', 'continue'): @@ -2805,6 +2807,7 @@ def _check_error(self, code, errtext, else: self.fail("compile() did not raise SyntaxError") + @unittest.expectedFailure # TODO: RUSTPYTHON def test_expression_with_assignment(self): self._check_error( "print(end1 + end2 = ' ')", @@ -2818,6 +2821,7 @@ def test_curly_brace_after_primary_raises_immediately(self): def test_assign_call(self): self._check_error("f() = 1", "assign") + @unittest.expectedFailure # TODO: RUSTPYTHON def test_assign_del(self): self._check_error("del (,)", "invalid syntax") self._check_error("del 1", "cannot delete literal") @@ -2908,6 +2912,7 @@ def test_break_outside_loop(self): self._check_error("with object() as obj:\n break", msg, lineno=2) + @unittest.expectedFailure # TODO: RUSTPYTHON def test_continue_outside_loop(self): msg = "not properly in loop" self._check_error("if 0: continue", msg, lineno=1) @@ -2932,30 +2937,36 @@ def test_bad_outdent(self): "unindent does not match .* level", subclass=IndentationError) + @unittest.expectedFailure # TODO: RUSTPYTHON def test_kwargs_last(self): self._check_error("int(base=10, '2')", "positional argument follows keyword argument") + @unittest.expectedFailure # TODO: RUSTPYTHON def test_kwargs_last2(self): self._check_error("int(**{'base': 10}, '2')", "positional argument follows " "keyword argument unpacking") + @unittest.expectedFailure # TODO: RUSTPYTHON def test_kwargs_last3(self): self._check_error("int(**{'base': 10}, *['2'])", "iterable argument unpacking follows " "keyword argument unpacking") + @unittest.expectedFailure # TODO: RUSTPYTHON def test_generator_in_function_call(self): self._check_error("foo(x, y for y in range(3) for z in range(2) if z , p)", "Generator expression must be parenthesized", lineno=1, end_lineno=1, offset=11, end_offset=53) + @unittest.expectedFailure # TODO: RUSTPYTHON def test_except_then_except_star(self): self._check_error("try: pass\nexcept ValueError: pass\nexcept* TypeError: pass", r"cannot have both 'except' and 'except\*' on the same 'try'", lineno=3, end_lineno=3, offset=1, end_offset=8) + @unittest.expectedFailure # TODO: RUSTPYTHON def test_except_star_then_except(self): self._check_error("try: pass\nexcept* ValueError: pass\nexcept TypeError: pass", r"cannot have both 'except' and 'except\*' on the same 'try'", @@ -3086,6 +3097,7 @@ async def bug(): with self.subTest(f"out of range: {n=}"): self._check_error(get_code(n), "too many statically nested blocks") + @unittest.expectedFailure # TODO: RUSTPYTHON 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 @@ -3103,6 +3115,7 @@ def func2(): """ self._check_error(code, "expected ':'") + @unittest.expectedFailure # TODO: RUSTPYTHON def test_invalid_line_continuation_error_position(self): self._check_error(r"a = 3 \ 4", "unexpected character after line continuation character", @@ -3114,6 +3127,7 @@ def test_invalid_line_continuation_error_position(self): "unexpected character after line continuation character", lineno=3, offset=4) + @unittest.expectedFailure # TODO: RUSTPYTHON 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 @@ -3122,6 +3136,7 @@ def test_invalid_line_continuation_left_recursive(self): self._check_error("A.\u03bc\\\n", "unexpected EOF while parsing") + @unittest.expectedFailure # TODO: RUSTPYTHON def test_error_parenthesis(self): for paren in "([{": self._check_error(paren + "1 + 2", f"\\{paren}' was never closed") @@ -3147,6 +3162,7 @@ def test_error_parenthesis(self): s = b'# coding=latin\n(aaaaaaaaaaaaaaaaa\naaaaaaaaaaa\xb5' self._check_error(s, r"'\(' was never closed") + @unittest.expectedFailure # TODO: RUSTPYTHON def test_error_string_literal(self): self._check_error("'blech", r"unterminated string literal \(.*\)$") @@ -3160,6 +3176,7 @@ def test_error_string_literal(self): self._check_error("'''blech", "unterminated triple-quoted string literal") self._check_error('"""blech', "unterminated triple-quoted string literal") + @unittest.expectedFailure # TODO: RUSTPYTHON def test_invisible_characters(self): self._check_error('print\x17("Hello")', "invalid non-printable character") self._check_error(b"with(0,,):\n\x01", "invalid non-printable character") @@ -3182,6 +3199,7 @@ def case(x): """ compile(code, "", "exec") + @unittest.expectedFailure # TODO: RUSTPYTHON def test_multiline_compiler_error_points_to_the_end(self): self._check_error( "call(\na=1,\na=1\n)", @@ -3242,6 +3260,7 @@ def test_deep_invalid_rule(self): with self.assertRaises(SyntaxError): compile(source, "", "exec") + @unittest.expectedFailure # TODO: RUSTPYTHON def test_except_stmt_invalid_as_expr(self): self._check_error( textwrap.dedent( @@ -3259,6 +3278,7 @@ def test_except_stmt_invalid_as_expr(self): end_offset=22 + len("obj.attr"), ) + @unittest.expectedFailure # TODO: RUSTPYTHON def test_match_stmt_invalid_as_expr(self): self._check_error( textwrap.dedent( @@ -3275,6 +3295,7 @@ def test_match_stmt_invalid_as_expr(self): end_offset=15 + len("obj.attr"), ) + @unittest.expectedFailure # TODO: RUSTPYTHON def test_ifexp_else_stmt(self): msg = "expected expression after 'else', but statement is given" @@ -3295,6 +3316,7 @@ def test_ifexp_else_stmt(self): ]: self._check_error(f"x = 1 if 1 else {stmt}", msg) + @unittest.expectedFailure # TODO: RUSTPYTHON def test_ifexp_body_stmt_else_expression(self): msg = "expected expression before 'if', but statement is given" @@ -3305,6 +3327,7 @@ def test_ifexp_body_stmt_else_expression(self): ]: self._check_error(f"x = {stmt} if 1 else 1", msg) + @unittest.expectedFailure # TODO: RUSTPYTHON def test_ifexp_body_stmt_else_stmt(self): msg = "expected expression before 'if', but statement is given" for lhs_stmt, rhs_stmt in [ From 3b61bde47aab9bf8342386fcdd0b27e2ee4a7c71 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 19 May 2026 13:16:33 +0300 Subject: [PATCH 09/10] Fix `continue` error message --- Lib/test/test_syntax.py | 3 +- crates/codegen/src/error.rs | 59 ++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index af07f046a74..0be25357009 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -931,7 +931,7 @@ A continue outside loop should not be allowed. - >>> def foo(): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE + >>> def foo(): ... try: ... continue ... finally: @@ -2912,7 +2912,6 @@ def test_break_outside_loop(self): self._check_error("with object() as obj:\n break", msg, lineno=2) - @unittest.expectedFailure # TODO: RUSTPYTHON def test_continue_outside_loop(self): msg = "not properly in loop" self._check_error("if 0: continue", msg, lineno=1) diff --git a/crates/codegen/src/error.rs b/crates/codegen/src/error.rs index 086f9dfd739..86ac86244ad 100644 --- a/crates/codegen/src/error.rs +++ b/crates/codegen/src/error.rs @@ -101,74 +101,73 @@ impl core::error::Error for CodegenErrorType {} impl fmt::Display for CodegenErrorType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use CodegenErrorType::*; match self { - Assign(target) => write!(f, "cannot assign to {target}"), - Delete(target) => write!(f, "cannot delete {target}"), - SyntaxError(err) => write!(f, "{}", err.as_str()), - MultipleStarArgs => { + Self::Assign(target) => write!(f, "cannot assign to {target}"), + Self::Delete(target) => write!(f, "cannot delete {target}"), + Self::SyntaxError(err) => write!(f, "{}", err.as_str()), + Self::MultipleStarArgs => { write!(f, "multiple starred expressions in assignment") } - InvalidStarExpr => write!(f, "can't use starred expression here"), - InvalidBreak => write!(f, "'break' outside loop"), - InvalidContinue => write!(f, "'continue' outside loop"), - InvalidReturn => write!(f, "'return' outside function"), - InvalidYield => write!(f, "'yield' outside function"), - InvalidYieldFrom => write!(f, "'yield from' outside function"), - InvalidAwait => write!(f, "'await' outside async function"), - InvalidAsyncFor => write!(f, "'async for' outside async function"), - InvalidAsyncWith => write!(f, "'async with' outside async function"), - InvalidAsyncComprehension => { + Self::InvalidStarExpr => write!(f, "can't use starred expression here"), + Self::InvalidBreak => write!(f, "'break' outside loop"), + Self::InvalidContinue => write!(f, "'continue' not properly in loop"), + Self::InvalidReturn => write!(f, "'return' outside function"), + Self::InvalidYield => write!(f, "'yield' outside function"), + Self::InvalidYieldFrom => write!(f, "'yield from' outside function"), + Self::InvalidAwait => write!(f, "'await' outside async function"), + Self::InvalidAsyncFor => write!(f, "'async for' outside async function"), + Self::InvalidAsyncWith => write!(f, "'async with' outside async function"), + Self::InvalidAsyncComprehension => { write!( f, "asynchronous comprehension outside of an asynchronous function" ) } - AsyncYieldFrom => write!(f, "'yield from' inside async function"), - AsyncReturnValue => { + Self::AsyncYieldFrom => write!(f, "'yield from' inside async function"), + Self::AsyncReturnValue => { write!(f, "'return' with value inside async generator") } - InvalidFuturePlacement => write!( + Self::InvalidFuturePlacement => write!( f, "from __future__ imports must occur at the beginning of the file" ), - InvalidFutureFeature(feat) => { + Self::InvalidFutureFeature(feat) => { write!(f, "future feature {feat} is not defined") } - FunctionImportStar => { + Self::FunctionImportStar => { write!(f, "import * only allowed at module level") } - TooManyStarUnpack => { + Self::TooManyStarUnpack => { write!(f, "too many expressions in star-unpacking assignment") } - EmptyWithItems => { + Self::EmptyWithItems => { write!(f, "empty items on With") } - EmptyWithBody => { + Self::EmptyWithBody => { write!(f, "empty body on With") } - ForbiddenName => { + Self::ForbiddenName => { write!(f, "forbidden attribute name") } - DuplicateStore(s) => { + Self::DuplicateStore(s) => { write!(f, "duplicate store {s}") } - UnreachablePattern(reason) => { + Self::UnreachablePattern(reason) => { write!(f, "{reason} makes remaining patterns unreachable") } - RepeatedAttributePattern => { + Self::RepeatedAttributePattern => { write!(f, "attribute name repeated in class pattern") } - ConflictingNameBindPattern => { + Self::ConflictingNameBindPattern => { write!(f, "alternative patterns bind different names") } - BreakContinueReturnInExceptStar => { + Self::BreakContinueReturnInExceptStar => { write!( f, "'break', 'continue' and 'return' cannot appear in an except* block" ) } - NotImplementedYet => { + Self::NotImplementedYet => { write!(f, "RustPython does not implement this feature yet") } } From d332789d714f0ad0ba29fea0566aaaf2ab61308b Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Tue, 19 May 2026 13:19:41 +0300 Subject: [PATCH 10/10] Fix accedental deletion --- Lib/test/test_syntax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 0be25357009..7d5ffc7a3f7 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -1318,7 +1318,7 @@ Traceback (most recent call last): SyntaxError: Function parameters cannot be parenthesized - >>> def f((x, y, z, w)) # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE + >>> def f((x, y, z, w)): # TODO: RUSTPYTHON; Wrong error message # doctest: +EXPECTED_FAILURE ... pass Traceback (most recent call last): SyntaxError: Function parameters cannot be parenthesized