summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2024-08-09 09:22:41 (GMT)
committerGitHub <noreply@github.com>2024-08-09 09:22:41 (GMT)
commit8393608dd9f157ae25ee44777541e62fa80a6d82 (patch)
tree4f1b67a9aedd4af5fc4b090740bf21cf7eeebcbe /Lib/test
parentb6e745a27e9c98127acee436e4855066c58b7a3b (diff)
downloadcpython-8393608dd9f157ae25ee44777541e62fa80a6d82.zip
cpython-8393608dd9f157ae25ee44777541e62fa80a6d82.tar.gz
cpython-8393608dd9f157ae25ee44777541e62fa80a6d82.tar.bz2
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.
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/clinic.test.c12
-rw-r--r--Lib/test/test_clinic.py96
2 files changed, 91 insertions, 17 deletions
diff --git a/Lib/test/clinic.test.c b/Lib/test/clinic.test.c
index 76214e6..2a071f8 100644
--- a/Lib/test/clinic.test.c
+++ b/Lib/test/clinic.test.c
@@ -4134,8 +4134,8 @@ test_vararg_and_posonly
a: object
- *args: object
/
+ *args: object
[clinic start generated code]*/
@@ -4177,7 +4177,7 @@ exit:
static PyObject *
test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
-/*[clinic end generated code: output=79b75dc07decc8d6 input=08dc2bf7afbf1613]*/
+/*[clinic end generated code: output=79b75dc07decc8d6 input=9cfa748bbff09877]*/
/*[clinic input]
test_vararg
@@ -4920,7 +4920,7 @@ Test_an_metho_arg_named_arg_impl(TestObj *self, int arg)
/*[clinic input]
Test.__init__
*args: object
- /
+
Varargs init method. For example, nargs is translated to PyTuple_GET_SIZE.
[clinic start generated code]*/
@@ -4958,14 +4958,14 @@ exit:
static int
Test___init___impl(TestObj *self, PyObject *args)
-/*[clinic end generated code: output=0ed1009fe0dcf98d input=96c3ddc0cd38fc0c]*/
+/*[clinic end generated code: output=0ed1009fe0dcf98d input=2a8bd0033c9ac772]*/
/*[clinic input]
@classmethod
Test.__new__
*args: object
- /
+
Varargs new method. For example, nargs is translated to PyTuple_GET_SIZE.
[clinic start generated code]*/
@@ -5002,7 +5002,7 @@ exit:
static PyObject *
Test_impl(PyTypeObject *type, PyObject *args)
-/*[clinic end generated code: output=8b219f6633e2a2e9 input=26a672e2e9750120]*/
+/*[clinic end generated code: output=8b219f6633e2a2e9 input=70ad829df3dd9b84]*/
/*[clinic input]
diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py
index 8d511ab..a7ba7f3 100644
--- a/Lib/test/test_clinic.py
+++ b/Lib/test/test_clinic.py
@@ -322,7 +322,7 @@ class ClinicWholeFileTest(TestCase):
"""
self.expect_failure(block, err, lineno=8)
- def test_multiple_star_in_args(self):
+ def test_star_after_vararg(self):
err = "'my_test_func' uses '*' more than once."
block = """
/*[clinic input]
@@ -336,6 +336,20 @@ class ClinicWholeFileTest(TestCase):
"""
self.expect_failure(block, err, lineno=6)
+ def test_vararg_after_star(self):
+ err = "'my_test_func' uses '*' more than once."
+ block = """
+ /*[clinic input]
+ my_test_func
+
+ pos_arg: object
+ *
+ *args: object
+ kw_arg: object
+ [clinic start generated code]*/
+ """
+ self.expect_failure(block, err, lineno=6)
+
def test_module_already_got_one(self):
err = "Already defined module 'm'!"
block = """
@@ -1787,13 +1801,43 @@ class ClinicParserTest(TestCase):
)
self.expect_failure(block, err, lineno=4)
+ def test_parameters_required_after_depr_star3(self):
+ block = """
+ module foo
+ foo.bar
+ a: int
+ * [from 3.14]
+ *args: object
+ b: int
+ Docstring.
+ """
+ err = (
+ "Function 'bar' specifies '* [from ...]' without "
+ "following parameters."
+ )
+ self.expect_failure(block, err, lineno=4)
+
def test_depr_star_must_come_before_star(self):
block = """
module foo
foo.bar
- this: int
+ a: int
*
* [from 3.14]
+ b: int
+ Docstring.
+ """
+ err = "Function 'bar': '* [from ...]' must precede '*'"
+ self.expect_failure(block, err, lineno=4)
+
+ def test_depr_star_must_come_before_vararg(self):
+ block = """
+ module foo
+ foo.bar
+ a: int
+ *args: object
+ * [from 3.14]
+ b: int
Docstring.
"""
err = "Function 'bar': '* [from ...]' must precede '*'"
@@ -1908,7 +1952,7 @@ class ClinicParserTest(TestCase):
err = "Function 'bar' uses '/' more than once."
self.expect_failure(block, err)
- def test_mix_star_and_slash(self):
+ def test_slash_after_star(self):
block = """
module foo
foo.bar
@@ -1921,6 +1965,19 @@ class ClinicParserTest(TestCase):
err = "Function 'bar': '/' must precede '*'"
self.expect_failure(block, err)
+ def test_slash_after_vararg(self):
+ block = """
+ module foo
+ foo.bar
+ x: int
+ y: int
+ *args: object
+ z: int
+ /
+ """
+ err = "Function 'bar': '/' must precede '*'"
+ self.expect_failure(block, err)
+
def test_depr_star_must_come_after_slash(self):
block = """
module foo
@@ -1960,6 +2017,19 @@ class ClinicParserTest(TestCase):
err = "Function 'bar': '/ [from ...]' must precede '*'"
self.expect_failure(block, err, lineno=4)
+ def test_vararg_must_come_after_depr_slash(self):
+ block = """
+ module foo
+ foo.bar
+ a: int
+ *args: object
+ / [from 3.14]
+ b: int
+ Docstring.
+ """
+ err = "Function 'bar': '/ [from ...]' must precede '*'"
+ self.expect_failure(block, err, lineno=4)
+
def test_depr_slash_must_come_after_slash(self):
block = """
module foo
@@ -1987,7 +2057,7 @@ class ClinicParserTest(TestCase):
self.expect_failure(block, err)
def test_parameters_no_more_than_one_vararg(self):
- err = "Too many var args"
+ err = "Function 'bar' uses '*' more than once."
block = """
module foo
foo.bar
@@ -3319,13 +3389,6 @@ class ClinicFunctionalTest(unittest.TestCase):
with self.assertRaises(TypeError):
ac_tester.posonly_vararg(1, 2, 3, b=4)
- def test_vararg_and_posonly(self):
- with self.assertRaises(TypeError):
- ac_tester.vararg_and_posonly()
- with self.assertRaises(TypeError):
- ac_tester.vararg_and_posonly(1, b=2)
- self.assertEqual(ac_tester.vararg_and_posonly(1, 2, 3, 4), (1, (2, 3, 4)))
-
def test_vararg(self):
with self.assertRaises(TypeError):
ac_tester.vararg()
@@ -3363,6 +3426,17 @@ class ClinicFunctionalTest(unittest.TestCase):
self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4), ((1, 2, 3, 4), None))
self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4, b=5), ((1, 2, 3, 4), 5))
+ def test_vararg_kwonly_req_opt(self):
+ fn = ac_tester.vararg_kwonly_req_opt
+ self.assertRaises(TypeError, fn)
+ self.assertEqual(fn(a=1), ((), 1, None, None))
+ self.assertEqual(fn(a=1, b=2), ((), 1, 2, None))
+ self.assertEqual(fn(a=1, b=2, c=3), ((), 1, 2, 3))
+ self.assertRaises(TypeError, fn, 1)
+ self.assertEqual(fn(1, a=2), ((1,), 2, None, None))
+ self.assertEqual(fn(1, a=2, b=3), ((1,), 2, 3, None))
+ self.assertEqual(fn(1, a=2, b=3, c=4), ((1,), 2, 3, 4))
+
def test_gh_32092_oob(self):
ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6)