Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8393608

Browse filesBrowse files
gh-122688: Fix support of var-positional parameter in Argument Clinic (GH-122689)
* Parameters after the var-positional parameter are now keyword-only instead of positional-or-keyword. * Correctly calculate min_kw_only. * Raise errors for invalid combinations of the var-positional parameter with "*", "/" and deprecation markers.
1 parent b6e745a commit 8393608
Copy full SHA for 8393608

File tree

Expand file treeCollapse file tree

7 files changed

+203
-96
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+203
-96
lines changed

‎Lib/test/clinic.test.c

Copy file name to clipboardExpand all lines: Lib/test/clinic.test.c
+6-6Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4134,8 +4134,8 @@ test_vararg_and_posonly
41344134
41354135
41364136
a: object
4137-
*args: object
41384137
/
4138+
*args: object
41394139
41404140
[clinic start generated code]*/
41414141

@@ -4177,7 +4177,7 @@ test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t narg
41774177

41784178
static PyObject *
41794179
test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
4180-
/*[clinic end generated code: output=79b75dc07decc8d6 input=08dc2bf7afbf1613]*/
4180+
/*[clinic end generated code: output=79b75dc07decc8d6 input=9cfa748bbff09877]*/
41814181

41824182
/*[clinic input]
41834183
test_vararg
@@ -4920,7 +4920,7 @@ Test_an_metho_arg_named_arg_impl(TestObj *self, int arg)
49204920
/*[clinic input]
49214921
Test.__init__
49224922
*args: object
4923-
/
4923+
49244924
Varargs init method. For example, nargs is translated to PyTuple_GET_SIZE.
49254925
[clinic start generated code]*/
49264926

@@ -4958,14 +4958,14 @@ Test___init__(PyObject *self, PyObject *args, PyObject *kwargs)
49584958

49594959
static int
49604960
Test___init___impl(TestObj *self, PyObject *args)
4961-
/*[clinic end generated code: output=0ed1009fe0dcf98d input=96c3ddc0cd38fc0c]*/
4961+
/*[clinic end generated code: output=0ed1009fe0dcf98d input=2a8bd0033c9ac772]*/
49624962

49634963

49644964
/*[clinic input]
49654965
@classmethod
49664966
Test.__new__
49674967
*args: object
4968-
/
4968+
49694969
Varargs new method. For example, nargs is translated to PyTuple_GET_SIZE.
49704970
[clinic start generated code]*/
49714971

@@ -5002,7 +5002,7 @@ Test(PyTypeObject *type, PyObject *args, PyObject *kwargs)
50025002

50035003
static PyObject *
50045004
Test_impl(PyTypeObject *type, PyObject *args)
5005-
/*[clinic end generated code: output=8b219f6633e2a2e9 input=26a672e2e9750120]*/
5005+
/*[clinic end generated code: output=8b219f6633e2a2e9 input=70ad829df3dd9b84]*/
50065006

50075007

50085008
/*[clinic input]

‎Lib/test/test_clinic.py

Copy file name to clipboardExpand all lines: Lib/test/test_clinic.py
+85-11Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ def __init__(self):
322322
"""
323323
self.expect_failure(block, err, lineno=8)
324324

325-
def test_multiple_star_in_args(self):
325+
def test_star_after_vararg(self):
326326
err = "'my_test_func' uses '*' more than once."
327327
block = """
328328
/*[clinic input]
@@ -336,6 +336,20 @@ def test_multiple_star_in_args(self):
336336
"""
337337
self.expect_failure(block, err, lineno=6)
338338

339+
def test_vararg_after_star(self):
340+
err = "'my_test_func' uses '*' more than once."
341+
block = """
342+
/*[clinic input]
343+
my_test_func
344+
345+
pos_arg: object
346+
*
347+
*args: object
348+
kw_arg: object
349+
[clinic start generated code]*/
350+
"""
351+
self.expect_failure(block, err, lineno=6)
352+
339353
def test_module_already_got_one(self):
340354
err = "Already defined module 'm'!"
341355
block = """
@@ -1787,13 +1801,43 @@ def test_parameters_required_after_depr_star2(self):
17871801
)
17881802
self.expect_failure(block, err, lineno=4)
17891803

1804+
def test_parameters_required_after_depr_star3(self):
1805+
block = """
1806+
module foo
1807+
foo.bar
1808+
a: int
1809+
* [from 3.14]
1810+
*args: object
1811+
b: int
1812+
Docstring.
1813+
"""
1814+
err = (
1815+
"Function 'bar' specifies '* [from ...]' without "
1816+
"following parameters."
1817+
)
1818+
self.expect_failure(block, err, lineno=4)
1819+
17901820
def test_depr_star_must_come_before_star(self):
17911821
block = """
17921822
module foo
17931823
foo.bar
1794-
this: int
1824+
a: int
17951825
*
17961826
* [from 3.14]
1827+
b: int
1828+
Docstring.
1829+
"""
1830+
err = "Function 'bar': '* [from ...]' must precede '*'"
1831+
self.expect_failure(block, err, lineno=4)
1832+
1833+
def test_depr_star_must_come_before_vararg(self):
1834+
block = """
1835+
module foo
1836+
foo.bar
1837+
a: int
1838+
*args: object
1839+
* [from 3.14]
1840+
b: int
17971841
Docstring.
17981842
"""
17991843
err = "Function 'bar': '* [from ...]' must precede '*'"
@@ -1908,7 +1952,7 @@ def test_double_slash(self):
19081952
err = "Function 'bar' uses '/' more than once."
19091953
self.expect_failure(block, err)
19101954

1911-
def test_mix_star_and_slash(self):
1955+
def test_slash_after_star(self):
19121956
block = """
19131957
module foo
19141958
foo.bar
@@ -1921,6 +1965,19 @@ def test_mix_star_and_slash(self):
19211965
err = "Function 'bar': '/' must precede '*'"
19221966
self.expect_failure(block, err)
19231967

1968+
def test_slash_after_vararg(self):
1969+
block = """
1970+
module foo
1971+
foo.bar
1972+
x: int
1973+
y: int
1974+
*args: object
1975+
z: int
1976+
/
1977+
"""
1978+
err = "Function 'bar': '/' must precede '*'"
1979+
self.expect_failure(block, err)
1980+
19241981
def test_depr_star_must_come_after_slash(self):
19251982
block = """
19261983
module foo
@@ -1960,6 +2017,19 @@ def test_star_must_come_after_depr_slash(self):
19602017
err = "Function 'bar': '/ [from ...]' must precede '*'"
19612018
self.expect_failure(block, err, lineno=4)
19622019

2020+
def test_vararg_must_come_after_depr_slash(self):
2021+
block = """
2022+
module foo
2023+
foo.bar
2024+
a: int
2025+
*args: object
2026+
/ [from 3.14]
2027+
b: int
2028+
Docstring.
2029+
"""
2030+
err = "Function 'bar': '/ [from ...]' must precede '*'"
2031+
self.expect_failure(block, err, lineno=4)
2032+
19632033
def test_depr_slash_must_come_after_slash(self):
19642034
block = """
19652035
module foo
@@ -1987,7 +2057,7 @@ def test_parameters_not_permitted_after_slash_for_now(self):
19872057
self.expect_failure(block, err)
19882058

19892059
def test_parameters_no_more_than_one_vararg(self):
1990-
err = "Too many var args"
2060+
err = "Function 'bar' uses '*' more than once."
19912061
block = """
19922062
module foo
19932063
foo.bar
@@ -3319,13 +3389,6 @@ def test_posonly_vararg(self):
33193389
with self.assertRaises(TypeError):
33203390
ac_tester.posonly_vararg(1, 2, 3, b=4)
33213391

3322-
def test_vararg_and_posonly(self):
3323-
with self.assertRaises(TypeError):
3324-
ac_tester.vararg_and_posonly()
3325-
with self.assertRaises(TypeError):
3326-
ac_tester.vararg_and_posonly(1, b=2)
3327-
self.assertEqual(ac_tester.vararg_and_posonly(1, 2, 3, 4), (1, (2, 3, 4)))
3328-
33293392
def test_vararg(self):
33303393
with self.assertRaises(TypeError):
33313394
ac_tester.vararg()
@@ -3363,6 +3426,17 @@ def test_vararg_with_only_defaults(self):
33633426
self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4), ((1, 2, 3, 4), None))
33643427
self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4, b=5), ((1, 2, 3, 4), 5))
33653428

