Skip to content

Commit e451a89

Browse files
authored
gh-123440: Improve error message for except as used with not a name (#123442)
1 parent d8e69b2 commit e451a89

File tree

4 files changed

+1282
-972
lines changed

4 files changed

+1282
-972
lines changed

Grammar/python.gram

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ except_star_block[excepthandler_ty]:
434434
| invalid_except_star_stmt_indent
435435
| 'except' '*' e=expression t=['as' z=NAME { z }] ':' b=block {
436436
_PyAST_ExceptHandler(e, (t) ? ((expr_ty) t)->v.Name.id : NULL, b, EXTRA) }
437-
| invalid_except_stmt
437+
| invalid_except_star_stmt
438438
finally_block[asdl_stmt_seq*]:
439439
| invalid_finally_stmt
440440
| 'finally' &&':' a=block { a }
@@ -1340,11 +1340,21 @@ invalid_try_stmt:
13401340
| 'try' ':' block* except_star_block+ a='except' [expression ['as' NAME]] ':' {
13411341
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot have both 'except' and 'except*' on the same 'try'") }
13421342
invalid_except_stmt:
1343-
| 'except' '*'? a=expression ',' expressions ['as' NAME ] ':' {
1343+
| 'except' a=expression ',' expressions ['as' NAME ] ':' {
13441344
RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types must be parenthesized") }
1345-
| a='except' '*'? expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
1345+
| a='except' expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
13461346
| a='except' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
1347+
| 'except' expression 'as' a=expression {
1348+
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
1349+
a, "cannot use except statement with %s", _PyPegen_get_expr_name(a)) }
1350+
invalid_except_star_stmt:
1351+
| 'except' '*' a=expression ',' expressions ['as' NAME ] ':' {
1352+
RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types must be parenthesized") }
1353+
| a='except' '*' expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
13471354
| a='except' '*' (NEWLINE | ':') { RAISE_SYNTAX_ERROR("expected one or more exception types") }
1355+
| 'except' '*' expression 'as' a=expression {
1356+
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
1357+
a, "cannot use except* statement with %s", _PyPegen_get_expr_name(a)) }
13481358
invalid_finally_stmt:
13491359
| a='finally' ':' NEWLINE !INDENT {
13501360
RAISE_INDENTATION_ERROR("expected an indented block after 'finally' statement on line %d", a->lineno) }

Lib/test/test_syntax.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,36 @@
13591359
Traceback (most recent call last):
13601360
SyntaxError: cannot have both 'except' and 'except*' on the same 'try'
13611361
1362+
Better error message for using `except as` with not a name:
1363+
1364+
>>> try:
1365+
... pass
1366+
... except TypeError as obj.attr:
1367+
... pass
1368+
Traceback (most recent call last):
1369+
SyntaxError: cannot use except statement with attribute
1370+
1371+
>>> try:
1372+
... pass
1373+
... except TypeError as obj[1]:
1374+
... pass
1375+
Traceback (most recent call last):
1376+
SyntaxError: cannot use except statement with subscript
1377+
1378+
>>> try:
1379+
... pass
1380+
... except* TypeError as (obj, name):
1381+
... pass
1382+
Traceback (most recent call last):
1383+
SyntaxError: cannot use except* statement with tuple
1384+
1385+
>>> try:
1386+
... pass
1387+
... except* TypeError as 1:
1388+
... pass
1389+
Traceback (most recent call last):
1390+
SyntaxError: cannot use except* statement with literal
1391+
13621392
Ensure that early = are not matched by the parser as invalid comparisons
13631393
>>> f(2, 4, x=34); 1 $ 2
13641394
Traceback (most recent call last):
@@ -2770,6 +2800,23 @@ def test_deep_invalid_rule(self):
27702800
with self.assertRaises(SyntaxError):
27712801
compile(source, "<string>", "exec")
27722802

2803+
def test_except_stmt_invalid_as_expr(self):
2804+
self._check_error(
2805+
textwrap.dedent(
2806+
"""
2807+
try:
2808+
pass
2809+
except ValueError as obj.attr:
2810+
pass
2811+
"""
2812+
),
2813+
errtext="cannot use except statement with attribute",
2814+
lineno=4,
2815+
end_lineno=4,
2816+
offset=22,
2817+
end_offset=22 + len("obj.attr"),
2818+
)
2819+
27732820

27742821
def load_tests(loader, tests, pattern):
27752822
tests.addTest(doctest.DocTestSuite())
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve :exc:`SyntaxError` message for using ``except as`` with not a name.

0 commit comments

Comments
 (0)