]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-133999: Fix `except` parsing regression in 3.14 (GH-134035) (#134206)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 19 May 2025 11:26:27 +0000 (13:26 +0200)
committerGitHub <noreply@github.com>
Mon, 19 May 2025 11:26:27 +0000 (14:26 +0300)
gh-133999: Fix `except` parsing regression in 3.14 (GH-134035)
(cherry picked from commit 84914ad0e5f96f0ca7238f3b4bc7fc4e50b1abb3)

Co-authored-by: sobolevn <mail@sobolevn.me>
Grammar/python.gram
Lib/test/test_syntax.py
Misc/NEWS.d/next/Core_and_Builtins/2025-05-15-11-38-16.gh-issue-133999.uBZ8uS.rst [new file with mode: 0644]
Parser/parser.c

index 528075b8bc0d71224e74f486e3140b5508b15c47..8b15cf29fa02e2ba7b20817da51c9aa92b64593c 100644 (file)
@@ -1418,7 +1418,7 @@ invalid_except_stmt:
         RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types must be parenthesized when using 'as'") }
     | a='except' expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
     | a='except' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
-    | 'except' expression 'as' a=expression {
+    | 'except' expression 'as' a=expression ':' block {
         RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
             a, "cannot use except statement with %s", _PyPegen_get_expr_name(a)) }
 invalid_except_star_stmt:
@@ -1426,7 +1426,7 @@ invalid_except_star_stmt:
         RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types must be parenthesized when using 'as'") }
     | a='except' '*' expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
     | a='except' '*' (NEWLINE | ':') { RAISE_SYNTAX_ERROR("expected one or more exception types") }
-    | 'except' '*' expression 'as' a=expression {
+    | 'except' '*' expression 'as' a=expression ':' block {
         RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
             a, "cannot use except* statement with %s", _PyPegen_get_expr_name(a)) }
 invalid_finally_stmt:
index 0ee17849e2812172eed58715ef954b39111fe333..fadafd9b3d3aead29dbd33294075530084a8eda3 100644 (file)
@@ -1431,6 +1431,23 @@ Better error message for using `except as` with not a name:
    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):
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-05-15-11-38-16.gh-issue-133999.uBZ8uS.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-15-11-38-16.gh-issue-133999.uBZ8uS.rst
new file mode 100644 (file)
index 0000000..7d9c496
--- /dev/null
@@ -0,0 +1,2 @@
+Fix :exc:`SyntaxError` regression in :keyword:`except` parsing after
+:gh:`123440`.
index 509fac7df6e37176afcfa6528a51ef0828b6e299..dc55e391d29280019b3cb4ddd40d85cc047a0eba 100644 (file)
@@ -24202,7 +24202,7 @@ invalid_try_stmt_rule(Parser *p)
 //     | 'except' expression ',' expressions 'as' NAME ':'
 //     | 'except' expression ['as' NAME] NEWLINE
 //     | 'except' NEWLINE
-//     | 'except' expression 'as' expression
+//     | 'except' expression 'as' expression ':' block
 static void *
 invalid_except_stmt_rule(Parser *p)
 {
@@ -24318,15 +24318,17 @@ invalid_except_stmt_rule(Parser *p)
         D(fprintf(stderr, "%*c%s invalid_except_stmt[%d-%d]: %s failed!\n", p->level, ' ',
                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' NEWLINE"));
     }
-    { // 'except' expression 'as' expression
+    { // 'except' expression 'as' expression ':' block
         if (p->error_indicator) {
             p->level--;
             return NULL;
         }
-        D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression 'as' expression"));
+        D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression 'as' expression ':' block"));
         Token * _keyword;
         Token * _keyword_1;
+        Token * _literal;
         expr_ty a;
+        asdl_stmt_seq* block_var;
         expr_ty expression_var;
         if (
             (_keyword = _PyPegen_expect_token(p, 677))  // token='except'
@@ -24336,9 +24338,13 @@ invalid_except_stmt_rule(Parser *p)
             (_keyword_1 = _PyPegen_expect_token(p, 680))  // token='as'
             &&
             (a = expression_rule(p))  // expression
+            &&
+            (_literal = _PyPegen_expect_token(p, 11))  // token=':'
+            &&
+            (block_var = block_rule(p))  // block
         )
         {
-            D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression 'as' expression"));
+            D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression 'as' expression ':' block"));
             _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use except statement with %s" , _PyPegen_get_expr_name ( a ) );
             if (_res == NULL && PyErr_Occurred()) {
                 p->error_indicator = 1;
@@ -24349,7 +24355,7 @@ invalid_except_stmt_rule(Parser *p)
         }
         p->mark = _mark;
         D(fprintf(stderr, "%*c%s invalid_except_stmt[%d-%d]: %s failed!\n", p->level, ' ',
-                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' expression 'as' expression"));
+                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' expression 'as' expression ':' block"));
     }
     _res = NULL;
   done:
@@ -24361,7 +24367,7 @@ invalid_except_stmt_rule(Parser *p)
 //     | 'except' '*' expression ',' expressions 'as' NAME ':'
 //     | 'except' '*' expression ['as' NAME] NEWLINE
 //     | 'except' '*' (NEWLINE | ':')
-//     | 'except' '*' expression 'as' expression
+//     | 'except' '*' expression 'as' expression ':' block
 static void *
 invalid_except_star_stmt_rule(Parser *p)
 {
@@ -24486,16 +24492,18 @@ invalid_except_star_stmt_rule(Parser *p)
         D(fprintf(stderr, "%*c%s invalid_except_star_stmt[%d-%d]: %s failed!\n", p->level, ' ',
                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' '*' (NEWLINE | ':')"));
     }
-    { // 'except' '*' expression 'as' expression
+    { // 'except' '*' expression 'as' expression ':' block
         if (p->error_indicator) {
             p->level--;
             return NULL;
         }
-        D(fprintf(stderr, "%*c> invalid_except_star_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' expression 'as' expression"));
+        D(fprintf(stderr, "%*c> invalid_except_star_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' expression 'as' expression ':' block"));
         Token * _keyword;
         Token * _keyword_1;
         Token * _literal;
+        Token * _literal_1;
         expr_ty a;
+        asdl_stmt_seq* block_var;
         expr_ty expression_var;
         if (
             (_keyword = _PyPegen_expect_token(p, 677))  // token='except'
@@ -24507,9 +24515,13 @@ invalid_except_star_stmt_rule(Parser *p)
             (_keyword_1 = _PyPegen_expect_token(p, 680))  // token='as'
             &&
             (a = expression_rule(p))  // expression
+            &&
+            (_literal_1 = _PyPegen_expect_token(p, 11))  // token=':'
+            &&
+            (block_var = block_rule(p))  // block
         )
         {
-            D(fprintf(stderr, "%*c+ invalid_except_star_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression 'as' expression"));
+            D(fprintf(stderr, "%*c+ invalid_except_star_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression 'as' expression ':' block"));
             _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use except* statement with %s" , _PyPegen_get_expr_name ( a ) );
             if (_res == NULL && PyErr_Occurred()) {
                 p->error_indicator = 1;
@@ -24520,7 +24532,7 @@ invalid_except_star_stmt_rule(Parser *p)
         }
         p->mark = _mark;
         D(fprintf(stderr, "%*c%s invalid_except_star_stmt[%d-%d]: %s failed!\n", p->level, ' ',
-                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' '*' expression 'as' expression"));
+                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' '*' expression 'as' expression ':' block"));
     }
     _res = NULL;
   done: