https://github.com/python/cpython/commit/84914ad0e5f96f0ca7238f3b4bc7fc4e50b1abb3
commit: 84914ad0e5f96f0ca7238f3b4bc7fc4e50b1abb3
branch: main
author: sobolevn <[email protected]>
committer: sobolevn <[email protected]>
date: 2025-05-17T17:57:02+03:00
summary:
gh-133999: Fix `except` parsing regression in 3.14 (#134035)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2025-05-15-11-38-16.gh-issue-133999.uBZ8uS.rst
M Grammar/python.gram
M Lib/test/test_syntax.py
M Parser/parser.c
diff --git a/Grammar/python.gram b/Grammar/python.gram
index 7f0ee11ba7e2e7..de435537095031 100644
--- a/Grammar/python.gram
+++ b/Grammar/python.gram
@@ -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:
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py
index 0eccf03a1a96e3..c7ac791415830f 100644
--- a/Lib/test/test_syntax.py
+++ b/Lib/test/test_syntax.py
@@ -1431,6 +1431,23 @@
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
index 00000000000000..7d9c49688c3ce2
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-15-11-38-16.gh-issue-133999.uBZ8uS.rst
@@ -0,0 +1,2 @@
+Fix :exc:`SyntaxError` regression in :keyword:`except` parsing after
+:gh:`123440`.
diff --git a/Parser/parser.c b/Parser/parser.c
index b48b1b20ee4d8e..84a293cddffde6 100644
--- a/Parser/parser.c
+++ b/Parser/parser.c
@@ -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:
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]