From a009d38689c476c5b584436ccf31ed48745f16cc Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sun, 15 Oct 2023 22:38:45 +0300 Subject: [PATCH] gh-110907: AC: Disallow using `*` with vararg --- Lib/test/test_clinic.py | 14 ++++++++++++++ Objects/clinic/typevarobject.c.h | 4 ++-- Objects/typevarobject.c | 3 +-- Tools/clinic/clinic.py | 9 +++++++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 627a329bb738a2..4a8d5221b0f8df 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -359,6 +359,20 @@ def __init__(self): """ self.expect_failure(block, err, lineno=8) + def test_multiple_star_in_args(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 = """ diff --git a/Objects/clinic/typevarobject.c.h b/Objects/clinic/typevarobject.c.h index 4762cd63545b60..22090b15481431 100644 --- a/Objects/clinic/typevarobject.c.h +++ b/Objects/clinic/typevarobject.c.h @@ -8,7 +8,7 @@ preserve #endif PyDoc_STRVAR(typevar_new__doc__, -"typevar(name, *constraints, *, bound=None, covariant=False,\n" +"typevar(name, *constraints, bound=None, covariant=False,\n" " contravariant=False, infer_variance=False)\n" "--\n" "\n" @@ -590,4 +590,4 @@ typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=db0b327ebbb1488f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=027fb8cbef6e5015 input=a9049054013a1b77]*/ diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index 8a20b23c6866d7..51424ffb24e2bf 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -327,7 +327,6 @@ typevar.__new__ as typevar_new name: object(subclass_of="&PyUnicode_Type") *constraints: object - * bound: object = None covariant: bool = False contravariant: bool = False @@ -340,7 +339,7 @@ static PyObject * typevar_new_impl(PyTypeObject *type, PyObject *name, PyObject *constraints, PyObject *bound, int covariant, int contravariant, int infer_variance) -/*[clinic end generated code: output=1d200450ee99226d input=2c07ab87c94f462b]*/ +/*[clinic end generated code: output=1d200450ee99226d input=41ae33a916bfe76f]*/ { if (covariant && contravariant) { PyErr_SetString(PyExc_ValueError, diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 1bcc85537bf2da..a54986506066f4 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -5944,6 +5944,7 @@ def parse_star(self, function: Function, version: VersionTuple | None) -> None: if version is None: if self.keyword_only: fail(f"Function {function.name!r} uses '*' more than once.") + self.check_previous_star() self.check_remaining_star() self.keyword_only = True else: @@ -6353,6 +6354,14 @@ def check_remaining_star(self, lineno: int | None = None) -> None: fail(f"Function {self.function.name!r} specifies {symbol!r} " f"without following parameters.", line_number=lineno) + def check_previous_star(self, lineno: int | None = None) -> None: + assert isinstance(self.function, Function) + + for p in self.function.parameters.values(): + if p.kind == inspect.Parameter.VAR_POSITIONAL: + fail(f"Function {self.function.name!r} uses '*' more than once.") + + def do_post_block_processing_cleanup(self, lineno: int) -> None: """ Called when processing the block is done.