mirror of https://github.com/python/cpython
gh-123440: Improve error message for `except as` used with not a name (#123442)
This commit is contained in:
parent
d8e69b2c1b
commit
e451a8937d
|
@ -434,7 +434,7 @@ except_star_block[excepthandler_ty]:
|
||||||
| invalid_except_star_stmt_indent
|
| invalid_except_star_stmt_indent
|
||||||
| 'except' '*' e=expression t=['as' z=NAME { z }] ':' b=block {
|
| 'except' '*' e=expression t=['as' z=NAME { z }] ':' b=block {
|
||||||
_PyAST_ExceptHandler(e, (t) ? ((expr_ty) t)->v.Name.id : NULL, b, EXTRA) }
|
_PyAST_ExceptHandler(e, (t) ? ((expr_ty) t)->v.Name.id : NULL, b, EXTRA) }
|
||||||
| invalid_except_stmt
|
| invalid_except_star_stmt
|
||||||
finally_block[asdl_stmt_seq*]:
|
finally_block[asdl_stmt_seq*]:
|
||||||
| invalid_finally_stmt
|
| invalid_finally_stmt
|
||||||
| 'finally' &&':' a=block { a }
|
| 'finally' &&':' a=block { a }
|
||||||
|
@ -1340,11 +1340,21 @@ invalid_try_stmt:
|
||||||
| 'try' ':' block* except_star_block+ a='except' [expression ['as' NAME]] ':' {
|
| 'try' ':' block* except_star_block+ a='except' [expression ['as' NAME]] ':' {
|
||||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot have both 'except' and 'except*' on the same 'try'") }
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot have both 'except' and 'except*' on the same 'try'") }
|
||||||
invalid_except_stmt:
|
invalid_except_stmt:
|
||||||
| 'except' '*'? a=expression ',' expressions ['as' NAME ] ':' {
|
| 'except' a=expression ',' expressions ['as' NAME ] ':' {
|
||||||
RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types must be parenthesized") }
|
RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types must be parenthesized") }
|
||||||
| a='except' '*'? expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
|
| a='except' expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
|
||||||
| a='except' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
|
| a='except' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
|
||||||
|
| 'except' expression 'as' a=expression {
|
||||||
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
||||||
|
a, "cannot use except statement with %s", _PyPegen_get_expr_name(a)) }
|
||||||
|
invalid_except_star_stmt:
|
||||||
|
| 'except' '*' a=expression ',' expressions ['as' NAME ] ':' {
|
||||||
|
RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types must be parenthesized") }
|
||||||
|
| a='except' '*' expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
|
||||||
| a='except' '*' (NEWLINE | ':') { RAISE_SYNTAX_ERROR("expected one or more exception types") }
|
| a='except' '*' (NEWLINE | ':') { RAISE_SYNTAX_ERROR("expected one or more exception types") }
|
||||||
|
| 'except' '*' expression 'as' a=expression {
|
||||||
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
||||||
|
a, "cannot use except* statement with %s", _PyPegen_get_expr_name(a)) }
|
||||||
invalid_finally_stmt:
|
invalid_finally_stmt:
|
||||||
| a='finally' ':' NEWLINE !INDENT {
|
| a='finally' ':' NEWLINE !INDENT {
|
||||||
RAISE_INDENTATION_ERROR("expected an indented block after 'finally' statement on line %d", a->lineno) }
|
RAISE_INDENTATION_ERROR("expected an indented block after 'finally' statement on line %d", a->lineno) }
|
||||||
|
|
|
@ -1359,6 +1359,36 @@ Custom error message for try block mixing except and except*
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
SyntaxError: cannot have both 'except' and 'except*' on the same 'try'
|
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
|
||||||
|
|
||||||
Ensure that early = are not matched by the parser as invalid comparisons
|
Ensure that early = are not matched by the parser as invalid comparisons
|
||||||
>>> f(2, 4, x=34); 1 $ 2
|
>>> f(2, 4, x=34); 1 $ 2
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
|
@ -2770,6 +2800,23 @@ while 1:
|
||||||
with self.assertRaises(SyntaxError):
|
with self.assertRaises(SyntaxError):
|
||||||
compile(source, "<string>", "exec")
|
compile(source, "<string>", "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 load_tests(loader, tests, pattern):
|
def load_tests(loader, tests, pattern):
|
||||||
tests.addTest(doctest.DocTestSuite())
|
tests.addTest(doctest.DocTestSuite())
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Improve :exc:`SyntaxError` message for using ``except as`` with not a name.
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue