diff --git a/Grammar/python.gram b/Grammar/python.gram index 53288a5418c931..cb23dec73c9157 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -1259,7 +1259,7 @@ invalid_parameters: | (slash_no_default | slash_with_default) param_maybe_default* a='/' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "/ may appear only once") } | slash_no_default? param_no_default* invalid_parameters_helper a=param_no_default { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "parameter without a default follows parameter with a default") } + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "positional parameter without a default follows parameter with a default") } | param_no_default* a='(' param_no_default+ ','? b=')' { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "Function parameters cannot be parenthesized") } | (slash_no_default | slash_with_default)? param_maybe_default* '*' (',' | param_no_default) param_maybe_default* a='/' { @@ -1287,7 +1287,7 @@ invalid_lambda_parameters: | (lambda_slash_no_default | lambda_slash_with_default) lambda_param_maybe_default* a='/' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "/ may appear only once") } | lambda_slash_no_default? lambda_param_no_default* invalid_lambda_parameters_helper a=lambda_param_no_default { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "parameter without a default follows parameter with a default") } + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "positional parameter without a default follows parameter with a default") } | lambda_param_no_default* a='(' ','.lambda_param+ ','? b=')' { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "Lambda expression parameters cannot be parenthesized") } | (lambda_slash_no_default | lambda_slash_with_default)? lambda_param_maybe_default* '*' (',' | lambda_param_no_default) lambda_param_maybe_default* a='/' { diff --git a/Lib/test/test_positional_only_arg.py b/Lib/test/test_positional_only_arg.py index eea0625012da6d..928a02c4230f31 100644 --- a/Lib/test/test_positional_only_arg.py +++ b/Lib/test/test_positional_only_arg.py @@ -24,11 +24,11 @@ def assertRaisesSyntaxError(self, codestr, regex="invalid syntax"): compile(codestr + "\n", "", "single") def test_invalid_syntax_errors(self): - check_syntax_error(self, "def f(a, b = 5, /, c): pass", "parameter without a default follows parameter with a default") - check_syntax_error(self, "def f(a = 5, b, /, c): pass", "parameter without a default follows parameter with a default") - check_syntax_error(self, "def f(a = 5, b=1, /, c, *, d=2): pass", "parameter without a default follows parameter with a default") - check_syntax_error(self, "def f(a = 5, b, /): pass", "parameter without a default follows parameter with a default") - check_syntax_error(self, "def f(a, /, b = 5, c): pass", "parameter without a default follows parameter with a default") + check_syntax_error(self, "def f(a, b = 5, /, c): pass", "positional parameter without a default follows parameter with a default") + check_syntax_error(self, "def f(a = 5, b, /, c): pass", "positional parameter without a default follows parameter with a default") + check_syntax_error(self, "def f(a = 5, b=1, /, c, *, d=2): pass", "positional parameter without a default follows parameter with a default") + check_syntax_error(self, "def f(a = 5, b, /): pass", "positional parameter without a default follows parameter with a default") + check_syntax_error(self, "def f(a, /, b = 5, c): pass", "positional parameter without a default follows parameter with a default") check_syntax_error(self, "def f(*args, /): pass") check_syntax_error(self, "def f(*args, a, /): pass") check_syntax_error(self, "def f(**kwargs, /): pass") @@ -46,11 +46,11 @@ def test_invalid_syntax_errors(self): check_syntax_error(self, "def f(a, *, c, /, d, e): pass") def test_invalid_syntax_errors_async(self): - check_syntax_error(self, "async def f(a, b = 5, /, c): pass", "parameter without a default follows parameter with a default") - check_syntax_error(self, "async def f(a = 5, b, /, c): pass", "parameter without a default follows parameter with a default") - check_syntax_error(self, "async def f(a = 5, b=1, /, c, d=2): pass", "parameter without a default follows parameter with a default") - check_syntax_error(self, "async def f(a = 5, b, /): pass", "parameter without a default follows parameter with a default") - check_syntax_error(self, "async def f(a, /, b = 5, c): pass", "parameter without a default follows parameter with a default") + check_syntax_error(self, "async def f(a, b = 5, /, c): pass", "positional parameter without a default follows parameter with a default") + check_syntax_error(self, "async def f(a = 5, b, /, c): pass", "positional parameter without a default follows parameter with a default") + check_syntax_error(self, "async def f(a = 5, b=1, /, c, d=2): pass", "positional parameter without a default follows parameter with a default") + check_syntax_error(self, "async def f(a = 5, b, /): pass", "positional parameter without a default follows parameter with a default") + check_syntax_error(self, "async def f(a, /, b = 5, c): pass", "positional parameter without a default follows parameter with a default") 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(**kwargs, /): pass") @@ -234,11 +234,11 @@ def test_lambdas(self): self.assertEqual(x(1, 2), 3) def test_invalid_syntax_lambda(self): - check_syntax_error(self, "lambda a, b = 5, /, c: None", "parameter without a default follows parameter with a default") - check_syntax_error(self, "lambda a = 5, b, /, c: None", "parameter without a default follows parameter with a default") - check_syntax_error(self, "lambda a = 5, b=1, /, c, *, d=2: None", "parameter without a default follows parameter with a default") - check_syntax_error(self, "lambda a = 5, b, /: None", "parameter without a default follows parameter with a default") - check_syntax_error(self, "lambda a, /, b = 5, c: None", "parameter without a default follows parameter with a default") + check_syntax_error(self, "lambda a, b = 5, /, c: None", "positional parameter without a default follows parameter with a default") + check_syntax_error(self, "lambda a = 5, b, /, c: None", "positional parameter without a default follows parameter with a default") + check_syntax_error(self, "lambda a = 5, b=1, /, c, *, d=2: None", "positional parameter without a default follows parameter with a default") + check_syntax_error(self, "lambda a = 5, b, /: None", "positional parameter without a default follows parameter with a default") + check_syntax_error(self, "lambda a, /, b = 5, c: None", "positional parameter without a default follows parameter with a default") check_syntax_error(self, "lambda *args, /: None") check_syntax_error(self, "lambda *args, a, /: None") check_syntax_error(self, "lambda **kwargs, /: None") diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 707d4fc6df16ea..a95b11dabc768e 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -394,12 +394,12 @@ >>> def f(x, y=1, z): ... pass Traceback (most recent call last): -SyntaxError: parameter without a default follows parameter with a default +SyntaxError: positional parameter without a default follows parameter with a default >>> def f(x, /, y=1, z): ... pass Traceback (most recent call last): -SyntaxError: parameter without a default follows parameter with a default +SyntaxError: positional parameter without a default follows parameter with a default >>> def f(x, None): ... pass @@ -622,11 +622,11 @@ >>> lambda a,d=3,c: None Traceback (most recent call last): -SyntaxError: parameter without a default follows parameter with a default +SyntaxError: positional parameter without a default follows parameter with a default >>> lambda a,/,d=3,c: None Traceback (most recent call last): -SyntaxError: parameter without a default follows parameter with a default +SyntaxError: positional parameter without a default follows parameter with a default >>> import ast; ast.parse(''' ... def f( diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-03-07-16-48-12.gh-issue-129545.t-9iTH.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-03-07-16-48-12.gh-issue-129545.t-9iTH.rst new file mode 100644 index 00000000000000..b254ca2edb2279 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-03-07-16-48-12.gh-issue-129545.t-9iTH.rst @@ -0,0 +1,3 @@ +Change the text of the ``SyntaxError: parameter without a default follows parameter with a default`` +to ``SyntaxError: positional parameter without a default follows parameter with a default`` to improve +error message clarity in certain cases. diff --git a/Parser/parser.c b/Parser/parser.c index edebddc95f968e..9cb0603f05666a 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -21487,7 +21487,7 @@ invalid_parameters_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default? param_no_default* invalid_parameters_helper param_no_default")); - _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameter without a default follows parameter with a default" ); + _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "positional parameter without a default follows parameter with a default" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--; @@ -22078,7 +22078,7 @@ invalid_lambda_parameters_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default? lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); - _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameter without a default follows parameter with a default" ); + _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "positional parameter without a default follows parameter with a default" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--;