mirror of https://github.com/python/cpython
bpo-40334: Spacialized error message for invalid args after bare '*' (GH-19865)
When parsing things like `def f(*): pass` the old parser used to output `SyntaxError: named arguments must follow bare *`, which the new parser wasn't able to do.
This commit is contained in:
parent
c3f001461d
commit
e10e7c771b
|
@ -249,6 +249,7 @@ star_etc[StarEtc*]:
|
||||||
| '*' ',' b=param_maybe_default+ c=[kwds] {
|
| '*' ',' b=param_maybe_default+ c=[kwds] {
|
||||||
_PyPegen_star_etc(p, NULL, b, c) }
|
_PyPegen_star_etc(p, NULL, b, c) }
|
||||||
| a=kwds { _PyPegen_star_etc(p, NULL, NULL, a) }
|
| a=kwds { _PyPegen_star_etc(p, NULL, NULL, a) }
|
||||||
|
| invalid_star_etc
|
||||||
|
|
||||||
kwds[arg_ty]: '**' a=param_no_default { a }
|
kwds[arg_ty]: '**' a=param_no_default { a }
|
||||||
|
|
||||||
|
@ -356,6 +357,7 @@ lambda_star_etc[StarEtc*]:
|
||||||
| '*' ',' b=lambda_param_maybe_default+ c=[lambda_kwds] {
|
| '*' ',' b=lambda_param_maybe_default+ c=[lambda_kwds] {
|
||||||
_PyPegen_star_etc(p, NULL, b, c) }
|
_PyPegen_star_etc(p, NULL, b, c) }
|
||||||
| a=lambda_kwds { _PyPegen_star_etc(p, NULL, NULL, a) }
|
| a=lambda_kwds { _PyPegen_star_etc(p, NULL, NULL, a) }
|
||||||
|
| invalid_lambda_star_etc
|
||||||
|
|
||||||
lambda_kwds[arg_ty]: '**' a=lambda_param_no_default { a }
|
lambda_kwds[arg_ty]: '**' a=lambda_param_no_default { a }
|
||||||
|
|
||||||
|
@ -636,6 +638,10 @@ invalid_comprehension:
|
||||||
invalid_parameters:
|
invalid_parameters:
|
||||||
| param_no_default* (slash_with_default | param_with_default+) param_no_default {
|
| param_no_default* (slash_with_default | param_with_default+) param_no_default {
|
||||||
RAISE_SYNTAX_ERROR("non-default argument follows default argument") }
|
RAISE_SYNTAX_ERROR("non-default argument follows default argument") }
|
||||||
|
invalid_star_etc:
|
||||||
|
| '*' (')' | ',' (')' | '**')) { RAISE_SYNTAX_ERROR("named arguments must follow bare *") }
|
||||||
|
invalid_lambda_star_etc:
|
||||||
|
| '*' (':' | ',' (':' | '**')) { RAISE_SYNTAX_ERROR("named arguments must follow bare *") }
|
||||||
invalid_double_type_comments:
|
invalid_double_type_comments:
|
||||||
| TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT {
|
| TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT {
|
||||||
RAISE_SYNTAX_ERROR("Cannot have two type comments on def") }
|
RAISE_SYNTAX_ERROR("Cannot have two type comments on def") }
|
||||||
|
|
|
@ -242,11 +242,11 @@ class ExceptionTests(unittest.TestCase):
|
||||||
check('from __future__ import doesnt_exist', 1, 1)
|
check('from __future__ import doesnt_exist', 1, 1)
|
||||||
check('from __future__ import braces', 1, 1)
|
check('from __future__ import braces', 1, 1)
|
||||||
check('x=1\nfrom __future__ import division', 2, 1)
|
check('x=1\nfrom __future__ import division', 2, 1)
|
||||||
|
check('def f(*):\n pass', 1, 7 if support.use_old_parser() else 8)
|
||||||
|
|
||||||
@support.skip_if_new_parser("Pegen column offsets might be different")
|
@support.skip_if_new_parser("Pegen column offsets might be different")
|
||||||
def testSyntaxErrorOffsetCustom(self):
|
def testSyntaxErrorOffsetCustom(self):
|
||||||
self.check('for 1 in []: pass', 1, 5)
|
self.check('for 1 in []: pass', 1, 5)
|
||||||
self.check('def f(*):\n pass', 1, 7)
|
|
||||||
self.check('[*x for x in xs]', 1, 2)
|
self.check('[*x for x in xs]', 1, 2)
|
||||||
self.check('def f():\n x, y: int', 2, 3)
|
self.check('def f():\n x, y: int', 2, 3)
|
||||||
self.check('(yield i) = 2', 1, 1)
|
self.check('(yield i) = 2', 1, 1)
|
||||||
|
|
|
@ -603,6 +603,12 @@ FAIL_SPECIALIZED_MESSAGE_CASES = [
|
||||||
("1 += 1", "cannot assign to literal"),
|
("1 += 1", "cannot assign to literal"),
|
||||||
("pass\n pass", "unexpected indent"),
|
("pass\n pass", "unexpected indent"),
|
||||||
("def f():\npass", "expected an indented block"),
|
("def f():\npass", "expected an indented block"),
|
||||||
|
("def f(*): pass", "named arguments must follow bare *"),
|
||||||
|
("def f(*,): pass", "named arguments must follow bare *"),
|
||||||
|
("def f(*, **a): pass", "named arguments must follow bare *"),
|
||||||
|
("lambda *: pass", "named arguments must follow bare *"),
|
||||||
|
("lambda *,: pass", "named arguments must follow bare *"),
|
||||||
|
("lambda *, **a: pass", "named arguments must follow bare *"),
|
||||||
]
|
]
|
||||||
|
|
||||||
GOOD_BUT_FAIL_TEST_CASES = [
|
GOOD_BUT_FAIL_TEST_CASES = [
|
||||||
|
|
|
@ -627,9 +627,9 @@ Corner-cases that used to fail to raise the correct error:
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
SyntaxError: cannot assign to __debug__
|
SyntaxError: cannot assign to __debug__
|
||||||
|
|
||||||
# >>> with (lambda *:0): pass
|
>>> with (lambda *:0): pass
|
||||||
# Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
# SyntaxError: named arguments must follow bare *
|
SyntaxError: named arguments must follow bare *
|
||||||
|
|
||||||
Corner-cases that used to crash:
|
Corner-cases that used to crash:
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue