Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions Grammar/python.gram
Original file line number Diff line number Diff line change
Expand Up @@ -649,9 +649,10 @@ type_param_seq[asdl_type_param_seq*]: a[asdl_type_param_seq*]=','.type_param+ ['

type_param[type_param_ty] (memo):
| a=NAME b=[type_param_bound] c=[type_param_default] { _PyAST_TypeVar(a->v.Name.id, b, c, EXTRA) }
| invalid_type_param
| invalid_type_param_def
| '*' a=NAME b=[type_param_starred_default] { _PyAST_TypeVarTuple(a->v.Name.id, b, EXTRA) }
| '**' a=NAME b=[type_param_default] { _PyAST_ParamSpec(a->v.Name.id, b, EXTRA) }
| invalid_type_param_expr

type_param_bound[expr_ty]: ':' e=expression { e }
type_param_default[expr_ty]: '=' e=expression {
Expand Down Expand Up @@ -1165,7 +1166,15 @@ invalid_legacy_expression:
_PyPegen_check_legacy_stmt(p, a) ? RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b,
"Missing parentheses in call to '%U'. Did you mean %U(...)?", a->v.Name.id, a->v.Name.id) : NULL}

invalid_type_param:
# Invalid type parameters:

invalid_type_params:
| '[' token=']' {
RAISE_SYNTAX_ERROR_STARTING_FROM(
token,
"Type parameter list cannot be empty")}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Type parameter list cannot be empty")}
"type parameter list cannot be empty")}

We're not completely consistent but most syntax error messages are lowercase.


invalid_type_param_def:
| '*' a=NAME colon=':' e=expression {
RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind
? "cannot use constraints with TypeVarTuple"
Expand All @@ -1177,6 +1186,13 @@ invalid_type_param:
: "cannot use bound with ParamSpec")
}

invalid_type_param_expr:
| ('*' | '**')? a=expression {
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
a, "expected a type parameter definition, found %s",
_PyPegen_get_expr_name(a))
}

invalid_expression:
# !(NAME STRING) is not matched so we don't show this error with some invalid string prefixes like: kf"dsfsdf"
# Soft keywords need to also be ignored because they can be parsed as NAME NAME
Expand Down Expand Up @@ -1453,9 +1469,3 @@ invalid_arithmetic:
| sum ('+'|'-'|'*'|'/'|'%'|'//'|'@') a='not' b=inversion { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "'not' after an operator must be parenthesized") }
invalid_factor:
| ('+' | '-' | '~') a='not' b=factor { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "'not' after an operator must be parenthesized") }

invalid_type_params:
| '[' token=']' {
RAISE_SYNTAX_ERROR_STARTING_FROM(
token,
"Type parameter list cannot be empty")}
30 changes: 30 additions & 0 deletions Lib/test/test_syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -2175,6 +2175,36 @@ def f(x: *b)
...
SyntaxError: Type parameter list cannot be empty

>>> type A[1] = ...
Traceback (most recent call last):
...
SyntaxError: expected a type parameter definition, found literal

>>> type A[*()] = ...
Traceback (most recent call last):
...
SyntaxError: expected a type parameter definition, found tuple

>>> type A[**{}] = ...
Traceback (most recent call last):
...
SyntaxError: expected a type parameter definition, found dict literal

>>> def some["abc"](): ...
Traceback (most recent call last):
...
SyntaxError: expected a type parameter definition, found literal

>>> class Some[*...]: ...
Traceback (most recent call last):
...
SyntaxError: expected a type parameter definition, found ellipsis

>>> async def some[**{}](): ...
Traceback (most recent call last):
...
SyntaxError: expected a type parameter definition, found dict literal

>>> def f[T: (x:=3)](): pass
Traceback (most recent call last):
...
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Improve :exc:`SyntaxError` messages when reporting invalid
:ref:`type parameters <type-params>` definitions.
Loading
Loading