Skip to content

Commit d55ed7b

Browse files
Raise specialised syntax error for invalid lambda parameters (GH-20776)
(cherry picked from commit c6483c9) Co-authored-by: Pablo Galindo <[email protected]>
1 parent 73b728a commit d55ed7b

File tree

3 files changed

+732
-426
lines changed

3 files changed

+732
-426
lines changed

Grammar/python.gram

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,11 @@ expression[expr_ty] (memo):
329329
| lambdef
330330

331331
lambdef[expr_ty]:
332-
| 'lambda' a=[lambda_parameters] ':' b=expression { _Py_Lambda((a) ? a : CHECK(_PyPegen_empty_arguments(p)), b, EXTRA) }
332+
| 'lambda' a=[lambda_params] ':' b=expression { _Py_Lambda((a) ? a : CHECK(_PyPegen_empty_arguments(p)), b, EXTRA) }
333+
334+
lambda_params[arguments_ty]:
335+
| invalid_lambda_parameters
336+
| lambda_parameters
333337

334338
# lambda_parameters etc. duplicates parameters but without annotations
335339
# or type comments, and if there's no comma after a parameter, we expect
@@ -669,6 +673,9 @@ invalid_dict_comprehension:
669673
invalid_parameters:
670674
| param_no_default* (slash_with_default | param_with_default+) param_no_default {
671675
RAISE_SYNTAX_ERROR("non-default argument follows default argument") }
676+
invalid_lambda_parameters:
677+
| lambda_param_no_default* (lambda_slash_with_default | lambda_param_with_default+) lambda_param_no_default {
678+
RAISE_SYNTAX_ERROR("non-default argument follows default argument") }
672679
invalid_star_etc:
673680
| '*' (')' | ',' (')' | '**')) { RAISE_SYNTAX_ERROR("named arguments must follow bare *") }
674681
| '*' ',' TYPE_COMMENT { RAISE_SYNTAX_ERROR("bare * has associated type comment") }

Lib/test/test_positional_only_arg.py

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pickle
55
import unittest
66

7-
from test.support import check_syntax_error, use_old_parser
7+
from test.support import check_syntax_error
88

99

1010
def global_pos_only_f(a, b, /):
@@ -23,12 +23,10 @@ def assertRaisesSyntaxError(self, codestr, regex="invalid syntax"):
2323
compile(codestr + "\n", "<test>", "single")
2424

2525
def test_invalid_syntax_errors(self):
26-
if use_old_parser():
27-
check_syntax_error(self, "def f(a, b = 5, /, c): pass", "non-default argument follows default argument")
28-
check_syntax_error(self, "def f(a = 5, b, /, c): pass", "non-default argument follows default argument")
29-
check_syntax_error(self, "def f(a = 5, b=1, /, c, *, d=2): pass", "non-default argument follows default argument")
30-
check_syntax_error(self, "def f(a = 5, b, /): pass", "non-default argument follows default argument")
31-
26+
check_syntax_error(self, "def f(a, b = 5, /, c): pass", "non-default argument follows default argument")
27+
check_syntax_error(self, "def f(a = 5, b, /, c): pass", "non-default argument follows default argument")
28+
check_syntax_error(self, "def f(a = 5, b=1, /, c, *, d=2): pass", "non-default argument follows default argument")
29+
check_syntax_error(self, "def f(a = 5, b, /): pass", "non-default argument follows default argument")
3230
check_syntax_error(self, "def f(*args, /): pass")
3331
check_syntax_error(self, "def f(*args, a, /): pass")
3432
check_syntax_error(self, "def f(**kwargs, /): pass")
@@ -46,12 +44,10 @@ def test_invalid_syntax_errors(self):
4644
check_syntax_error(self, "def f(a, *, c, /, d, e): pass")
4745

4846
def test_invalid_syntax_errors_async(self):
49-
if use_old_parser():
50-
check_syntax_error(self, "async def f(a, b = 5, /, c): pass", "non-default argument follows default argument")
51-
check_syntax_error(self, "async def f(a = 5, b, /, c): pass", "non-default argument follows default argument")
52-
check_syntax_error(self, "async def f(a = 5, b=1, /, c, d=2): pass", "non-default argument follows default argument")
53-
check_syntax_error(self, "async def f(a = 5, b, /): pass", "non-default argument follows default argument")
54-
47+
check_syntax_error(self, "async def f(a, b = 5, /, c): pass", "non-default argument follows default argument")
48+
check_syntax_error(self, "async def f(a = 5, b, /, c): pass", "non-default argument follows default argument")
49+
check_syntax_error(self, "async def f(a = 5, b=1, /, c, d=2): pass", "non-default argument follows default argument")
50+
check_syntax_error(self, "async def f(a = 5, b, /): pass", "non-default argument follows default argument")
5551
check_syntax_error(self, "async def f(*args, /): pass")
5652
check_syntax_error(self, "async def f(*args, a, /): pass")
5753
check_syntax_error(self, "async def f(**kwargs, /): pass")
@@ -235,11 +231,9 @@ def test_lambdas(self):
235231
self.assertEqual(x(1, 2), 3)
236232

237233
def test_invalid_syntax_lambda(self):
238-
if use_old_parser():
239-
check_syntax_error(self, "lambda a, b = 5, /, c: None", "non-default argument follows default argument")
240-
check_syntax_error(self, "lambda a = 5, b, /, c: None", "non-default argument follows default argument")
241-
check_syntax_error(self, "lambda a = 5, b, /: None", "non-default argument follows default argument")
242-
234+
check_syntax_error(self, "lambda a, b = 5, /, c: None", "non-default argument follows default argument")
235+
check_syntax_error(self, "lambda a = 5, b, /, c: None", "non-default argument follows default argument")
236+
check_syntax_error(self, "lambda a = 5, b, /: None", "non-default argument follows default argument")
243237
check_syntax_error(self, "lambda *args, /: None")
244238
check_syntax_error(self, "lambda *args, a, /: None")
245239
check_syntax_error(self, "lambda **kwargs, /: None")

0 commit comments

Comments
 (0)