Raise specialised syntax error for invalid lambda parameters (GH-20776)

This commit is contained in:
Pablo Galindo 2020-06-10 14:07:06 +01:00 committed by GitHub
parent 0d00b2a5d7
commit c6483c9896
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 902 additions and 596 deletions

View File

@ -329,7 +329,11 @@ expression[expr_ty] (memo):
| lambdef | lambdef
lambdef[expr_ty]: lambdef[expr_ty]:
| 'lambda' a=[lambda_parameters] ':' b=expression { _Py_Lambda((a) ? a : CHECK(_PyPegen_empty_arguments(p)), b, EXTRA) } | 'lambda' a=[lambda_params] ':' b=expression { _Py_Lambda((a) ? a : CHECK(_PyPegen_empty_arguments(p)), b, EXTRA) }
lambda_params[arguments_ty]:
| invalid_lambda_parameters
| lambda_parameters
# lambda_parameters etc. duplicates parameters but without annotations # lambda_parameters etc. duplicates parameters but without annotations
# or type comments, and if there's no comma after a parameter, we expect # or type comments, and if there's no comma after a parameter, we expect
@ -669,6 +673,9 @@ invalid_dict_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_lambda_parameters:
| lambda_param_no_default* (lambda_slash_with_default | lambda_param_with_default+) lambda_param_no_default {
RAISE_SYNTAX_ERROR("non-default argument follows default argument") }
invalid_star_etc: invalid_star_etc:
| '*' (')' | ',' (')' | '**')) { RAISE_SYNTAX_ERROR("named arguments must follow bare *") } | '*' (')' | ',' (')' | '**')) { RAISE_SYNTAX_ERROR("named arguments must follow bare *") }
| '*' ',' TYPE_COMMENT { RAISE_SYNTAX_ERROR("bare * has associated type comment") } | '*' ',' TYPE_COMMENT { RAISE_SYNTAX_ERROR("bare * has associated type comment") }

View File

@ -4,7 +4,7 @@ import dis
import pickle import pickle
import unittest import unittest
from test.support import check_syntax_error, use_old_parser from test.support import check_syntax_error
def global_pos_only_f(a, b, /): def global_pos_only_f(a, b, /):
@ -23,12 +23,10 @@ class PositionalOnlyTestCase(unittest.TestCase):
compile(codestr + "\n", "<test>", "single") compile(codestr + "\n", "<test>", "single")
def test_invalid_syntax_errors(self): def test_invalid_syntax_errors(self):
if use_old_parser():
check_syntax_error(self, "def f(a, b = 5, /, c): pass", "non-default argument follows default argument") check_syntax_error(self, "def f(a, b = 5, /, c): pass", "non-default argument follows default argument")
check_syntax_error(self, "def f(a = 5, b, /, c): pass", "non-default argument follows default argument") check_syntax_error(self, "def f(a = 5, b, /, c): pass", "non-default argument follows default argument")
check_syntax_error(self, "def f(a = 5, b=1, /, c, *, d=2): pass", "non-default argument follows default argument") check_syntax_error(self, "def f(a = 5, b=1, /, c, *, d=2): pass", "non-default argument follows default argument")
check_syntax_error(self, "def f(a = 5, b, /): pass", "non-default argument follows default argument") check_syntax_error(self, "def f(a = 5, b, /): pass", "non-default argument follows default argument")
check_syntax_error(self, "def f(*args, /): pass") check_syntax_error(self, "def f(*args, /): pass")
check_syntax_error(self, "def f(*args, a, /): pass") check_syntax_error(self, "def f(*args, a, /): pass")
check_syntax_error(self, "def f(**kwargs, /): pass") check_syntax_error(self, "def f(**kwargs, /): pass")
@ -46,12 +44,10 @@ class PositionalOnlyTestCase(unittest.TestCase):
check_syntax_error(self, "def f(a, *, c, /, d, e): pass") check_syntax_error(self, "def f(a, *, c, /, d, e): pass")
def test_invalid_syntax_errors_async(self): def test_invalid_syntax_errors_async(self):
if use_old_parser():
check_syntax_error(self, "async def f(a, b = 5, /, c): pass", "non-default argument follows default argument") check_syntax_error(self, "async def f(a, b = 5, /, c): pass", "non-default argument follows default argument")
check_syntax_error(self, "async def f(a = 5, b, /, c): pass", "non-default argument follows default argument") check_syntax_error(self, "async def f(a = 5, b, /, c): pass", "non-default argument follows default argument")
check_syntax_error(self, "async def f(a = 5, b=1, /, c, d=2): pass", "non-default argument follows default argument") check_syntax_error(self, "async def f(a = 5, b=1, /, c, d=2): pass", "non-default argument follows default argument")
check_syntax_error(self, "async def f(a = 5, b, /): pass", "non-default argument follows default argument") check_syntax_error(self, "async def f(a = 5, b, /): pass", "non-default argument follows default argument")
check_syntax_error(self, "async def f(*args, /): pass") check_syntax_error(self, "async def f(*args, /): pass")
check_syntax_error(self, "async def f(*args, a, /): pass") check_syntax_error(self, "async def f(*args, a, /): pass")
check_syntax_error(self, "async def f(**kwargs, /): pass") check_syntax_error(self, "async def f(**kwargs, /): pass")
@ -235,11 +231,9 @@ class PositionalOnlyTestCase(unittest.TestCase):
self.assertEqual(x(1, 2), 3) self.assertEqual(x(1, 2), 3)
def test_invalid_syntax_lambda(self): def test_invalid_syntax_lambda(self):
if use_old_parser():
check_syntax_error(self, "lambda a, b = 5, /, c: None", "non-default argument follows default argument") check_syntax_error(self, "lambda a, b = 5, /, c: None", "non-default argument follows default argument")
check_syntax_error(self, "lambda a = 5, b, /, c: None", "non-default argument follows default argument") check_syntax_error(self, "lambda a = 5, b, /, c: None", "non-default argument follows default argument")
check_syntax_error(self, "lambda a = 5, b, /: None", "non-default argument follows default argument") check_syntax_error(self, "lambda a = 5, b, /: None", "non-default argument follows default argument")
check_syntax_error(self, "lambda *args, /: None") check_syntax_error(self, "lambda *args, /: None")
check_syntax_error(self, "lambda *args, a, /: None") check_syntax_error(self, "lambda *args, a, /: None")
check_syntax_error(self, "lambda **kwargs, /: None") check_syntax_error(self, "lambda **kwargs, /: None")

File diff suppressed because it is too large Load Diff