3429+
def test_vararg_kwonly_req_opt(self):
3430+
fn = ac_tester.vararg_kwonly_req_opt
3431+
self.assertRaises(TypeError, fn)
3432+
self.assertEqual(fn(a=1), ((), 1, None, None))
3433+
self.assertEqual(fn(a=1, b=2), ((), 1, 2, None))
3434+
self.assertEqual(fn(a=1, b=2, c=3), ((), 1, 2, 3))
3435+
self.assertRaises(TypeError, fn, 1)
3436+
self.assertEqual(fn(1, a=2), ((1,), 2, None, None))
3437+
self.assertEqual(fn(1, a=2, b=3), ((1,), 2, 3, None))
3438+
self.assertEqual(fn(1, a=2, b=3, c=4), ((1,), 2, 3, 4))
3439+
33663440
def test_gh_32092_oob(self):
33673441
ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6)
33683442

‎Modules/_testclinic.c

Copy file name to clipboardExpand all lines: Modules/_testclinic.c
+21-20Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -981,23 +981,6 @@ posonly_vararg_impl(PyObject *module, PyObject *a, PyObject *b,
981981
}
982982

983983

984-
/*[clinic input]
985-
vararg_and_posonly
986-
987-
a: object
988-
*args: object
989-
/
990-
991-
[clinic start generated code]*/
992-
993-
static PyObject *
994-
vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
995-
/*[clinic end generated code: output=42792f799465a14d input=defe017b19ba52e8]*/
996-
{
997-
return pack_arguments_newref(2, a, args);
998-
}
999-
1000-
1001984
/*[clinic input]
1002985
vararg
1003986
@@ -1068,6 +1051,25 @@ vararg_with_only_defaults_impl(PyObject *module, PyObject *args, PyObject *b)
10681051
}
10691052

10701053

1054+
/*[clinic input]
1055+
vararg_kwonly_req_opt
1056+
1057+
*args: object
1058+
a: object
1059+
b: object = None
1060+
c: object = None
1061+
1062+
[clinic start generated code]*/
1063+
1064+
static PyObject *
1065+
vararg_kwonly_req_opt_impl(PyObject *module, PyObject *args, PyObject *a,
1066+
PyObject *b, PyObject *c)
1067+
/*[clinic end generated code: output=54694a99c3da370a input=b0d8bf09e540d400]*/
1068+
{
1069+
return pack_arguments_newref(4, args, a, b, c);
1070+
}
1071+
1072+
10711073

10721074
/*[clinic input]
10731075
gh_32092_oob
@@ -1115,15 +1117,14 @@ gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args,
11151117
gh_99233_refcount
11161118
11171119
*args: object
1118-
/
11191120
11201121
Proof-of-concept of GH-99233 refcount error bug.
11211122
11221123
[clinic start generated code]*/
11231124

11241125
static PyObject *
11251126
gh_99233_refcount_impl(PyObject *module, PyObject *args)
1126-
/*[clinic end generated code: output=585855abfbca9a7f input=85f5fb47ac91a626]*/
1127+
/*[clinic end generated code: output=585855abfbca9a7f input=eecfdc2092d90dc3]*/
11271128
{
11281129
Py_RETURN_NONE;
11291130
}
@@ -1923,11 +1924,11 @@ static PyMethodDef tester_methods[] = {
19231924
POSONLY_OPT_KEYWORDS_OPT_KWONLY_OPT_METHODDEF
19241925
KEYWORD_ONLY_PARAMETER_METHODDEF
19251926
POSONLY_VARARG_METHODDEF
1926-
VARARG_AND_POSONLY_METHODDEF
19271927
VARARG_METHODDEF
19281928
VARARG_WITH_DEFAULT_METHODDEF
19291929
VARARG_WITH_DEFAULT2_METHODDEF
19301930
VARARG_WITH_ONLY_DEFAULTS_METHODDEF
1931+
VARARG_KWONLY_REQ_OPT_METHODDEF
19311932
GH_32092_OOB_METHODDEF
19321933
GH_32092_KW_PASS_METHODDEF
19331934
GH_99233_REFCOUNT_METHODDEF

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.