summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/internal/pycore_modsupport.h23
-rw-r--r--Include/internal/pycore_tuple.h2
-rw-r--r--Lib/test/clinic.test.c206
-rw-r--r--Lib/test/test_clinic.py105
-rw-r--r--Modules/_testclinic.c332
-rw-r--r--Modules/clinic/_testclinic.c.h776
-rw-r--r--Modules/clinic/_testclinic_depr.c.h3
-rw-r--r--Modules/clinic/gcmodule.c.h33
-rw-r--r--Modules/clinic/mathmodule.c.h50
-rw-r--r--Modules/gcmodule.c39
-rw-r--r--Modules/mathmodule.c43
-rw-r--r--Objects/clinic/setobject.c.h103
-rw-r--r--Objects/clinic/typevarobject.c.h31
-rw-r--r--Objects/setobject.c74
-rw-r--r--Python/clinic/bltinmodule.c.h31
-rw-r--r--Python/getargs.c168
-rw-r--r--Tools/c-analyzer/c_parser/parser/__init__.py2
-rw-r--r--Tools/clinic/libclinic/clanguage.py16
-rw-r--r--Tools/clinic/libclinic/converter.py2
-rw-r--r--Tools/clinic/libclinic/converters.py27
-rw-r--r--Tools/clinic/libclinic/dsl_parser.py9
-rw-r--r--Tools/clinic/libclinic/parse_args.py184
22 files changed, 1597 insertions, 662 deletions
diff --git a/Include/internal/pycore_modsupport.h b/Include/internal/pycore_modsupport.h
index 11fde81..250106a 100644
--- a/Include/internal/pycore_modsupport.h
+++ b/Include/internal/pycore_modsupport.h
@@ -76,7 +76,7 @@ PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords(
...);
// Export for 'math' shared extension
-PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywords(
+PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywordsEx(
PyObject *const *args,
Py_ssize_t nargs,
PyObject *kwargs,
@@ -85,20 +85,19 @@ PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywords(
int minpos,
int maxpos,
int minkw,
+ int varpos,
PyObject **buf);
#define _PyArg_UnpackKeywords(args, nargs, kwargs, kwnames, parser, minpos, maxpos, minkw, buf) \
(((minkw) == 0 && (kwargs) == NULL && (kwnames) == NULL && \
- (minpos) <= (nargs) && (nargs) <= (maxpos) && (args) != NULL) ? (args) : \
- _PyArg_UnpackKeywords((args), (nargs), (kwargs), (kwnames), (parser), \
- (minpos), (maxpos), (minkw), (buf)))
-
-// Export for '_testclinic' shared extension
-PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywordsWithVararg(
- PyObject *const *args, Py_ssize_t nargs,
- PyObject *kwargs, PyObject *kwnames,
- struct _PyArg_Parser *parser,
- int minpos, int maxpos, int minkw,
- int vararg, PyObject **buf);
+ (minpos) <= (nargs) && (nargs) <= (maxpos) && (args) != NULL) ? \
+ (args) : \
+ _PyArg_UnpackKeywordsEx((args), (nargs), (kwargs), (kwnames), (parser), \
+ (minpos), (maxpos), (minkw), 0, (buf)))
+#define _PyArg_UnpackKeywordsWithVararg(args, nargs, kwargs, kwnames, parser, minpos, maxpos, minkw, buf) \
+ (((minkw) == 0 && (kwargs) == NULL && (kwnames) == NULL && \
+ (minpos) <= (nargs) && (args) != NULL) ? (args) : \
+ _PyArg_UnpackKeywordsEx((args), (nargs), (kwargs), (kwnames), (parser), \
+ (minpos), (maxpos), (minkw), 1, (buf)))
#ifdef __cplusplus
}
diff --git a/Include/internal/pycore_tuple.h b/Include/internal/pycore_tuple.h
index dfbbd6f..82b8752 100644
--- a/Include/internal/pycore_tuple.h
+++ b/Include/internal/pycore_tuple.h
@@ -20,7 +20,7 @@ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
#define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)
-extern PyObject *_PyTuple_FromArray(PyObject *const *, Py_ssize_t);
+PyAPI_FUNC(PyObject *)_PyTuple_FromArray(PyObject *const *, Py_ssize_t);
PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefSteal(const union _PyStackRef *, Py_ssize_t);
PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);
diff --git a/Lib/test/clinic.test.c b/Lib/test/clinic.test.c
index e22324e..8020886 100644
--- a/Lib/test/clinic.test.c
+++ b/Lib/test/clinic.test.c
@@ -4148,6 +4148,45 @@ PyDoc_STRVAR(test_vararg_and_posonly__doc__,
{"test_vararg_and_posonly", _PyCFunction_CAST(test_vararg_and_posonly), METH_FASTCALL, test_vararg_and_posonly__doc__},
static PyObject *
+test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args);
+
+static PyObject *
+test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *a;
+ PyObject *__clinic_args = NULL;
+
+ if (!_PyArg_CheckPositional("test_vararg_and_posonly", nargs, 1, PY_SSIZE_T_MAX)) {
+ goto exit;
+ }
+ a = args[0];
+ __clinic_args = _PyTuple_FromArray(args + 1, nargs - 1);
+ if (__clinic_args == NULL) {
+ goto exit;
+ }
+ return_value = test_vararg_and_posonly_impl(module, a, __clinic_args);
+
+exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
+ return return_value;
+}
+
+static PyObject *
+test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
+/*[clinic end generated code: output=0c11c475e240869e input=9cfa748bbff09877]*/
+
+PyDoc_STRVAR(test_vararg_and_posonly__doc__,
+"test_vararg_and_posonly($module, a, /, *args)\n"
+"--\n"
+"\n");
+
+#define TEST_VARARG_AND_POSONLY_METHODDEF \
+ {"test_vararg_and_posonly", _PyCFunction_CAST(test_vararg_and_posonly), METH_FASTCALL, test_vararg_and_posonly__doc__},
+
+static PyObject *
test_vararg_and_posonly_impl(PyObject *module, PyObject *a, Py_ssize_t nargs,
PyObject *const *args);
@@ -4163,17 +4202,19 @@ test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t narg
goto exit;
}
a = args[0];
- __clinic_args = args + 1;
+ __clinic_args = _PyTuple_FromArray(args + 1, nargs - 1);
+ if (__clinic_args == NULL) {
+ goto exit;
+ }
return_value = test_vararg_and_posonly_impl(module, a, nvararg, __clinic_args);
exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
return return_value;
}
-static PyObject *
-test_vararg_and_posonly_impl(PyObject *module, PyObject *a, Py_ssize_t nargs,
- PyObject *const *args)
-/*[clinic end generated code: output=dc2dd9483cc0459e input=9cfa748bbff09877]*/
/*[clinic input]
test_vararg
@@ -4224,26 +4265,34 @@ test_vararg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[1];
+ PyObject * const *fastargs;
PyObject *a;
PyObject *__clinic_args = NULL;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!fastargs) {
+ goto exit;
+ }
+ a = fastargs[0];
+ __clinic_args = nargs > 1
+ ? _PyTuple_FromArray(args + 1, nargs - 1)
+ : PyTuple_New(0);
+ if (__clinic_args == NULL) {
goto exit;
}
- a = args[0];
- __clinic_args = args[1];
return_value = test_vararg_impl(module, a, __clinic_args);
exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
return return_value;
}
static PyObject *
test_vararg_impl(PyObject *module, PyObject *a, PyObject *args)
-/*[clinic end generated code: output=1411e464f358a7ba input=81d33815ad1bae6e]*/
+/*[clinic end generated code: output=e7d7da6a7e008125 input=81d33815ad1bae6e]*/
/*[clinic input]
test_vararg_with_default
@@ -4296,37 +4345,45 @@ test_vararg_with_default(PyObject *module, PyObject *const *args, Py_ssize_t nar
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[3];
+ PyObject *argsbuf[2];
+ PyObject * const *fastargs;
Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *a;
PyObject *__clinic_args = NULL;
int b = 0;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!fastargs) {
goto exit;
}
- a = args[0];
- __clinic_args = args[1];
+ a = fastargs[0];
if (!noptargs) {
goto skip_optional_kwonly;
}
- b = PyObject_IsTrue(args[2]);
+ b = PyObject_IsTrue(fastargs[1]);
if (b < 0) {
goto exit;
}
skip_optional_kwonly:
+ __clinic_args = nargs > 1
+ ? _PyTuple_FromArray(args + 1, nargs - 1)
+ : PyTuple_New(0);
+ if (__clinic_args == NULL) {
+ goto exit;
+ }
return_value = test_vararg_with_default_impl(module, a, __clinic_args, b);
exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
return return_value;
}
static PyObject *
test_vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args,
int b)
-/*[clinic end generated code: output=f09d4b917063ca41 input=6e110b54acd9b22d]*/
+/*[clinic end generated code: output=46781f9920ecedcf input=6e110b54acd9b22d]*/
/*[clinic input]
test_vararg_with_only_defaults
@@ -4379,22 +4436,22 @@ test_vararg_with_only_defaults(PyObject *module, PyObject *const *args, Py_ssize
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[3];
+ PyObject *argsbuf[2];
+ PyObject * const *fastargs;
Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
PyObject *__clinic_args = NULL;
int b = 0;
PyObject *c = " ";
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf);
+ if (!fastargs) {
goto exit;
}
- __clinic_args = args[0];
if (!noptargs) {
goto skip_optional_kwonly;
}
- if (args[1]) {
- b = PyObject_IsTrue(args[1]);
+ if (fastargs[0]) {
+ b = PyObject_IsTrue(fastargs[0]);
if (b < 0) {
goto exit;
}
@@ -4402,19 +4459,25 @@ test_vararg_with_only_defaults(PyObject *module, PyObject *const *args, Py_ssize
goto skip_optional_kwonly;
}
}
- c = args[2];
+ c = fastargs[1];
skip_optional_kwonly:
+ __clinic_args = _PyTuple_FromArray(args, nargs);
+ if (__clinic_args == NULL) {
+ goto exit;
+ }
return_value = test_vararg_with_only_defaults_impl(module, __clinic_args, b, c);
exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
return return_value;
}
static PyObject *
test_vararg_with_only_defaults_impl(PyObject *module, PyObject *args, int b,
PyObject *c)
-/*[clinic end generated code: output=cc6590b8805d5433 input=fa56a709a035666e]*/
+/*[clinic end generated code: output=d03daf5067039c03 input=fa56a709a035666e]*/
/*[clinic input]
test_paramname_module
@@ -4927,33 +4990,65 @@ PyDoc_STRVAR(Test___init____doc__,
"Varargs init method. For example, nargs is translated to PyTuple_GET_SIZE.");
static int
-Test___init___impl(TestObj *self, Py_ssize_t nargs, PyObject *const *args);
+Test___init___impl(TestObj *self, PyObject *args);
static int
Test___init__(PyObject *self, PyObject *args, PyObject *kwargs)
{
int return_value = -1;
PyTypeObject *base_tp = TestType;
- PyObject *const *__clinic_args = NULL;
+ PyObject *__clinic_args = NULL;
if ((Py_IS_TYPE(self, base_tp) ||
Py_TYPE(self)->tp_new == base_tp->tp_new) &&
!_PyArg_NoKeywords("Test", kwargs)) {
goto exit;
}
- if (!_PyArg_CheckPositional("Test", PyTuple_GET_SIZE(args), 0, PY_SSIZE_T_MAX)) {
+ __clinic_args = Py_NewRef(args);
+ return_value = Test___init___impl((TestObj *)self, __clinic_args);
+
+exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
+ return return_value;
+}
+
+static int
+Test___init___impl(TestObj *self, PyObject *args)
+/*[clinic end generated code: output=f172425cec373cd6 input=2a8bd0033c9ac772]*/
+
+PyDoc_STRVAR(Test___init____doc__,
+"Test(*args)\n"
+"--\n"
+"\n"
+"Varargs init method. For example, nargs is translated to PyTuple_GET_SIZE.");
+
+static int
+Test___init___impl(TestObj *self, Py_ssize_t nargs, PyObject *const *args);
+
+static int
+Test___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ int return_value = -1;
+ PyTypeObject *base_tp = TestType;
+ PyObject *const *__clinic_args = NULL;
+
+ if ((Py_IS_TYPE(self, base_tp) ||
+ Py_TYPE(self)->tp_new == base_tp->tp_new) &&
+ !_PyArg_NoKeywords("Test", kwargs)) {
goto exit;
}
- __clinic_args = _PyTuple_CAST(args)->ob_item;
+ __clinic_args = Py_NewRef(args);
return_value = Test___init___impl((TestObj *)self, nvararg, __clinic_args);
exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
return return_value;
}
-static int
-Test___init___impl(TestObj *self, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=6a64b417c9080a73 input=2a8bd0033c9ac772]*/
/*[clinic input]
@@ -4971,32 +5066,63 @@ PyDoc_STRVAR(Test__doc__,
"Varargs new method. For example, nargs is translated to PyTuple_GET_SIZE.");
static PyObject *
-Test_impl(PyTypeObject *type, Py_ssize_t nargs, PyObject *const *args);
+Test_impl(PyTypeObject *type, PyObject *args);
static PyObject *
Test(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
PyTypeObject *base_tp = TestType;
- PyObject *const *__clinic_args = NULL;
+ PyObject *__clinic_args = NULL;
if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
!_PyArg_NoKeywords("Test", kwargs)) {
goto exit;
}
- if (!_PyArg_CheckPositional("Test", PyTuple_GET_SIZE(args), 0, PY_SSIZE_T_MAX)) {
+ __clinic_args = Py_NewRef(args);
+ return_value = Test_impl(type, __clinic_args);
+
+exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
+ return return_value;
+}
+
+static PyObject *
+Test_impl(PyTypeObject *type, PyObject *args)
+/*[clinic end generated code: output=ee1e8892a67abd4a input=70ad829df3dd9b84]*/
+
+PyDoc_STRVAR(Test__doc__,
+"Test(*args)\n"
+"--\n"
+"\n"
+"Varargs new method. For example, nargs is translated to PyTuple_GET_SIZE.");
+
+static PyObject *
+Test_impl(PyTypeObject *type, Py_ssize_t nargs, PyObject *const *args);
+
+static PyObject *
+Test(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ PyTypeObject *base_tp = TestType;
+ PyObject *const *__clinic_args = NULL;
+
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+ !_PyArg_NoKeywords("Test", kwargs)) {
goto exit;
}
- __clinic_args = _PyTuple_CAST(args)->ob_item;
+ __clinic_args = Py_NewRef(args);
return_value = Test_impl(type, nvararg, __clinic_args);
exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
return return_value;
}
-static PyObject *
-Test_impl(PyTypeObject *type, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=bf22f942407383a5 input=70ad829df3dd9b84]*/
/*[clinic input]
diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py
index d492ea1..a4317a3 100644
--- a/Lib/test/test_clinic.py
+++ b/Lib/test/test_clinic.py
@@ -33,6 +33,15 @@ with test_tools.imports_under_tool('clinic'):
from libclinic.cli import parse_file, Clinic
+def repeat_fn(*functions):
+ def wrapper(test):
+ def wrapped(self):
+ for fn in functions:
+ with self.subTest(fn=fn):
+ test(self, fn)
+ return wrapped
+ return wrapper
+
def _make_clinic(*, filename='clinic_tests', limited_capi=False):
clang = CLanguage(filename)
c = Clinic(clang, filename=filename, limited_capi=limited_capi)
@@ -3378,30 +3387,53 @@ class ClinicFunctionalTest(unittest.TestCase):
ac_tester.keyword_only_parameter(1)
self.assertEqual(ac_tester.keyword_only_parameter(a=1), (1,))
- def test_varpos(self):
- # fn(*args)
- fn = ac_tester.varpos
- self.assertEqual(fn(), ((),))
- self.assertEqual(fn(1, 2), ((1, 2),))
-
- def test_posonly_varpos(self):
- # fn(a, b, /, *args)
- fn = ac_tester.posonly_varpos
- self.assertRaises(TypeError, fn)
- self.assertRaises(TypeError, fn, 1)
- self.assertRaises(TypeError, fn, 1, b=2)
- self.assertEqual(fn(1, 2), (1, 2, ()))
- self.assertEqual(fn(1, 2, 3, 4), (1, 2, (3, 4)))
-
- def test_posonly_poskw_varpos(self):
- # fn(a, /, b, *args)
- fn = ac_tester.posonly_poskw_varpos
- self.assertRaises(TypeError, fn)
- self.assertEqual(fn(1, 2), (1, 2, ()))
- self.assertEqual(fn(1, b=2), (1, 2, ()))
- self.assertEqual(fn(1, 2, 3, 4), (1, 2, (3, 4)))
- self.assertRaises(TypeError, fn, b=4)
- self.assertRaises(TypeError, fn, 1, 2, 3, b=4)
+ if ac_tester is not None:
+ @repeat_fn(ac_tester.varpos,
+ ac_tester.varpos_array,
+ ac_tester.TestClass.varpos_no_fastcall,
+ ac_tester.TestClass.varpos_array_no_fastcall)
+ def test_varpos(self, fn):
+ # fn(*args)
+ self.assertEqual(fn(), ())
+ self.assertEqual(fn(1, 2), (1, 2))
+
+ @repeat_fn(ac_tester.posonly_varpos,
+ ac_tester.posonly_varpos_array,
+ ac_tester.TestClass.posonly_varpos_no_fastcall,
+ ac_tester.TestClass.posonly_varpos_array_no_fastcall)
+ def test_posonly_varpos(self, fn):
+ # fn(a, b, /, *args)
+ self.assertRaises(TypeError, fn)
+ self.assertRaises(TypeError, fn, 1)
+ self.assertRaises(TypeError, fn, 1, b=2)
+ self.assertEqual(fn(1, 2), (1, 2, ()))
+ self.assertEqual(fn(1, 2, 3, 4), (1, 2, (3, 4)))
+
+ @repeat_fn(ac_tester.posonly_req_opt_varpos,
+ ac_tester.posonly_req_opt_varpos_array,
+ ac_tester.TestClass.posonly_req_opt_varpos_no_fastcall,
+ ac_tester.TestClass.posonly_req_opt_varpos_array_no_fastcall)
+ def test_posonly_req_opt_varpos(self, fn):
+ # fn(a, b=False, /, *args)
+ self.assertRaises(TypeError, fn)
+ self.assertRaises(TypeError, fn, a=1)
+ self.assertEqual(fn(1), (1, False, ()))
+ self.assertEqual(fn(1, 2), (1, 2, ()))
+ self.assertEqual(fn(1, 2, 3, 4), (1, 2, (3, 4)))
+
+ @repeat_fn(ac_tester.posonly_poskw_varpos,
+ ac_tester.posonly_poskw_varpos_array,
+ ac_tester.TestClass.posonly_poskw_varpos_no_fastcall,
+ ac_tester.TestClass.posonly_poskw_varpos_array_no_fastcall)
+ def test_posonly_poskw_varpos(self, fn):
+ # fn(a, /, b, *args)
+ self.assertRaises(TypeError, fn)
+ self.assertEqual(fn(1, 2), (1, 2, ()))
+ self.assertEqual(fn(1, b=2), (1, 2, ()))
+ self.assertEqual(fn(1, 2, 3, 4), (1, 2, (3, 4)))
+ self.assertRaises(TypeError, fn, b=4)
+ errmsg = re.escape("given by name ('b') and position (2)")
+ self.assertRaisesRegex(TypeError, errmsg, fn, 1, 2, 3, b=4)
def test_poskw_varpos(self):
# fn(a, *args)
@@ -3409,7 +3441,8 @@ class ClinicFunctionalTest(unittest.TestCase):
self.assertRaises(TypeError, fn)
self.assertRaises(TypeError, fn, 1, b=2)
self.assertEqual(fn(a=1), (1, ()))
- self.assertRaises(TypeError, fn, 1, a=2)
+ errmsg = re.escape("given by name ('a') and position (1)")
+ self.assertRaisesRegex(TypeError, errmsg, fn, 1, a=2)
self.assertEqual(fn(1), (1, ()))
self.assertEqual(fn(1, 2, 3, 4), (1, (2, 3, 4)))
@@ -3417,7 +3450,8 @@ class ClinicFunctionalTest(unittest.TestCase):
# fn(a, *args, b=False)
fn = ac_tester.poskw_varpos_kwonly_opt
self.assertRaises(TypeError, fn)
- self.assertRaises(TypeError, fn, 1, a=2)
+ errmsg = re.escape("given by name ('a') and position (1)")
+ self.assertRaisesRegex(TypeError, errmsg, fn, 1, a=2)
self.assertEqual(fn(1, b=2), (1, (), True))
self.assertEqual(fn(1, 2, 3, 4), (1, (2, 3, 4), False))
self.assertEqual(fn(1, 2, 3, 4, b=5), (1, (2, 3, 4), True))
@@ -3428,7 +3462,8 @@ class ClinicFunctionalTest(unittest.TestCase):
# fn(a, *args, b=False, c=False)
fn = ac_tester.poskw_varpos_kwonly_opt2
self.assertRaises(TypeError, fn)
- self.assertRaises(TypeError, fn, 1, a=2)
+ errmsg = re.escape("given by name ('a') and position (1)")
+ self.assertRaisesRegex(TypeError, errmsg, fn, 1, a=2)
self.assertEqual(fn(1, b=2), (1, (), 2, False))
self.assertEqual(fn(1, b=2, c=3), (1, (), 2, 3))
self.assertEqual(fn(1, 2, 3), (1, (2, 3), False, False))
@@ -3490,9 +3525,10 @@ class ClinicFunctionalTest(unittest.TestCase):
self.assertEqual(fn(covariant=True, name='a'), ('a', (), True))
self.assertRaises(TypeError, fn, covariant=True)
- self.assertRaises(TypeError, fn, 1, name='a')
- self.assertRaises(TypeError, fn, 1, 2, 3, name='a', covariant=True)
- self.assertRaises(TypeError, fn, 1, 2, 3, covariant=True, name='a')
+ errmsg = re.escape("given by name ('name') and position (1)")
+ self.assertRaisesRegex(TypeError, errmsg, fn, 1, name='a')
+ self.assertRaisesRegex(TypeError, errmsg, fn, 1, 2, 3, name='a', covariant=True)
+ self.assertRaisesRegex(TypeError, errmsg, fn, 1, 2, 3, covariant=True, name='a')
def test_cloned_func_exception_message(self):
incorrect_arg = -1 # f1() and f2() accept a single str
@@ -3568,14 +3604,15 @@ class ClinicFunctionalTest(unittest.TestCase):
cls = ac_tester.TestClass
obj = cls()
fn = obj.defclass_posonly_varpos
- self.assertRaises(TypeError, fn)
- self.assertRaises(TypeError, fn, 1)
+ errmsg = 'takes at least 2 positional arguments'
+ self.assertRaisesRegex(TypeError, errmsg, fn)
+ self.assertRaisesRegex(TypeError, errmsg, fn, 1)
self.assertEqual(fn(1, 2), (cls, 1, 2, ()))
self.assertEqual(fn(1, 2, 3, 4), (cls, 1, 2, (3, 4)))
fn = cls.defclass_posonly_varpos
self.assertRaises(TypeError, fn)
- self.assertRaises(TypeError, fn, obj)
- self.assertRaises(TypeError, fn, obj, 1)
+ self.assertRaisesRegex(TypeError, errmsg, fn, obj)
+ self.assertRaisesRegex(TypeError, errmsg, fn, obj, 1)
self.assertEqual(fn(obj, 1, 2), (cls, 1, 2, ()))
self.assertEqual(fn(obj, 1, 2, 3, 4), (cls, 1, 2, (3, 4)))
diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c
index e3c8ba9..320c8dd 100644
--- a/Modules/_testclinic.c
+++ b/Modules/_testclinic.c
@@ -59,19 +59,20 @@ pack_arguments_newref(int argc, ...)
}
static PyObject *
-pack_varargs_to_tuple(Py_ssize_t varargssize, PyObject *const *args)
+pack_arguments_2pos_varpos(PyObject *a, PyObject *b,
+ PyObject * const *args, Py_ssize_t args_length)
+/*[clinic end generated code: output=267032f41bd039cc input=86ee3064b7853e86]*/
{
- assert(!PyErr_Occurred());
- PyObject *tuple = PyTuple_New(varargssize);
- if (!tuple) {
+ PyObject *tuple = _PyTuple_FromArray(args, args_length);
+ if (tuple == NULL) {
return NULL;
}
- for (Py_ssize_t i = 0; i < varargssize; i++) {
- PyTuple_SET_ITEM(tuple, i, Py_NewRef(args[i]));
- }
- return tuple;
+ PyObject *result = pack_arguments_newref(3, a, b, tuple);
+ Py_DECREF(tuple);
+ return result;
}
+
/* Pack arguments to a tuple.
* `wrapper` is function which converts primitive type to PyObject.
* `arg_type` is type that arguments should be converted to before wrapped. */
@@ -984,16 +985,10 @@ varpos
[clinic start generated code]*/
static PyObject *
-varpos_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=b65096f423fb5dcc input=f87cd674145d394c]*/
+varpos_impl(PyObject *module, PyObject *args)
+/*[clinic end generated code: output=7b0b9545872bdca4 input=f87cd674145d394c]*/
{
- PyObject *vararg_tuple = pack_varargs_to_tuple(nargs, args);
- if (!vararg_tuple) {
- return NULL;
- }
- PyObject *result = pack_arguments_newref(1, vararg_tuple);
- Py_DECREF(vararg_tuple);
- return result;
+ return Py_NewRef(args);
}
@@ -1009,16 +1004,29 @@ posonly_varpos
static PyObject *
posonly_varpos_impl(PyObject *module, PyObject *a, PyObject *b,
- Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=d10d43d86d117ab3 input=c9fd7895cfbaabba]*/
+ PyObject *args)
+/*[clinic end generated code: output=5dae5eb2a0d623cd input=c9fd7895cfbaabba]*/
{
- PyObject *vararg_tuple = pack_varargs_to_tuple(nargs, args);
- if (!vararg_tuple) {
- return NULL;
- }
- PyObject *result = pack_arguments_newref(3, a, b, vararg_tuple);
- Py_DECREF(vararg_tuple);
- return result;
+ return pack_arguments_newref(3, a, b, args);
+}
+
+
+/*[clinic input]
+posonly_req_opt_varpos
+
+ a: object
+ b: object = False
+ /
+ *args: object
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_req_opt_varpos_impl(PyObject *module, PyObject *a, PyObject *b,
+ PyObject *args)
+/*[clinic end generated code: output=67f82f90838e166a input=a49bd64740171e1c]*/
+{
+ return pack_arguments_newref(3, a, b, args);
}
@@ -1130,6 +1138,81 @@ varpos_kwonly_req_opt_impl(PyObject *module, PyObject *args, PyObject *a,
}
+/*[clinic input]
+varpos_array
+
+ *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+varpos_array_impl(PyObject *module, PyObject * const *args,
+ Py_ssize_t args_length)
+/*[clinic end generated code: output=a25f42f39c9b13ad input=97b8bdcf87e019c7]*/
+{
+ return _PyTuple_FromArray(args, args_length);
+}
+
+
+/*[clinic input]
+posonly_varpos_array
+
+ a: object
+ b: object
+ /
+ *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_varpos_array_impl(PyObject *module, PyObject *a, PyObject *b,
+ PyObject * const *args, Py_ssize_t args_length)
+/*[clinic end generated code: output=267032f41bd039cc input=86ee3064b7853e86]*/
+{
+ return pack_arguments_2pos_varpos(a, b, args, args_length);
+}
+
+
+/*[clinic input]
+posonly_req_opt_varpos_array
+
+ a: object
+ b: object = False
+ /
+ *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_req_opt_varpos_array_impl(PyObject *module, PyObject *a, PyObject *b,
+ PyObject * const *args,
+ Py_ssize_t args_length)
+/*[clinic end generated code: output=f2f93c77ead93699 input=b01d7728164fd93e]*/
+{
+ return pack_arguments_2pos_varpos(a, b, args, args_length);
+}
+
+
+/*[clinic input]
+posonly_poskw_varpos_array
+
+ a: object
+ /
+ b: object
+ *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_poskw_varpos_array_impl(PyObject *module, PyObject *a, PyObject *b,
+ PyObject * const *args,
+ Py_ssize_t args_length)
+/*[clinic end generated code: output=155811a8b2d65a12 input=5fb08cdc6afb9d7c]*/
+{
+ return pack_arguments_2pos_varpos(a, b, args, args_length);
+}
+
+
/*[clinic input]
gh_32092_oob
@@ -1183,9 +1266,8 @@ Proof-of-concept of GH-99233 refcount error bug.
[clinic start generated code]*/
static PyObject *
-gh_99233_refcount_impl(PyObject *module, Py_ssize_t nargs,
- PyObject *const *args)
-/*[clinic end generated code: output=b570007e61e5c670 input=eecfdc2092d90dc3]*/
+gh_99233_refcount_impl(PyObject *module, PyObject *args)
+/*[clinic end generated code: output=585855abfbca9a7f input=eecfdc2092d90dc3]*/
{
Py_RETURN_NONE;
}
@@ -1295,9 +1377,9 @@ clone_with_conv_f2_impl(PyObject *module, custom_t path)
/*[clinic input]
-class _testclinic.TestClass "PyObject *" "PyObject"
+class _testclinic.TestClass "PyObject *" "&PyBaseObject_Type"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=668a591c65bec947]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c991635bb3c91f1a]*/
/*[clinic input]
_testclinic.TestClass.get_defining_class
@@ -1360,11 +1442,192 @@ _testclinic_TestClass_defclass_posonly_varpos_impl(PyObject *self,
return pack_arguments_newref(4, cls, a, b, args);
}
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as varpos_no_fastcall
+
+ *args: object
+
+[clinic start generated code]*/
+
+static PyObject *
+varpos_no_fastcall_impl(PyTypeObject *type, PyObject *args)
+/*[clinic end generated code: output=04e94f2898bb2dde input=b0447ebab3e81001]*/
+{
+ return Py_NewRef(args);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as posonly_varpos_no_fastcall
+
+ a: object
+ b: object
+ /
+ *args: object
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a, PyObject *b,
+ PyObject *args)
+/*[clinic end generated code: output=b0a0425719f69f5a input=d2ec37a06b3c2389]*/
+{
+ return pack_arguments_newref(3, a, b, args);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as posonly_req_opt_varpos_no_fastcall
+
+ a: object
+ b: object = False
+ /
+ *args: object
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_req_opt_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+ PyObject *b, PyObject *args)
+/*[clinic end generated code: output=3c44915b1a554e2d input=e9e74686a5e6a06d]*/
+{
+ return pack_arguments_newref(3, a, b, args);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as posonly_poskw_varpos_no_fastcall
+
+ a: object
+ /
+ b: object
+ *args: object
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_poskw_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+ PyObject *b, PyObject *args)
+/*[clinic end generated code: output=6ad74bed4bdc7f96 input=fa931c38184213aa]*/
+{
+ return pack_arguments_newref(3, a, b, args);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as varpos_array_no_fastcall
+
+ *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject * const *args,
+ Py_ssize_t args_length)
+/*[clinic end generated code: output=f99d984346c60d42 input=368d8eea6de48c12]*/
+{
+ return _PyTuple_FromArray(args, args_length);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as posonly_varpos_array_no_fastcall
+
+ a: object
+ b: object
+ /
+ *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+ PyObject *b, PyObject * const *args,
+ Py_ssize_t args_length)
+/*[clinic end generated code: output=1eec4da1fb5b5978 input=7330c8d819a23548]*/
+{
+ return pack_arguments_2pos_varpos(a, b, args, args_length);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as posonly_req_opt_varpos_array_no_fastcall
+
+ a: object
+ b: object = False
+ /
+ *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_req_opt_varpos_array_no_fastcall_impl(PyTypeObject *type,
+ PyObject *a, PyObject *b,
+ PyObject * const *args,
+ Py_ssize_t args_length)
+/*[clinic end generated code: output=88041c2176135218 input=7f5fd34ee5f9e0bf]*/
+{
+ return pack_arguments_2pos_varpos(a, b, args, args_length);
+}
+
+
+/*[clinic input]
+@classmethod
+_testclinic.TestClass.__new__ as posonly_poskw_varpos_array_no_fastcall
+
+ a: object
+ /
+ b: object
+ *args: array
+
+[clinic start generated code]*/
+
+static PyObject *
+posonly_poskw_varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+ PyObject *b,
+ PyObject * const *args,
+ Py_ssize_t args_length)
+/*[clinic end generated code: output=70eda18c3667681e input=2b0fcd7bd9bb865c]*/
+{
+ return pack_arguments_2pos_varpos(a, b, args, args_length);
+}
+
static struct PyMethodDef test_class_methods[] = {
_TESTCLINIC_TESTCLASS_GET_DEFINING_CLASS_METHODDEF
_TESTCLINIC_TESTCLASS_GET_DEFINING_CLASS_ARG_METHODDEF
_TESTCLINIC_TESTCLASS_DEFCLASS_VARPOS_METHODDEF
_TESTCLINIC_TESTCLASS_DEFCLASS_POSONLY_VARPOS_METHODDEF
+
+ {"varpos_no_fastcall", _PyCFunction_CAST(varpos_no_fastcall),
+ METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+ {"posonly_varpos_no_fastcall", _PyCFunction_CAST(posonly_varpos_no_fastcall),
+ METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+ {"posonly_req_opt_varpos_no_fastcall", _PyCFunction_CAST(posonly_req_opt_varpos_no_fastcall),
+ METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+ {"posonly_poskw_varpos_no_fastcall", _PyCFunction_CAST(posonly_poskw_varpos_no_fastcall),
+ METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+
+ {"varpos_array_no_fastcall",
+ _PyCFunction_CAST(varpos_array_no_fastcall),
+ METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+ {"posonly_varpos_array_no_fastcall",
+ _PyCFunction_CAST(posonly_varpos_array_no_fastcall),
+ METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+ {"posonly_req_opt_varpos_array_no_fastcall",
+ _PyCFunction_CAST(posonly_req_opt_varpos_array_no_fastcall),
+ METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+ {"posonly_poskw_varpos_array_no_fastcall",
+ _PyCFunction_CAST(posonly_poskw_varpos_array_no_fastcall),
+ METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""},
+
{NULL, NULL}
};
@@ -2023,12 +2286,19 @@ static PyMethodDef tester_methods[] = {
VARPOS_METHODDEF
POSONLY_VARPOS_METHODDEF
+ POSONLY_REQ_OPT_VARPOS_METHODDEF
POSONLY_POSKW_VARPOS_METHODDEF
POSKW_VARPOS_METHODDEF
POSKW_VARPOS_KWONLY_OPT_METHODDEF
POSKW_VARPOS_KWONLY_OPT2_METHODDEF
VARPOS_KWONLY_OPT_METHODDEF
VARPOS_KWONLY_REQ_OPT_METHODDEF
+
+ VARPOS_ARRAY_METHODDEF
+ POSONLY_VARPOS_ARRAY_METHODDEF
+ POSONLY_REQ_OPT_VARPOS_ARRAY_METHODDEF
+ POSONLY_POSKW_VARPOS_ARRAY_METHODDEF
+
GH_32092_OOB_METHODDEF
GH_32092_KW_PASS_METHODDEF
GH_99233_REFCOUNT_METHODDEF
diff --git a/Modules/clinic/_testclinic.c.h b/Modules/clinic/_testclinic.c.h
index 7e29998..0f5ae5e 100644
--- a/Modules/clinic/_testclinic.c.h
+++ b/Modules/clinic/_testclinic.c.h
@@ -9,6 +9,7 @@ preserve
#include "pycore_long.h" // _PyLong_UnsignedShort_Converter()
#include "pycore_modsupport.h" // _PyArg_CheckPositional()
#include "pycore_runtime.h" // _Py_ID()
+#include "pycore_tuple.h" // _PyTuple_FromArray()
PyDoc_STRVAR(test_empty_function__doc__,
"test_empty_function($module, /)\n"
@@ -2530,22 +2531,24 @@ PyDoc_STRVAR(varpos__doc__,
{"varpos", _PyCFunction_CAST(varpos), METH_FASTCALL, varpos__doc__},
static PyObject *
-varpos_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args);
+varpos_impl(PyObject *module, PyObject *args);
static PyObject *
varpos(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject *__clinic_args = NULL;
- if (!_PyArg_CheckPositional("varpos", nargs, 0, PY_SSIZE_T_MAX)) {
+ __clinic_args = _PyTuple_FromArray(args, nargs);
+ if (__clinic_args == NULL) {
goto exit;
}
- __clinic_args = args + 0;
- return_value = varpos_impl(module, nvararg, __clinic_args);
+ return_value = varpos_impl(module, __clinic_args);
exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
return return_value;
}
@@ -2559,26 +2562,75 @@ PyDoc_STRVAR(posonly_varpos__doc__,
static PyObject *
posonly_varpos_impl(PyObject *module, PyObject *a, PyObject *b,
- Py_ssize_t nargs, PyObject *const *args);
+ PyObject *args);
static PyObject *
posonly_varpos(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 2;
PyObject *a;
PyObject *b;
- PyObject *const *__clinic_args = NULL;
+ PyObject *__clinic_args = NULL;
if (!_PyArg_CheckPositional("posonly_varpos", nargs, 2, PY_SSIZE_T_MAX)) {
goto exit;
}
a = args[0];
b = args[1];
- __clinic_args = args + 2;
- return_value = posonly_varpos_impl(module, a, b, nvararg, __clinic_args);
+ __clinic_args = _PyTuple_FromArray(args + 2, nargs - 2);
+ if (__clinic_args == NULL) {
+ goto exit;
+ }
+ return_value = posonly_varpos_impl(module, a, b, __clinic_args);
exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
+ return return_value;
+}
+
+PyDoc_STRVAR(posonly_req_opt_varpos__doc__,
+"posonly_req_opt_varpos($module, a, b=False, /, *args)\n"
+"--\n"
+"\n");
+
+#define POSONLY_REQ_OPT_VARPOS_METHODDEF \
+ {"posonly_req_opt_varpos", _PyCFunction_CAST(posonly_req_opt_varpos), METH_FASTCALL, posonly_req_opt_varpos__doc__},
+
+static PyObject *
+posonly_req_opt_varpos_impl(PyObject *module, PyObject *a, PyObject *b,
+ PyObject *args);
+
+static PyObject *
+posonly_req_opt_varpos(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *a;
+ PyObject *b = Py_False;
+ PyObject *__clinic_args = NULL;
+
+ if (!_PyArg_CheckPositional("posonly_req_opt_varpos", nargs, 1, PY_SSIZE_T_MAX)) {
+ goto exit;
+ }
+ a = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ b = args[1];
+skip_optional:
+ __clinic_args = nargs > 2
+ ? _PyTuple_FromArray(args + 2, nargs - 2)
+ : PyTuple_New(0);
+ if (__clinic_args == NULL) {
+ goto exit;
+ }
+ return_value = posonly_req_opt_varpos_impl(module, a, b, __clinic_args);
+
+exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
return return_value;
}
@@ -2623,22 +2675,30 @@ posonly_poskw_varpos(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[3];
+ PyObject *argsbuf[2];
+ PyObject * const *fastargs;
PyObject *a;
PyObject *b;
PyObject *__clinic_args = NULL;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, 2, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
+ if (!fastargs) {
+ goto exit;
+ }
+ a = fastargs[0];
+ b = fastargs[1];
+ __clinic_args = nargs > 2
+ ? _PyTuple_FromArray(args + 2, nargs - 2)
+ : PyTuple_New(0);
+ if (__clinic_args == NULL) {
goto exit;
}
- a = args[0];
- b = args[1];
- __clinic_args = args[2];
return_value = posonly_poskw_varpos_impl(module, a, b, __clinic_args);
exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
return return_value;
}
@@ -2682,20 +2742,28 @@ poskw_varpos(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[1];
+ PyObject * const *fastargs;
PyObject *a;
PyObject *__clinic_args = NULL;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!fastargs) {
+ goto exit;
+ }
+ a = fastargs[0];
+ __clinic_args = nargs > 1
+ ? _PyTuple_FromArray(args + 1, nargs - 1)
+ : PyTuple_New(0);
+ if (__clinic_args == NULL) {
goto exit;
}
- a = args[0];
- __clinic_args = args[1];
return_value = poskw_varpos_impl(module, a, __clinic_args);
exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
return return_value;
}
@@ -2740,30 +2808,38 @@ poskw_varpos_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t narg
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[3];
+ PyObject *argsbuf[2];
+ PyObject * const *fastargs;
Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *a;
PyObject *__clinic_args = NULL;
int b = 0;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!fastargs) {
goto exit;
}
- a = args[0];
- __clinic_args = args[1];
+ a = fastargs[0];
if (!noptargs) {
goto skip_optional_kwonly;
}
- b = PyObject_IsTrue(args[2]);
+ b = PyObject_IsTrue(fastargs[1]);
if (b < 0) {
goto exit;
}
skip_optional_kwonly:
+ __clinic_args = nargs > 1
+ ? _PyTuple_FromArray(args + 1, nargs - 1)
+ : PyTuple_New(0);
+ if (__clinic_args == NULL) {
+ goto exit;
+ }
return_value = poskw_varpos_kwonly_opt_impl(module, a, __clinic_args, b);
exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
return return_value;
}
@@ -2808,34 +2884,42 @@ poskw_varpos_kwonly_opt2(PyObject *module, PyObject *const *args, Py_ssize_t nar
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[4];
+ PyObject *argsbuf[3];
+ PyObject * const *fastargs;
Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *a;
PyObject *__clinic_args = NULL;
PyObject *b = Py_False;
PyObject *c = Py_False;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!fastargs) {
goto exit;
}
- a = args[0];
- __clinic_args = args[1];
+ a = fastargs[0];
if (!noptargs) {
goto skip_optional_kwonly;
}
- if (args[2]) {
- b = args[2];
+ if (fastargs[1]) {
+ b = fastargs[1];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
- c = args[3];
+ c = fastargs[2];
skip_optional_kwonly:
+ __clinic_args = nargs > 1
+ ? _PyTuple_FromArray(args + 1, nargs - 1)
+ : PyTuple_New(0);
+ if (__clinic_args == NULL) {
+ goto exit;
+ }
return_value = poskw_varpos_kwonly_opt2_impl(module, a, __clinic_args, b, c);
exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
return return_value;
}
@@ -2879,25 +2963,31 @@ varpos_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[1];
+ PyObject * const *fastargs;
Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
PyObject *__clinic_args = NULL;
PyObject *b = Py_False;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf);
+ if (!fastargs) {
goto exit;
}
- __clinic_args = args[0];
if (!noptargs) {
goto skip_optional_kwonly;
}
- b = args[1];
+ b = fastargs[0];
skip_optional_kwonly:
+ __clinic_args = _PyTuple_FromArray(args, nargs);
+ if (__clinic_args == NULL) {
+ goto exit;
+ }
return_value = varpos_kwonly_opt_impl(module, __clinic_args, b);
exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
return return_value;
}
@@ -2942,34 +3032,202 @@ varpos_kwonly_req_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[4];
+ PyObject *argsbuf[3];
+ PyObject * const *fastargs;
Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *__clinic_args = NULL;
PyObject *a;
PyObject *b = Py_False;
PyObject *c = Py_False;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 1, 0, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 1, argsbuf);
+ if (!fastargs) {
goto exit;
}
- __clinic_args = args[0];
- a = args[1];
+ a = fastargs[0];
if (!noptargs) {
goto skip_optional_kwonly;
}
- if (args[2]) {
- b = args[2];
+ if (fastargs[1]) {
+ b = fastargs[1];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
- c = args[3];
+ c = fastargs[2];
skip_optional_kwonly:
+ __clinic_args = _PyTuple_FromArray(args, nargs);
+ if (__clinic_args == NULL) {
+ goto exit;
+ }
return_value = varpos_kwonly_req_opt_impl(module, __clinic_args, a, b, c);
exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
+ return return_value;
+}
+
+PyDoc_STRVAR(varpos_array__doc__,
+"varpos_array($module, /, *args)\n"
+"--\n"
+"\n");
+
+#define VARPOS_ARRAY_METHODDEF \
+ {"varpos_array", _PyCFunction_CAST(varpos_array), METH_FASTCALL, varpos_array__doc__},
+
+static PyObject *
+varpos_array_impl(PyObject *module, PyObject * const *args,
+ Py_ssize_t args_length);
+
+static PyObject *
+varpos_array(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject * const *__clinic_args;
+ Py_ssize_t args_length;
+
+ __clinic_args = args;
+ args_length = nargs;
+ return_value = varpos_array_impl(module, __clinic_args, args_length);
+
+ return return_value;
+}
+
+PyDoc_STRVAR(posonly_varpos_array__doc__,
+"posonly_varpos_array($module, a, b, /, *args)\n"
+"--\n"
+"\n");
+
+#define POSONLY_VARPOS_ARRAY_METHODDEF \
+ {"posonly_varpos_array", _PyCFunction_CAST(posonly_varpos_array), METH_FASTCALL, posonly_varpos_array__doc__},
+
+static PyObject *
+posonly_varpos_array_impl(PyObject *module, PyObject *a, PyObject *b,
+ PyObject * const *args, Py_ssize_t args_length);
+
+static PyObject *
+posonly_varpos_array(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *a;
+ PyObject *b;
+ PyObject * const *__clinic_args;
+ Py_ssize_t args_length;
+
+ if (!_PyArg_CheckPositional("posonly_varpos_array", nargs, 2, PY_SSIZE_T_MAX)) {
+ goto exit;
+ }
+ a = args[0];
+ b = args[1];
+ __clinic_args = args + 2;
+ args_length = nargs - 2;
+ return_value = posonly_varpos_array_impl(module, a, b, __clinic_args, args_length);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(posonly_req_opt_varpos_array__doc__,
+"posonly_req_opt_varpos_array($module, a, b=False, /, *args)\n"
+"--\n"
+"\n");
+
+#define POSONLY_REQ_OPT_VARPOS_ARRAY_METHODDEF \
+ {"posonly_req_opt_varpos_array", _PyCFunction_CAST(posonly_req_opt_varpos_array), METH_FASTCALL, posonly_req_opt_varpos_array__doc__},
+
+static PyObject *
+posonly_req_opt_varpos_array_impl(PyObject *module, PyObject *a, PyObject *b,
+ PyObject * const *args,
+ Py_ssize_t args_length);
+
+static PyObject *
+posonly_req_opt_varpos_array(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *a;
+ PyObject *b = Py_False;
+ PyObject * const *__clinic_args;
+ Py_ssize_t args_length;
+
+ if (!_PyArg_CheckPositional("posonly_req_opt_varpos_array", nargs, 1, PY_SSIZE_T_MAX)) {
+ goto exit;
+ }
+ a = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ b = args[1];
+skip_optional:
+ __clinic_args = nargs > 2 ? args + 2 : args;
+ args_length = Py_MAX(0, nargs - 2);
+ return_value = posonly_req_opt_varpos_array_impl(module, a, b, __clinic_args, args_length);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(posonly_poskw_varpos_array__doc__,
+"posonly_poskw_varpos_array($module, a, /, b, *args)\n"
+"--\n"
+"\n");
+
+#define POSONLY_POSKW_VARPOS_ARRAY_METHODDEF \
+ {"posonly_poskw_varpos_array", _PyCFunction_CAST(posonly_poskw_varpos_array), METH_FASTCALL|METH_KEYWORDS, posonly_poskw_varpos_array__doc__},
+
+static PyObject *
+posonly_poskw_varpos_array_impl(PyObject *module, PyObject *a, PyObject *b,
+ PyObject * const *args,
+ Py_ssize_t args_length);
+
+static PyObject *
+posonly_poskw_varpos_array(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { _Py_LATIN1_CHR('b'), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"", "b", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "posonly_poskw_varpos_array",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[2];
+ PyObject * const *fastargs;
+ PyObject *a;
+ PyObject *b;
+ PyObject * const *__clinic_args;
+ Py_ssize_t args_length;
+
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
+ if (!fastargs) {
+ goto exit;
+ }
+ a = fastargs[0];
+ b = fastargs[1];
+ __clinic_args = nargs > 2 ? args + 2 : args;
+ args_length = Py_MAX(0, nargs - 2);
+ return_value = posonly_poskw_varpos_array_impl(module, a, b, __clinic_args, args_length);
+
+exit:
return return_value;
}
@@ -3015,7 +3273,8 @@ gh_32092_oob(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[5];
+ PyObject *argsbuf[4];
+ PyObject * const *fastargs;
Py_ssize_t noptargs = Py_MIN(nargs, 2) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
PyObject *pos1;
PyObject *pos2;
@@ -3023,28 +3282,35 @@ gh_32092_oob(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
PyObject *kw1 = Py_None;
PyObject *kw2 = Py_None;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, 2, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
+ if (!fastargs) {
goto exit;
}
- pos1 = args[0];
- pos2 = args[1];
- varargs = args[2];
+ pos1 = fastargs[0];
+ pos2 = fastargs[1];
if (!noptargs) {
goto skip_optional_kwonly;
}
- if (args[3]) {
- kw1 = args[3];
+ if (fastargs[2]) {
+ kw1 = fastargs[2];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
- kw2 = args[4];
+ kw2 = fastargs[3];
skip_optional_kwonly:
+ varargs = nargs > 2
+ ? _PyTuple_FromArray(args + 2, nargs - 2)
+ : PyTuple_New(0);
+ if (varargs == NULL) {
+ goto exit;
+ }
return_value = gh_32092_oob_impl(module, pos1, pos2, varargs, kw1, kw2);
exit:
+ /* Cleanup for varargs */
Py_XDECREF(varargs);
+
return return_value;
}
@@ -3090,27 +3356,35 @@ gh_32092_kw_pass(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[3];
+ PyObject *argsbuf[2];
+ PyObject * const *fastargs;
Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *pos;
PyObject *__clinic_args = NULL;
PyObject *kw = Py_None;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!fastargs) {
goto exit;
}
- pos = args[0];
- __clinic_args = args[1];
+ pos = fastargs[0];
if (!noptargs) {
goto skip_optional_kwonly;
}
- kw = args[2];
+ kw = fastargs[1];
skip_optional_kwonly:
+ __clinic_args = nargs > 1
+ ? _PyTuple_FromArray(args + 1, nargs - 1)
+ : PyTuple_New(0);
+ if (__clinic_args == NULL) {
+ goto exit;
+ }
return_value = gh_32092_kw_pass_impl(module, pos, __clinic_args, kw);
exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
return return_value;
}
@@ -3124,23 +3398,24 @@ PyDoc_STRVAR(gh_99233_refcount__doc__,
{"gh_99233_refcount", _PyCFunction_CAST(gh_99233_refcount), METH_FASTCALL, gh_99233_refcount__doc__},
static PyObject *
-gh_99233_refcount_impl(PyObject *module, Py_ssize_t nargs,
- PyObject *const *args);
+gh_99233_refcount_impl(PyObject *module, PyObject *args);
static PyObject *
gh_99233_refcount(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject *__clinic_args = NULL;
- if (!_PyArg_CheckPositional("gh_99233_refcount", nargs, 0, PY_SSIZE_T_MAX)) {
+ __clinic_args = _PyTuple_FromArray(args, nargs);
+ if (__clinic_args == NULL) {
goto exit;
}
- __clinic_args = args + 0;
- return_value = gh_99233_refcount_impl(module, nvararg, __clinic_args);
+ return_value = gh_99233_refcount_impl(module, __clinic_args);
exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
return return_value;
}
@@ -3220,30 +3495,38 @@ null_or_tuple_for_varargs(PyObject *module, PyObject *const *args, Py_ssize_t na
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[3];
+ PyObject *argsbuf[2];
+ PyObject * const *fastargs;
Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *name;
PyObject *constraints = NULL;
int covariant = 0;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!fastargs) {
goto exit;
}
- name = args[0];
- constraints = args[1];
+ name = fastargs[0];
if (!noptargs) {
goto skip_optional_kwonly;
}
- covariant = PyObject_IsTrue(args[2]);
+ covariant = PyObject_IsTrue(fastargs[1]);
if (covariant < 0) {
goto exit;
}
skip_optional_kwonly:
+ constraints = nargs > 1
+ ? _PyTuple_FromArray(args + 1, nargs - 1)
+ : PyTuple_New(0);
+ if (constraints == NULL) {
+ goto exit;
+ }
return_value = null_or_tuple_for_varargs_impl(module, name, constraints, covariant);
exit:
+ /* Cleanup for constraints */
Py_XDECREF(constraints);
+
return return_value;
}
@@ -3613,17 +3896,23 @@ _testclinic_TestClass_defclass_varpos(PyObject *self, PyTypeObject *cls, PyObjec
};
#undef KWTUPLE
PyObject *argsbuf[1];
+ PyObject * const *fastargs;
PyObject *__clinic_args = NULL;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf);
+ if (!fastargs) {
+ goto exit;
+ }
+ __clinic_args = _PyTuple_FromArray(args, nargs);
+ if (__clinic_args == NULL) {
goto exit;
}
- __clinic_args = args[0];
return_value = _testclinic_TestClass_defclass_varpos_impl(self, cls, __clinic_args);
exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
return return_value;
}
@@ -3658,22 +3947,335 @@ _testclinic_TestClass_defclass_posonly_varpos(PyObject *self, PyTypeObject *cls,
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[3];
+ PyObject *argsbuf[2];
+ PyObject * const *fastargs;
PyObject *a;
PyObject *b;
PyObject *__clinic_args = NULL;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, 2, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
+ if (!fastargs) {
+ goto exit;
+ }
+ a = fastargs[0];
+ b = fastargs[1];
+ __clinic_args = _PyTuple_FromArray(args + 2, nargs - 2);
+ if (__clinic_args == NULL) {
goto exit;
}
- a = args[0];
- b = args[1];
- __clinic_args = args[2];
return_value = _testclinic_TestClass_defclass_posonly_varpos_impl(self, cls, a, b, __clinic_args);
exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
+ return return_value;
+}
+
+static PyObject *
+varpos_no_fastcall_impl(PyTypeObject *type, PyObject *args);
+
+static PyObject *
+varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ PyTypeObject *base_tp = &PyBaseObject_Type;
+ PyObject *__clinic_args = NULL;
+
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+ !_PyArg_NoKeywords("TestClass", kwargs)) {
+ goto exit;
+ }
+ __clinic_args = Py_NewRef(args);
+ return_value = varpos_no_fastcall_impl(type, __clinic_args);
+
+exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
+ return return_value;
+}
+
+static PyObject *
+posonly_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a, PyObject *b,
+ PyObject *args);
+
+static PyObject *
+posonly_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ PyTypeObject *base_tp = &PyBaseObject_Type;
+ PyObject *a;
+ PyObject *b;
+ PyObject *__clinic_args = NULL;
+
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+ !_PyArg_NoKeywords("TestClass", kwargs)) {
+ goto exit;
+ }
+ if (!_PyArg_CheckPositional("TestClass", PyTuple_GET_SIZE(args), 2, PY_SSIZE_T_MAX)) {
+ goto exit;
+ }
+ a = PyTuple_GET_ITEM(args, 0);
+ b = PyTuple_GET_ITEM(args, 1);
+ __clinic_args = PyTuple_GetSlice(args, 2, PY_SSIZE_T_MAX);
+ if (!__clinic_args) {
+ goto exit;
+ }
+ return_value = posonly_varpos_no_fastcall_impl(type, a, b, __clinic_args);
+
+exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
+ return return_value;
+}
+
+static PyObject *
+posonly_req_opt_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+ PyObject *b, PyObject *args);
+
+static PyObject *
+posonly_req_opt_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ PyTypeObject *base_tp = &PyBaseObject_Type;
+ PyObject *a;
+ PyObject *b = Py_False;
+ PyObject *__clinic_args = NULL;
+
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+ !_PyArg_NoKeywords("TestClass", kwargs)) {
+ goto exit;
+ }
+ if (!_PyArg_CheckPositional("TestClass", PyTuple_GET_SIZE(args), 1, PY_SSIZE_T_MAX)) {
+ goto exit;
+ }
+ a = PyTuple_GET_ITEM(args, 0);
+ if (PyTuple_GET_SIZE(args) < 2) {
+ goto skip_optional;
+ }
+ b = PyTuple_GET_ITEM(args, 1);
+skip_optional:
+ __clinic_args = PyTuple_GetSlice(args, 2, PY_SSIZE_T_MAX);
+ if (!__clinic_args) {
+ goto exit;
+ }
+ return_value = posonly_req_opt_varpos_no_fastcall_impl(type, a, b, __clinic_args);
+
+exit:
+ /* Cleanup for args */
+ Py_XDECREF(__clinic_args);
+
+ return return_value;
+}
+
+static PyObject *
+posonly_poskw_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+ PyObject *b, PyObject *args);
+
+static PyObject *
+posonly_poskw_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { _Py_LATIN1_CHR('b'), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"", "b", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "TestClass",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[2];
+ PyObject * const *fastargs;
+ Py_ssize_t nargs = PyTuple_GET_SIZE(args);
+ PyObject *a;
+ PyObject *b;
+ PyObject *__clinic_args = NULL;
+
+ fastargs = _PyArg_UnpackKeywordsWithVararg(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 2, 2, 0, argsbuf);
+ if (!fastargs) {
+ goto exit;
+ }
+ a = fastargs[0];
+ b = fastargs[1];
+ __clinic_args = PyTuple_GetSlice(args, 2, PY_SSIZE_T_MAX);
+ if (!__clinic_args) {
+ goto exit;
+ }
+ return_value = posonly_poskw_varpos_no_fastcall_impl(type, a, b, __clinic_args);
+
+exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
+ return return_value;
+}
+
+static PyObject *
+varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject * const *args,
+ Py_ssize_t args_length);
+
+static PyObject *
+varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ PyTypeObject *base_tp = &PyBaseObject_Type;
+ PyObject * const *__clinic_args;
+ Py_ssize_t args_length;
+
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+ !_PyArg_NoKeywords("TestClass", kwargs)) {
+ goto exit;
+ }
+ __clinic_args = _PyTuple_ITEMS(args);
+ args_length = PyTuple_GET_SIZE(args);
+ return_value = varpos_array_no_fastcall_impl(type, __clinic_args, args_length);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+posonly_varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+ PyObject *b, PyObject * const *args,
+ Py_ssize_t args_length);
+
+static PyObject *
+posonly_varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ PyTypeObject *base_tp = &PyBaseObject_Type;
+ PyObject *a;
+ PyObject *b;
+ PyObject * const *__clinic_args;
+ Py_ssize_t args_length;
+
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+ !_PyArg_NoKeywords("TestClass", kwargs)) {
+ goto exit;
+ }
+ if (!_PyArg_CheckPositional("TestClass", PyTuple_GET_SIZE(args), 2, PY_SSIZE_T_MAX)) {
+ goto exit;
+ }
+ a = PyTuple_GET_ITEM(args, 0);
+ b = PyTuple_GET_ITEM(args, 1);
+ __clinic_args = _PyTuple_ITEMS(args) + 2;
+ args_length = PyTuple_GET_SIZE(args) - 2;
+ return_value = posonly_varpos_array_no_fastcall_impl(type, a, b, __clinic_args, args_length);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+posonly_req_opt_varpos_array_no_fastcall_impl(PyTypeObject *type,
+ PyObject *a, PyObject *b,
+ PyObject * const *args,
+ Py_ssize_t args_length);
+
+static PyObject *
+posonly_req_opt_varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ PyTypeObject *base_tp = &PyBaseObject_Type;
+ PyObject *a;
+ PyObject *b = Py_False;
+ PyObject * const *__clinic_args;
+ Py_ssize_t args_length;
+
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+ !_PyArg_NoKeywords("TestClass", kwargs)) {
+ goto exit;
+ }
+ if (!_PyArg_CheckPositional("TestClass", PyTuple_GET_SIZE(args), 1, PY_SSIZE_T_MAX)) {
+ goto exit;
+ }
+ a = PyTuple_GET_ITEM(args, 0);
+ if (PyTuple_GET_SIZE(args) < 2) {
+ goto skip_optional;
+ }
+ b = PyTuple_GET_ITEM(args, 1);
+skip_optional:
+ __clinic_args = PyTuple_GET_SIZE(args) > 2 ? _PyTuple_ITEMS(args) + 2 : _PyTuple_ITEMS(args);
+ args_length = Py_MAX(0, PyTuple_GET_SIZE(args) - 2);
+ return_value = posonly_req_opt_varpos_array_no_fastcall_impl(type, a, b, __clinic_args, args_length);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+posonly_poskw_varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject *a,
+ PyObject *b,
+ PyObject * const *args,
+ Py_ssize_t args_length);
+
+static PyObject *
+posonly_poskw_varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { _Py_LATIN1_CHR('b'), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"", "b", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "TestClass",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[2];
+ PyObject * const *fastargs;
+ Py_ssize_t nargs = PyTuple_GET_SIZE(args);
+ PyObject *a;
+ PyObject *b;
+ PyObject * const *__clinic_args;
+ Py_ssize_t args_length;
+
+ fastargs = _PyArg_UnpackKeywordsWithVararg(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 2, 2, 0, argsbuf);
+ if (!fastargs) {
+ goto exit;
+ }
+ a = fastargs[0];
+ b = fastargs[1];
+ __clinic_args = PyTuple_GET_SIZE(args) > 2 ? _PyTuple_ITEMS(args) + 2 : _PyTuple_ITEMS(args);
+ args_length = Py_MAX(0, PyTuple_GET_SIZE(args) - 2);
+ return_value = posonly_poskw_varpos_array_no_fastcall_impl(type, a, b, __clinic_args, args_length);
+
+exit:
return return_value;
}
-/*[clinic end generated code: output=7662d07e7d29cbeb input=a9049054013a1b77]*/
+/*[clinic end generated code: output=ed3408af146a746c input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_testclinic_depr.c.h b/Modules/clinic/_testclinic_depr.c.h
index 95a2cc4..0e374f1 100644
--- a/Modules/clinic/_testclinic_depr.c.h
+++ b/Modules/clinic/_testclinic_depr.c.h
@@ -9,6 +9,7 @@ preserve
#include "pycore_long.h" // _PyLong_UnsignedShort_Converter()
#include "pycore_modsupport.h" // _PyArg_CheckPositional()
#include "pycore_runtime.h" // _Py_ID()
+#include "pycore_tuple.h" // _PyTuple_FromArray()
PyDoc_STRVAR(depr_star_new__doc__,
"DeprStarNew(a=None)\n"
@@ -2393,4 +2394,4 @@ depr_multi(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *
exit:
return return_value;
}
-/*[clinic end generated code: output=ca6da2c7137554be input=a9049054013a1b77]*/
+/*[clinic end generated code: output=5dda27c80df7351e input=a9049054013a1b77]*/
diff --git a/Modules/clinic/gcmodule.c.h b/Modules/clinic/gcmodule.c.h
index be3bd35..34b2a79 100644
--- a/Modules/clinic/gcmodule.c.h
+++ b/Modules/clinic/gcmodule.c.h
@@ -8,6 +8,7 @@ preserve
#endif
#include "pycore_abstract.h" // _Py_convert_optional_to_ssize_t()
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
+#include "pycore_tuple.h" // _PyTuple_FromArray()
PyDoc_STRVAR(gc_enable__doc__,
"enable($module, /)\n"
@@ -312,23 +313,24 @@ PyDoc_STRVAR(gc_get_referrers__doc__,
{"get_referrers", _PyCFunction_CAST(gc_get_referrers), METH_FASTCALL, gc_get_referrers__doc__},
static PyObject *
-gc_get_referrers_impl(PyObject *module, Py_ssize_t nargs,
- PyObject *const *args);
+gc_get_referrers_impl(PyObject *module, PyObject *objs);
static PyObject *
gc_get_referrers(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject *objs = NULL;
- if (!_PyArg_CheckPositional("get_referrers", nargs, 0, PY_SSIZE_T_MAX)) {
+ objs = _PyTuple_FromArray(args, nargs);
+ if (objs == NULL) {
goto exit;
}
- __clinic_args = args + 0;
- return_value = gc_get_referrers_impl(module, nvararg, __clinic_args);
+ return_value = gc_get_referrers_impl(module, objs);
exit:
+ /* Cleanup for objs */
+ Py_XDECREF(objs);
+
return return_value;
}
@@ -342,23 +344,24 @@ PyDoc_STRVAR(gc_get_referents__doc__,
{"get_referents", _PyCFunction_CAST(gc_get_referents), METH_FASTCALL, gc_get_referents__doc__},
static PyObject *
-gc_get_referents_impl(PyObject *module, Py_ssize_t nargs,
- PyObject *const *args);
+gc_get_referents_impl(PyObject *module, PyObject *objs);
static PyObject *
gc_get_referents(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject *objs = NULL;
- if (!_PyArg_CheckPositional("get_referents", nargs, 0, PY_SSIZE_T_MAX)) {
+ objs = _PyTuple_FromArray(args, nargs);
+ if (objs == NULL) {
goto exit;
}
- __clinic_args = args + 0;
- return_value = gc_get_referents_impl(module, nvararg, __clinic_args);
+ return_value = gc_get_referents_impl(module, objs);
exit:
+ /* Cleanup for objs */
+ Py_XDECREF(objs);
+
return return_value;
}
@@ -575,4 +578,4 @@ gc_get_freeze_count(PyObject *module, PyObject *Py_UNUSED(ignored))
exit:
return return_value;
}
-/*[clinic end generated code: output=f488a0d4d6bd3687 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4f35875870da17c9 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h
index e4bda8a..461f771 100644
--- a/Modules/clinic/mathmodule.c.h
+++ b/Modules/clinic/mathmodule.c.h
@@ -18,22 +18,20 @@ PyDoc_STRVAR(math_gcd__doc__,
{"gcd", _PyCFunction_CAST(math_gcd), METH_FASTCALL, math_gcd__doc__},
static PyObject *
-math_gcd_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args);
+math_gcd_impl(PyObject *module, PyObject * const *args,
+ Py_ssize_t args_length);
static PyObject *
math_gcd(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject * const *__clinic_args;
+ Py_ssize_t args_length;
- if (!_PyArg_CheckPositional("gcd", nargs, 0, PY_SSIZE_T_MAX)) {
- goto exit;
- }
- __clinic_args = args + 0;
- return_value = math_gcd_impl(module, nvararg, __clinic_args);
+ __clinic_args = args;
+ args_length = nargs;
+ return_value = math_gcd_impl(module, __clinic_args, args_length);
-exit:
return return_value;
}
@@ -47,22 +45,20 @@ PyDoc_STRVAR(math_lcm__doc__,
{"lcm", _PyCFunction_CAST(math_lcm), METH_FASTCALL, math_lcm__doc__},
static PyObject *
-math_lcm_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args);
+math_lcm_impl(PyObject *module, PyObject * const *args,
+ Py_ssize_t args_length);
static PyObject *
math_lcm(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject * const *__clinic_args;
+ Py_ssize_t args_length;
- if (!_PyArg_CheckPositional("lcm", nargs, 0, PY_SSIZE_T_MAX)) {
- goto exit;
- }
- __clinic_args = args + 0;
- return_value = math_lcm_impl(module, nvararg, __clinic_args);
+ __clinic_args = args;
+ args_length = nargs;
+ return_value = math_lcm_impl(module, __clinic_args, args_length);
-exit:
return return_value;
}
@@ -430,22 +426,20 @@ PyDoc_STRVAR(math_hypot__doc__,
{"hypot", _PyCFunction_CAST(math_hypot), METH_FASTCALL, math_hypot__doc__},
static PyObject *
-math_hypot_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args);
+math_hypot_impl(PyObject *module, PyObject * const *args,
+ Py_ssize_t args_length);
static PyObject *
math_hypot(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject * const *__clinic_args;
+ Py_ssize_t args_length;
- if (!_PyArg_CheckPositional("hypot", nargs, 0, PY_SSIZE_T_MAX)) {
- goto exit;
- }
- __clinic_args = args + 0;
- return_value = math_hypot_impl(module, nvararg, __clinic_args);
+ __clinic_args = args;
+ args_length = nargs;
+ return_value = math_hypot_impl(module, __clinic_args, args_length);
-exit:
return return_value;
}
@@ -1109,4 +1103,4 @@ math_ulp(PyObject *module, PyObject *arg)
exit:
return return_value;
}
-/*[clinic end generated code: output=ff99a737c18d9210 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=cb506f61bc5ef862 input=a9049054013a1b77]*/
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index f5fea5a..ad13496 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -216,31 +216,21 @@ gc_get_count_impl(PyObject *module)
/*[clinic input]
gc.get_referrers
- *objs as args: object
+ *objs: tuple
Return the list of objects that directly refer to any of 'objs'.
[clinic start generated code]*/
static PyObject *
-gc_get_referrers_impl(PyObject *module, Py_ssize_t nargs,
- PyObject *const *args)
-/*[clinic end generated code: output=1d44a7695ea25c40 input=bae96961b14a0922]*/
+gc_get_referrers_impl(PyObject *module, PyObject *objs)
+/*[clinic end generated code: output=929d6dff26f609b9 input=9102be7ebee69ee3]*/
{
- PyObject *varargs = _PyTuple_FromArray(args, nargs);
-
- if (!varargs) {
- return NULL;
- }
- if (PySys_Audit("gc.get_referrers", "(O)", varargs) < 0) {
- Py_DECREF(varargs);
+ if (PySys_Audit("gc.get_referrers", "(O)", objs) < 0) {
return NULL;
}
PyInterpreterState *interp = _PyInterpreterState_GET();
- PyObject *result = _PyGC_GetReferrers(interp, varargs);
-
- Py_DECREF(varargs);
- return result;
+ return _PyGC_GetReferrers(interp, objs);
}
/* Append obj to list; return true if error (out of memory), false if OK. */
@@ -274,43 +264,34 @@ append_referrents(PyObject *result, PyObject *args)
/*[clinic input]
gc.get_referents
- *objs as args: object
+ *objs: tuple
Return the list of objects that are directly referred to by 'objs'.
[clinic start generated code]*/
static PyObject *
-gc_get_referents_impl(PyObject *module, Py_ssize_t nargs,
- PyObject *const *args)
-/*[clinic end generated code: output=e459f3e8c0d19311 input=b3ceab0c34038cbf]*/
+gc_get_referents_impl(PyObject *module, PyObject *objs)
+/*[clinic end generated code: output=6dfde40cd1588e1d input=55c078a6d0248fe0]*/
{
- PyObject *varargs = _PyTuple_FromArray(args, nargs);
-
- if (!varargs) {
- return NULL;
- }
- if (PySys_Audit("gc.get_referents", "(O)", varargs) < 0) {
- Py_DECREF(varargs);
+ if (PySys_Audit("gc.get_referents", "(O)", objs) < 0) {
return NULL;
}
PyInterpreterState *interp = _PyInterpreterState_GET();
PyObject *result = PyList_New(0);
if (result == NULL) {
- Py_DECREF(varargs);
return NULL;
}
// NOTE: stop the world is a no-op in default build
_PyEval_StopTheWorld(interp);
- int err = append_referrents(result, varargs);
+ int err = append_referrents(result, objs);
_PyEval_StartTheWorld(interp);
if (err < 0) {
Py_CLEAR(result);
}
- Py_DECREF(varargs);
return result;
}
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index 77f50a2..2963811 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -722,22 +722,23 @@ m_log10(double x)
/*[clinic input]
math.gcd
- *integers as args: object
+ *integers as args: array
Greatest Common Divisor.
[clinic start generated code]*/
static PyObject *
-math_gcd_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=b57687fcf431c1b8 input=94e675b7ceeaf0c9]*/
+math_gcd_impl(PyObject *module, PyObject * const *args,
+ Py_ssize_t args_length)
+/*[clinic end generated code: output=a26c95907374ffb4 input=ded7f0ea3850c05c]*/
{
// Fast-path for the common case: gcd(int, int)
- if (nargs == 2 && PyLong_CheckExact(args[0]) && PyLong_CheckExact(args[1]))
+ if (args_length == 2 && PyLong_CheckExact(args[0]) && PyLong_CheckExact(args[1]))
{
return _PyLong_GCD(args[0], args[1]);
}
- if (nargs == 0) {
+ if (args_length == 0) {
return PyLong_FromLong(0);
}
@@ -745,13 +746,13 @@ math_gcd_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
if (res == NULL) {
return NULL;
}
- if (nargs == 1) {
+ if (args_length == 1) {
Py_SETREF(res, PyNumber_Absolute(res));
return res;
}
PyObject *one = _PyLong_GetOne(); // borrowed ref
- for (Py_ssize_t i = 1; i < nargs; i++) {
+ for (Py_ssize_t i = 1; i < args_length; i++) {
PyObject *x = _PyNumber_Index(args[i]);
if (x == NULL) {
Py_DECREF(res);
@@ -804,32 +805,33 @@ long_lcm(PyObject *a, PyObject *b)
/*[clinic input]
math.lcm
- *integers as args: object
+ *integers as args: array
Least Common Multiple.
[clinic start generated code]*/
static PyObject *
-math_lcm_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=f3eff0c25e4d7030 input=e64c33e85f4c47c6]*/
+math_lcm_impl(PyObject *module, PyObject * const *args,
+ Py_ssize_t args_length)
+/*[clinic end generated code: output=c8a59a5c2e55c816 input=3e4f4b7cdf948a98]*/
{
PyObject *res, *x;
Py_ssize_t i;
- if (nargs == 0) {
+ if (args_length == 0) {
return PyLong_FromLong(1);
}
res = PyNumber_Index(args[0]);
if (res == NULL) {
return NULL;
}
- if (nargs == 1) {
+ if (args_length == 1) {
Py_SETREF(res, PyNumber_Absolute(res));
return res;
}
PyObject *zero = _PyLong_GetZero(); // borrowed ref
- for (i = 1; i < nargs; i++) {
+ for (i = 1; i < args_length; i++) {
x = PyNumber_Index(args[i]);
if (x == NULL) {
Py_DECREF(res);
@@ -2629,7 +2631,7 @@ math_dist_impl(PyObject *module, PyObject *p, PyObject *q)
/*[clinic input]
math.hypot
- *coordinates as args: object
+ *coordinates as args: array
Multidimensional Euclidean distance from the origin to a point.
@@ -2646,8 +2648,9 @@ For example, the hypotenuse of a 3/4/5 right triangle is:
[clinic start generated code]*/
static PyObject *
-math_hypot_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=dcb6d4b7a1102ee1 input=5c0061a2d11235ed]*/
+math_hypot_impl(PyObject *module, PyObject * const *args,
+ Py_ssize_t args_length)
+/*[clinic end generated code: output=c9de404e24370068 input=1bceaf7d4fdcd9c2]*/
{
Py_ssize_t i;
PyObject *item;
@@ -2657,13 +2660,13 @@ math_hypot_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
double coord_on_stack[NUM_STACK_ELEMS];
double *coordinates = coord_on_stack;
- if (nargs > NUM_STACK_ELEMS) {
- coordinates = (double *) PyMem_Malloc(nargs * sizeof(double));
+ if (args_length > NUM_STACK_ELEMS) {
+ coordinates = (double *) PyMem_Malloc(args_length * sizeof(double));
if (coordinates == NULL) {
return PyErr_NoMemory();
}
}
- for (i = 0; i < nargs; i++) {
+ for (i = 0; i < args_length; i++) {
item = args[i];
ASSIGN_DOUBLE(x, item, error_exit);
x = fabs(x);
@@ -2673,7 +2676,7 @@ math_hypot_impl(PyObject *module, Py_ssize_t nargs, PyObject *const *args)
max = x;
}
}
- result = vector_norm(nargs, coordinates, max, found_nan);
+ result = vector_norm(args_length, coordinates, max, found_nan);
if (coordinates != coord_on_stack) {
PyMem_Free(coordinates);
}
diff --git a/Objects/clinic/setobject.c.h b/Objects/clinic/setobject.c.h
index d6e381a..986993b 100644
--- a/Objects/clinic/setobject.c.h
+++ b/Objects/clinic/setobject.c.h
@@ -3,7 +3,6 @@ preserve
[clinic start generated code]*/
#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
-#include "pycore_modsupport.h" // _PyArg_CheckPositional()
PyDoc_STRVAR(set_pop__doc__,
"pop($self, /)\n"
@@ -41,22 +40,20 @@ PyDoc_STRVAR(set_update__doc__,
{"update", _PyCFunction_CAST(set_update), METH_FASTCALL, set_update__doc__},
static PyObject *
-set_update_impl(PySetObject *so, Py_ssize_t nargs, PyObject *const *args);
+set_update_impl(PySetObject *so, PyObject * const *others,
+ Py_ssize_t others_length);
static PyObject *
set_update(PySetObject *so, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject * const *others;
+ Py_ssize_t others_length;
- if (!_PyArg_CheckPositional("update", nargs, 0, PY_SSIZE_T_MAX)) {
- goto exit;
- }
- __clinic_args = args + 0;
- return_value = set_update_impl(so, nvararg, __clinic_args);
+ others = args;
+ others_length = nargs;
+ return_value = set_update_impl(so, others, others_length);
-exit:
return return_value;
}
@@ -142,22 +139,20 @@ PyDoc_STRVAR(set_union__doc__,
{"union", _PyCFunction_CAST(set_union), METH_FASTCALL, set_union__doc__},
static PyObject *
-set_union_impl(PySetObject *so, Py_ssize_t nargs, PyObject *const *args);
+set_union_impl(PySetObject *so, PyObject * const *others,
+ Py_ssize_t others_length);
static PyObject *
set_union(PySetObject *so, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject * const *others;
+ Py_ssize_t others_length;
- if (!_PyArg_CheckPositional("union", nargs, 0, PY_SSIZE_T_MAX)) {
- goto exit;
- }
- __clinic_args = args + 0;
- return_value = set_union_impl(so, nvararg, __clinic_args);
+ others = args;
+ others_length = nargs;
+ return_value = set_union_impl(so, others, others_length);
-exit:
return return_value;
}
@@ -171,23 +166,20 @@ PyDoc_STRVAR(set_intersection_multi__doc__,
{"intersection", _PyCFunction_CAST(set_intersection_multi), METH_FASTCALL, set_intersection_multi__doc__},
static PyObject *
-set_intersection_multi_impl(PySetObject *so, Py_ssize_t nargs,
- PyObject *const *args);
+set_intersection_multi_impl(PySetObject *so, PyObject * const *others,
+ Py_ssize_t others_length);
static PyObject *
set_intersection_multi(PySetObject *so, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject * const *others;
+ Py_ssize_t others_length;
- if (!_PyArg_CheckPositional("intersection", nargs, 0, PY_SSIZE_T_MAX)) {
- goto exit;
- }
- __clinic_args = args + 0;
- return_value = set_intersection_multi_impl(so, nvararg, __clinic_args);
+ others = args;
+ others_length = nargs;
+ return_value = set_intersection_multi_impl(so, others, others_length);
-exit:
return return_value;
}
@@ -201,23 +193,20 @@ PyDoc_STRVAR(set_intersection_update_multi__doc__,
{"intersection_update", _PyCFunction_CAST(set_intersection_update_multi), METH_FASTCALL, set_intersection_update_multi__doc__},
static PyObject *
-set_intersection_update_multi_impl(PySetObject *so, Py_ssize_t nargs,
- PyObject *const *args);
+set_intersection_update_multi_impl(PySetObject *so, PyObject * const *others,
+ Py_ssize_t others_length);
static PyObject *
set_intersection_update_multi(PySetObject *so, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject * const *others;
+ Py_ssize_t others_length;
- if (!_PyArg_CheckPositional("intersection_update", nargs, 0, PY_SSIZE_T_MAX)) {
- goto exit;
- }
- __clinic_args = args + 0;
- return_value = set_intersection_update_multi_impl(so, nvararg, __clinic_args);
+ others = args;
+ others_length = nargs;
+ return_value = set_intersection_update_multi_impl(so, others, others_length);
-exit:
return return_value;
}
@@ -255,23 +244,20 @@ PyDoc_STRVAR(set_difference_update__doc__,
{"difference_update", _PyCFunction_CAST(set_difference_update), METH_FASTCALL, set_difference_update__doc__},
static PyObject *
-set_difference_update_impl(PySetObject *so, Py_ssize_t nargs,
- PyObject *const *args);
+set_difference_update_impl(PySetObject *so, PyObject * const *others,
+ Py_ssize_t others_length);
static PyObject *
set_difference_update(PySetObject *so, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject * const *others;
+ Py_ssize_t others_length;
- if (!_PyArg_CheckPositional("difference_update", nargs, 0, PY_SSIZE_T_MAX)) {
- goto exit;
- }
- __clinic_args = args + 0;
- return_value = set_difference_update_impl(so, nvararg, __clinic_args);
+ others = args;
+ others_length = nargs;
+ return_value = set_difference_update_impl(so, others, others_length);
-exit:
return return_value;
}
@@ -285,23 +271,20 @@ PyDoc_STRVAR(set_difference_multi__doc__,
{"difference", _PyCFunction_CAST(set_difference_multi), METH_FASTCALL, set_difference_multi__doc__},
static PyObject *
-set_difference_multi_impl(PySetObject *so, Py_ssize_t nargs,
- PyObject *const *args);
+set_difference_multi_impl(PySetObject *so, PyObject * const *others,
+ Py_ssize_t others_length);
static PyObject *
set_difference_multi(PySetObject *so, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- Py_ssize_t nvararg = nargs - 0;
- PyObject *const *__clinic_args = NULL;
+ PyObject * const *others;
+ Py_ssize_t others_length;
- if (!_PyArg_CheckPositional("difference", nargs, 0, PY_SSIZE_T_MAX)) {
- goto exit;
- }
- __clinic_args = args + 0;
- return_value = set_difference_multi_impl(so, nvararg, __clinic_args);
+ others = args;
+ others_length = nargs;
+ return_value = set_difference_multi_impl(so, others, others_length);
-exit:
return return_value;
}
@@ -536,4 +519,4 @@ set___sizeof__(PySetObject *so, PyObject *Py_UNUSED(ignored))
return return_value;
}
-/*[clinic end generated code: output=9d4b41191b2c602f input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4b65e7709927f31f input=a9049054013a1b77]*/
diff --git a/Objects/clinic/typevarobject.c.h b/Objects/clinic/typevarobject.c.h
index 0ba4ff4..3f439a7 100644
--- a/Objects/clinic/typevarobject.c.h
+++ b/Objects/clinic/typevarobject.c.h
@@ -49,7 +49,7 @@ typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[7];
+ PyObject *argsbuf[6];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
@@ -61,7 +61,7 @@ typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
int contravariant = 0;
int infer_variance = 0;
- fastargs = _PyArg_UnpackKeywordsWithVararg(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, 1, argsbuf);
+ fastargs = _PyArg_UnpackKeywordsWithVararg(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf);
if (!fastargs) {
goto exit;
}
@@ -70,24 +70,23 @@ typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
goto exit;
}
name = fastargs[0];
- constraints = fastargs[1];
if (!noptargs) {
goto skip_optional_kwonly;
}
- if (fastargs[2]) {
- bound = fastargs[2];
+ if (fastargs[1]) {
+ bound = fastargs[1];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
- if (fastargs[3]) {
- default_value = fastargs[3];
+ if (fastargs[2]) {
+ default_value = fastargs[2];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
- if (fastargs[4]) {
- covariant = PyObject_IsTrue(fastargs[4]);
+ if (fastargs[3]) {
+ covariant = PyObject_IsTrue(fastargs[3]);
if (covariant < 0) {
goto exit;
}
@@ -95,8 +94,8 @@ typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
goto skip_optional_kwonly;
}
}
- if (fastargs[5]) {
- contravariant = PyObject_IsTrue(fastargs[5]);
+ if (fastargs[4]) {
+ contravariant = PyObject_IsTrue(fastargs[4]);
if (contravariant < 0) {
goto exit;
}
@@ -104,15 +103,21 @@ typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
goto skip_optional_kwonly;
}
}
- infer_variance = PyObject_IsTrue(fastargs[6]);
+ infer_variance = PyObject_IsTrue(fastargs[5]);
if (infer_variance < 0) {
goto exit;
}
skip_optional_kwonly:
+ constraints = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
+ if (!constraints) {
+ goto exit;
+ }
return_value = typevar_new_impl(type, name, constraints, bound, default_value, covariant, contravariant, infer_variance);
exit:
+ /* Cleanup for constraints */
Py_XDECREF(constraints);
+
return return_value;
}
@@ -695,4 +700,4 @@ skip_optional_kwonly:
exit:
return return_value;
}
-/*[clinic end generated code: output=73b39e550e4e336c input=a9049054013a1b77]*/
+/*[clinic end generated code: output=32b9e6ced80d3fb0 input=a9049054013a1b77]*/
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 66d7fc7..2671792 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -1054,19 +1054,20 @@ set_update_internal(PySetObject *so, PyObject *other)
/*[clinic input]
set.update
so: setobject
- *others as args: object
+ *others: array
Update the set, adding elements from all others.
[clinic start generated code]*/
static PyObject *
-set_update_impl(PySetObject *so, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=050e2a21f8d7d16a input=df4fe486e38cd337]*/
+set_update_impl(PySetObject *so, PyObject * const *others,
+ Py_ssize_t others_length)
+/*[clinic end generated code: output=017c781c992d5c23 input=ed5d78885b076636]*/
{
Py_ssize_t i;
- for (i = 0; i < nargs; i++) {
- PyObject *other = args[i];
+ for (i = 0; i < others_length; i++) {
+ PyObject *other = others[i];
if (set_update_internal(so, other))
return NULL;
}
@@ -1283,14 +1284,15 @@ set_clear_impl(PySetObject *so)
/*[clinic input]
set.union
so: setobject
- *others as args: object
+ *others: array
Return a new set with elements from the set and all others.
[clinic start generated code]*/
static PyObject *
-set_union_impl(PySetObject *so, Py_ssize_t nargs, PyObject *const *args)
-/*[clinic end generated code: output=f68ec24d5c19d404 input=ddf088706e9577b2]*/
+set_union_impl(PySetObject *so, PyObject * const *others,
+ Py_ssize_t others_length)
+/*[clinic end generated code: output=b1bfa3d74065f27e input=55a2e81db6347a4f]*/
{
PySetObject *result;
PyObject *other;
@@ -1300,8 +1302,8 @@ set_union_impl(PySetObject *so, Py_ssize_t nargs, PyObject *const *args)
if (result == NULL)
return NULL;
- for (i = 0; i < nargs; i++) {
- other = args[i];
+ for (i = 0; i < others_length; i++) {
+ other = others[i];
if ((PyObject *)so == other)
continue;
if (set_update_local(result, other)) {
@@ -1434,25 +1436,25 @@ set_intersection(PySetObject *so, PyObject *other)
/*[clinic input]
set.intersection as set_intersection_multi
so: setobject
- *others as args: object
+ *others: array
Return a new set with elements common to the set and all others.
[clinic start generated code]*/
static PyObject *
-set_intersection_multi_impl(PySetObject *so, Py_ssize_t nargs,
- PyObject *const *args)
-/*[clinic end generated code: output=ef0756ddb5f2dee9 input=0d9f3805ccbba6a4]*/
+set_intersection_multi_impl(PySetObject *so, PyObject * const *others,
+ Py_ssize_t others_length)
+/*[clinic end generated code: output=db9ff9f875132b6b input=36c7b615694cadae]*/
{
Py_ssize_t i;
- if (nargs == 0) {
+ if (others_length == 0) {
return set_copy(so, NULL);
}
PyObject *result = Py_NewRef(so);
- for (i = 0; i < nargs; i++) {
- PyObject *other = args[i];
+ for (i = 0; i < others_length; i++) {
+ PyObject *other = others[i];
PyObject *newresult;
Py_BEGIN_CRITICAL_SECTION2(result, other);
newresult = set_intersection((PySetObject *)result, other);
@@ -1482,19 +1484,19 @@ set_intersection_update(PySetObject *so, PyObject *other)
/*[clinic input]
set.intersection_update as set_intersection_update_multi
so: setobject
- *others as args: object
+ *others: array
Update the set, keeping only elements found in it and all others.
[clinic start generated code]*/
static PyObject *
-set_intersection_update_multi_impl(PySetObject *so, Py_ssize_t nargs,
- PyObject *const *args)
-/*[clinic end generated code: output=808d7ad1935b1dfe input=223c1e086aa669a9]*/
+set_intersection_update_multi_impl(PySetObject *so, PyObject * const *others,
+ Py_ssize_t others_length)
+/*[clinic end generated code: output=d768b5584675b48d input=782e422fc370e4fc]*/
{
PyObject *tmp;
- tmp = set_intersection_multi_impl(so, nargs, args);
+ tmp = set_intersection_multi_impl(so, others, others_length);
if (tmp == NULL)
return NULL;
Py_BEGIN_CRITICAL_SECTION(so);
@@ -1672,20 +1674,20 @@ set_difference_update_internal(PySetObject *so, PyObject *other)
/*[clinic input]
set.difference_update
so: setobject
- *others as args: object
+ *others: array
Update the set, removing elements found in others.
[clinic start generated code]*/
static PyObject *
-set_difference_update_impl(PySetObject *so, Py_ssize_t nargs,
- PyObject *const *args)
-/*[clinic end generated code: output=55f850c27748d312 input=024e6baa6fbcbb3d]*/
+set_difference_update_impl(PySetObject *so, PyObject * const *others,
+ Py_ssize_t others_length)
+/*[clinic end generated code: output=04a22179b322cfe6 input=93ac28ba5b233696]*/
{
Py_ssize_t i;
- for (i = 0; i < nargs; i++) {
- PyObject *other = args[i];
+ for (i = 0; i < others_length; i++) {
+ PyObject *other = others[i];
int rv;
Py_BEGIN_CRITICAL_SECTION2(so, other);
rv = set_difference_update_internal(so, other);
@@ -1790,32 +1792,32 @@ set_difference(PySetObject *so, PyObject *other)
/*[clinic input]
set.difference as set_difference_multi
so: setobject
- *others as args: object
+ *others: array
Return a new set with elements in the set that are not in the others.
[clinic start generated code]*/
static PyObject *
-set_difference_multi_impl(PySetObject *so, Py_ssize_t nargs,
- PyObject *const *args)
-/*[clinic end generated code: output=8150d008c00523f3 input=ba78ea5f099e58df]*/
+set_difference_multi_impl(PySetObject *so, PyObject * const *others,
+ Py_ssize_t others_length)
+/*[clinic end generated code: output=b0d33fb05d5477a7 input=c1eb448d483416ad]*/
{
Py_ssize_t i;
PyObject *result, *other;
- if (nargs == 0) {
+ if (others_length == 0) {
return set_copy(so, NULL);
}
- other = args[0];
+ other = others[0];
Py_BEGIN_CRITICAL_SECTION2(so, other);
result = set_difference(so, other);
Py_END_CRITICAL_SECTION2();
if (result == NULL)
return NULL;
- for (i = 1; i < nargs; i++) {
- other = args[i];
+ for (i = 1; i < others_length; i++) {
+ other = others[i];
int rv;
Py_BEGIN_CRITICAL_SECTION(other);
rv = set_difference_update_internal((PySetObject *)result, other);
diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h
index f75a8d4..b472796 100644
--- a/Python/clinic/bltinmodule.c.h
+++ b/Python/clinic/bltinmodule.c.h
@@ -7,6 +7,7 @@ preserve
# include "pycore_runtime.h" // _Py_ID()
#endif
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
+#include "pycore_tuple.h" // _PyTuple_FromArray()
PyDoc_STRVAR(builtin___import____doc__,
"__import__($module, /, name, globals=None, locals=None, fromlist=(),\n"
@@ -933,7 +934,8 @@ builtin_print(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[5];
+ PyObject *argsbuf[4];
+ PyObject * const *fastargs;
Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
PyObject *__clinic_args = NULL;
PyObject *sep = Py_None;
@@ -941,41 +943,46 @@ builtin_print(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec
PyObject *file = Py_None;
int flush = 0;
- args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf);
- if (!args) {
+ fastargs = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf);
+ if (!fastargs) {
goto exit;
}
- __clinic_args = args[0];
if (!noptargs) {
goto skip_optional_kwonly;
}
- if (args[1]) {
- sep = args[1];
+ if (fastargs[0]) {
+ sep = fastargs[0];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
- if (args[2]) {
- end = args[2];
+ if (fastargs[1]) {
+ end = fastargs[1];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
- if (args[3]) {
- file = args[3];
+ if (fastargs[2]) {
+ file = fastargs[2];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
- flush = PyObject_IsTrue(args[4]);
+ flush = PyObject_IsTrue(fastargs[3]);
if (flush < 0) {
goto exit;
}
skip_optional_kwonly:
+ __clinic_args = _PyTuple_FromArray(args, nargs);
+ if (__clinic_args == NULL) {
+ goto exit;
+ }
return_value = builtin_print_impl(module, __clinic_args, sep, end, file, flush);
exit:
+ /* Cleanup for args */
Py_XDECREF(__clinic_args);
+
return return_value;
}
@@ -1228,4 +1235,4 @@ builtin_issubclass(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
exit:
return return_value;
}
-/*[clinic end generated code: output=435d3f286a863c49 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=76b27cf4164f257e input=a9049054013a1b77]*/
diff --git a/Python/getargs.c b/Python/getargs.c
index a764343..d529994 100644
--- a/Python/getargs.c
+++ b/Python/getargs.c
@@ -2308,13 +2308,11 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords,
}
-#undef _PyArg_UnpackKeywords
-
PyObject * const *
-_PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
+_PyArg_UnpackKeywordsEx(PyObject *const *args, Py_ssize_t nargs,
PyObject *kwargs, PyObject *kwnames,
struct _PyArg_Parser *parser,
- int minpos, int maxpos, int minkw,
+ int minpos, int maxpos, int minkw, int varpos,
PyObject **buf)
{
PyObject *kwtuple;
@@ -2360,11 +2358,11 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
else {
nkwargs = 0;
}
- if (nkwargs == 0 && minkw == 0 && minpos <= nargs && nargs <= maxpos) {
+ if (nkwargs == 0 && minkw == 0 && minpos <= nargs && (varpos || nargs <= maxpos)) {
/* Fast path. */
return args;
}
- if (nargs + nkwargs > maxargs) {
+ if (!varpos && nargs + nkwargs > maxargs) {
/* Adding "keyword" (when nargs == 0) prevents producing wrong error
messages in some special cases (see bpo-31229). */
PyErr_Format(PyExc_TypeError,
@@ -2377,7 +2375,7 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
nargs + nkwargs);
return NULL;
}
- if (nargs > maxpos) {
+ if (!varpos && nargs > maxpos) {
if (maxpos == 0) {
PyErr_Format(PyExc_TypeError,
"%.200s%s takes no positional arguments",
@@ -2402,13 +2400,16 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
" (%zd given)",
(parser->fname == NULL) ? "function" : parser->fname,
(parser->fname == NULL) ? "" : "()",
- minposonly < maxpos ? "at least" : "exactly",
+ (varpos || minposonly < maxpos) ? "at least" : "exactly",
minposonly,
minposonly == 1 ? "" : "s",
nargs);
return NULL;
}
+ if (varpos) {
+ nargs = Py_MIN(maxpos, nargs);
+ }
/* copy tuple args */
for (i = 0; i < nargs; i++) {
buf[i] = args[i];
@@ -2486,157 +2487,6 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
return buf;
}
-PyObject * const *
-_PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs,
- PyObject *kwargs, PyObject *kwnames,
- struct _PyArg_Parser *parser,
- int minpos, int maxpos, int minkw,
- int vararg, PyObject **buf)
-{
- PyObject *kwtuple;
- PyObject *keyword;
- Py_ssize_t varargssize = 0;
- int i, posonly, minposonly, maxargs;
- int reqlimit = minkw ? maxpos + minkw : minpos;
- Py_ssize_t nkwargs;
- PyObject * const *kwstack = NULL;
-
- assert(kwargs == NULL || PyDict_Check(kwargs));
- assert(kwargs == NULL || kwnames == NULL);
-
- if (parser == NULL) {
- PyErr_BadInternalCall();
- return NULL;
- }
-
- if (kwnames != NULL && !PyTuple_Check(kwnames)) {
- PyErr_BadInternalCall();
- return NULL;
- }
-
- if (args == NULL && nargs == 0) {
- args = buf;
- }
-
- if (parser_init(parser) < 0) {
- return NULL;
- }
-
- kwtuple = parser->kwtuple;
- posonly = parser->pos;
- minposonly = Py_MIN(posonly, minpos);
- maxargs = posonly + (int)PyTuple_GET_SIZE(kwtuple);
- if (kwargs != NULL) {
- nkwargs = PyDict_GET_SIZE(kwargs);
- }
- else if (kwnames != NULL) {
- nkwargs = PyTuple_GET_SIZE(kwnames);
- kwstack = args + nargs;
- }
- else {
- nkwargs = 0;
- }
- if (nargs < minposonly) {
- PyErr_Format(PyExc_TypeError,
- "%.200s%s takes %s %d positional argument%s"
- " (%zd given)",
- (parser->fname == NULL) ? "function" : parser->fname,
- (parser->fname == NULL) ? "" : "()",
- minposonly < maxpos ? "at least" : "exactly",
- minposonly,
- minposonly == 1 ? "" : "s",
- nargs);
- return NULL;
- }
-
- /* create varargs tuple */
- varargssize = nargs - maxpos;
- if (varargssize < 0) {
- varargssize = 0;
- }
- buf[vararg] = PyTuple_New(varargssize);
- if (!buf[vararg]) {
- return NULL;
- }
-
- /* copy tuple args */
- for (i = 0; i < nargs; i++) {
- if (i >= vararg) {
- PyTuple_SET_ITEM(buf[vararg], i - vararg, Py_NewRef(args[i]));
- continue;
- }
- else {
- buf[i] = args[i];
- }
- }
-
- /* copy keyword args using kwtuple to drive process */
- for (i = Py_MAX((int)nargs, posonly) - Py_SAFE_DOWNCAST(varargssize, Py_ssize_t, int); i < maxargs; i++) {
- PyObject *current_arg;
- if (nkwargs) {
- keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);
- if (kwargs != NULL) {
- if (PyDict_GetItemRef(kwargs, keyword, &current_arg) < 0) {
- goto exit;
- }
- }
- else {
- current_arg = find_keyword(kwnames, kwstack, keyword);
- }
- }
- else {
- current_arg = NULL;
- }
-
- /* If an arguments is passed in as a keyword argument,
- * it should be placed before `buf[vararg]`.
- *
- * For example:
- * def f(a, /, b, *args):
- * pass
- * f(1, b=2)
- *
- * This `buf` array should be: [1, 2, NULL].
- * In this case, nargs < vararg.
- *
- * Otherwise, we leave a place at `buf[vararg]` for vararg tuple
- * so the index is `i + 1`. */
- if (i < vararg) {
- buf[i] = current_arg;
- }
- else {
- buf[i + 1] = current_arg;
- }
-
- if (current_arg) {
- Py_DECREF(current_arg);
- --nkwargs;
- }
- else if (i < minpos || (maxpos <= i && i < reqlimit)) {
- /* Less arguments than required */
- keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);
- PyErr_Format(PyExc_TypeError, "%.200s%s missing required "
- "argument '%U' (pos %d)",
- (parser->fname == NULL) ? "function" : parser->fname,
- (parser->fname == NULL) ? "" : "()",
- keyword, i+1);
- goto exit;
- }
- }
-
- if (nkwargs > 0) {
- error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname);
- goto exit;
- }
-
- return buf;
-
-exit:
- Py_XDECREF(buf[vararg]);
- return NULL;
-}
-
-
static const char *
skipitem(const char **p_format, va_list *p_va, int flags)
{
diff --git a/Tools/c-analyzer/c_parser/parser/__init__.py b/Tools/c-analyzer/c_parser/parser/__init__.py
index 4227e93..ff4f303 100644
--- a/Tools/c-analyzer/c_parser/parser/__init__.py
+++ b/Tools/c-analyzer/c_parser/parser/__init__.py
@@ -164,7 +164,7 @@ def _parse(srclines, anon_name, **srckwargs):
# We use defaults that cover most files. Files with bigger declarations
# are covered elsewhere (MAX_SIZES in cpython/_parser.py).
-def _iter_source(lines, *, maxtext=10_000, maxlines=200, showtext=False):
+def _iter_source(lines, *, maxtext=11_000, maxlines=200, showtext=False):
maxtext = maxtext if maxtext and maxtext > 0 else None
maxlines = maxlines if maxlines and maxlines > 0 else None
filestack = []
diff --git a/Tools/clinic/libclinic/clanguage.py b/Tools/clinic/libclinic/clanguage.py
index 32aba81..32d2c04 100644
--- a/Tools/clinic/libclinic/clanguage.py
+++ b/Tools/clinic/libclinic/clanguage.py
@@ -15,7 +15,7 @@ from libclinic.function import (
Module, Class, Function, Parameter,
permute_optional_groups,
GETTER, SETTER, METHOD_INIT)
-from libclinic.converters import defining_class_converter, self_converter
+from libclinic.converters import self_converter
from libclinic.parse_args import ParseArgsCodeGen
if TYPE_CHECKING:
from libclinic.app import Clinic
@@ -396,12 +396,6 @@ class CLanguage(Language):
first_optional = len(selfless)
positional = selfless and selfless[-1].is_positional_only()
has_option_groups = False
- requires_defining_class = (len(selfless)
- and isinstance(selfless[0].converter,
- defining_class_converter))
- pass_vararg_directly = (all(p.is_positional_only() or p.is_vararg()
- for p in selfless)
- and not requires_defining_class)
# offset i by -1 because first_optional needs to ignore self
for i, p in enumerate(parameters, -1):
@@ -410,9 +404,6 @@ class CLanguage(Language):
if (i != -1) and (p.default is not unspecified):
first_optional = min(first_optional, i)
- if p.is_vararg() and not pass_vararg_directly:
- data.cleanup.append(f"Py_XDECREF({c.parser_name});")
-
# insert group variable
group = p.group
if last_group != group:
@@ -424,11 +415,6 @@ class CLanguage(Language):
data.impl_parameters.append("int " + group_name)
has_option_groups = True
- if p.is_vararg() and pass_vararg_directly:
- data.impl_arguments.append('nvararg')
- data.impl_parameters.append('Py_ssize_t nargs')
- p.converter.type = 'PyObject *const *'
-
c.render(p, data)
if has_option_groups and (not positional):
diff --git a/Tools/clinic/libclinic/converter.py b/Tools/clinic/libclinic/converter.py
index 86853bb..2c93dda 100644
--- a/Tools/clinic/libclinic/converter.py
+++ b/Tools/clinic/libclinic/converter.py
@@ -312,7 +312,7 @@ class CConverter(metaclass=CConverterAutoRegister):
def length_name(self) -> str:
"""Computes the name of the associated "length" variable."""
assert self.length is not None
- return self.parser_name + "_length"
+ return self.name + "_length"
# Why is this one broken out separately?
# For "positional-only" function parsing,
diff --git a/Tools/clinic/libclinic/converters.py b/Tools/clinic/libclinic/converters.py
index bd5c2a2..2d103c9 100644
--- a/Tools/clinic/libclinic/converters.py
+++ b/Tools/clinic/libclinic/converters.py
@@ -1228,3 +1228,30 @@ class self_converter(CConverter):
type_object = cls.type_object
type_ptr = f'PyTypeObject *base_tp = {type_object};'
template_dict['base_type_ptr'] = type_ptr
+
+
+# Converters for var-positional parameter.
+
+class varpos_tuple_converter(CConverter):
+ type = 'PyObject *'
+ format_unit = ''
+ c_default = 'NULL'
+
+ def cleanup(self) -> str:
+ return f"""Py_XDECREF({self.parser_name});\n"""
+
+ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
+ raise AssertionError('should never be called')
+
+class varpos_array_converter(CConverter):
+ type = 'PyObject * const *'
+ format_unit = ''
+ length = True
+ c_ignored_default = ''
+
+ def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
+ raise AssertionError('should never be called')
+
+# XXX: temporary
+class varpos_object_converter(varpos_tuple_converter):
+ pass
diff --git a/Tools/clinic/libclinic/dsl_parser.py b/Tools/clinic/libclinic/dsl_parser.py
index 5ca3bd5..4b4a8b9 100644
--- a/Tools/clinic/libclinic/dsl_parser.py
+++ b/Tools/clinic/libclinic/dsl_parser.py
@@ -925,16 +925,17 @@ class DSLParser:
parameter_name = parameter.arg
name, legacy, kwargs = self.parse_converter(parameter.annotation)
+ if is_vararg:
+ name = 'varpos_' + name
value: object
if not default:
- if self.parameter_state is ParamState.OPTIONAL:
- fail(f"Can't have a parameter without a default ({parameter_name!r}) "
- "after a parameter with a default!")
if is_vararg:
value = NULL
- kwargs.setdefault('c_default', "NULL")
else:
+ if self.parameter_state is ParamState.OPTIONAL:
+ fail(f"Can't have a parameter without a default ({parameter_name!r}) "
+ "after a parameter with a default!")
value = unspecified
if 'py_default' in kwargs:
fail("You can't specify py_default without specifying a default value!")
diff --git a/Tools/clinic/libclinic/parse_args.py b/Tools/clinic/libclinic/parse_args.py
index 559d4fb..2ce4e75 100644
--- a/Tools/clinic/libclinic/parse_args.py
+++ b/Tools/clinic/libclinic/parse_args.py
@@ -217,8 +217,7 @@ class ParseArgsCodeGen:
min_pos: int = 0
max_pos: int = 0
min_kw_only: int = 0
- pseudo_args: int = 0
- vararg: int | str = NO_VARARG
+ varpos: Parameter | None = None
docstring_prototype: str
docstring_definition: str
@@ -246,6 +245,13 @@ class ParseArgsCodeGen:
if self.parameters and isinstance(self.parameters[0].converter, defining_class_converter):
self.requires_defining_class = True
del self.parameters[0]
+
+ for i, p in enumerate(self.parameters):
+ if p.is_vararg():
+ self.varpos = p
+ del self.parameters[i]
+ break
+
self.converters = [p.converter for p in self.parameters]
if self.func.critical_section:
@@ -257,18 +263,13 @@ class ParseArgsCodeGen:
self.min_pos = 0
self.max_pos = 0
self.min_kw_only = 0
- self.pseudo_args = 0
for i, p in enumerate(self.parameters, 1):
if p.is_keyword_only():
assert not p.is_positional_only()
if not p.is_optional():
- self.min_kw_only = i - self.max_pos - int(self.vararg != NO_VARARG)
- elif p.is_vararg():
- self.pseudo_args += 1
- self.vararg = i - 1
+ self.min_kw_only = i - self.max_pos
else:
- if self.vararg == NO_VARARG:
- self.max_pos = i
+ self.max_pos = i
if p.is_positional_only():
self.pos_only = i
if not p.is_optional():
@@ -285,6 +286,7 @@ class ParseArgsCodeGen:
return (len(self.parameters) == 1
and self.parameters[0].is_positional_only()
and not self.converters[0].is_optional()
+ and not self.varpos
and not self.requires_defining_class
and not self.is_new_or_init())
@@ -315,7 +317,8 @@ class ParseArgsCodeGen:
def init_limited_capi(self) -> None:
self.limited_capi = self.codegen.limited_capi
- if self.limited_capi and (self.pseudo_args or
+ if self.limited_capi and (
+ (self.varpos and self.pos_only < len(self.parameters)) or
(any(p.is_optional() for p in self.parameters) and
any(p.is_keyword_only() and not p.is_optional() for p in self.parameters)) or
any(c.broken_limited_capi for c in self.converters)):
@@ -447,6 +450,74 @@ class ParseArgsCodeGen:
parser_code = ' {option_group_parsing}'
self.parser_body(parser_code)
+ def _parse_vararg(self) -> str:
+ assert self.varpos is not None
+ paramname = self.varpos.converter.parser_name
+ if self.varpos.converter.length:
+ if not self.fastcall:
+ self.codegen.add_include('pycore_tuple.h',
+ '_PyTuple_ITEMS()')
+ start = 'args' if self.fastcall else '_PyTuple_ITEMS(args)'
+ size = 'nargs' if self.fastcall else 'PyTuple_GET_SIZE(args)'
+ if self.max_pos:
+ if min(self.pos_only, self.min_pos) < self.max_pos:
+ start = f'{size} > {self.max_pos} ? {start} + {self.max_pos} : {start}'
+ size = f'Py_MAX(0, {size} - {self.max_pos})'
+ else:
+ start = f'{start} + {self.max_pos}'
+ size = f'{size} - {self.max_pos}'
+ return f"""
+ {paramname} = {start};
+ {self.varpos.converter.length_name} = {size};
+ """
+
+ if self.fastcall:
+ if self.limited_capi:
+ if min(self.pos_only, self.min_pos) < self.max_pos:
+ size = f'Py_MAX(nargs - {self.max_pos}, 0)'
+ else:
+ size = f'nargs - {self.max_pos}' if self.max_pos else 'nargs'
+ return f"""
+ {paramname} = PyTuple_New({size});
+ if (!{paramname}) {{{{
+ goto exit;
+ }}}}
+ for (Py_ssize_t i = {self.max_pos}; i < nargs; ++i) {{{{
+ PyTuple_SET_ITEM({paramname}, i - {self.max_pos}, Py_NewRef(args[i]));
+ }}}}
+ """
+ else:
+ self.codegen.add_include('pycore_tuple.h',
+ '_PyTuple_FromArray()')
+ if min(self.pos_only, self.min_pos) < self.max_pos:
+ return f"""
+ {paramname} = nargs > {self.max_pos}
+ ? _PyTuple_FromArray(args + {self.max_pos}, nargs - {self.max_pos})
+ : PyTuple_New(0);
+ if ({paramname} == NULL) {{{{
+ goto exit;
+ }}}}
+ """
+ else:
+ start = f'args + {self.max_pos}' if self.max_pos else 'args'
+ size = f'nargs - {self.max_pos}' if self.max_pos else 'nargs'
+ return f"""
+ {paramname} = _PyTuple_FromArray({start}, {size});
+ if ({paramname} == NULL) {{{{
+ goto exit;
+ }}}}
+ """
+ else:
+ if self.max_pos:
+ return f"""
+ {paramname} = PyTuple_GetSlice(args, {self.max_pos}, PY_SSIZE_T_MAX);
+ if (!{paramname}) {{{{
+ goto exit;
+ }}}}
+ """
+ else:
+ return f"{paramname} = Py_NewRef(args);\n"
+
def parse_pos_only(self) -> None:
if self.fastcall:
# positional-only, but no option groups
@@ -469,14 +540,9 @@ class ParseArgsCodeGen:
nargs = 'PyTuple_GET_SIZE(args)'
argname_fmt = 'PyTuple_GET_ITEM(args, %d)'
- if self.vararg != NO_VARARG:
- self.declarations = f"Py_ssize_t nvararg = {nargs} - {self.max_pos};"
- else:
- self.declarations = ""
-
- max_args = NO_VARARG if (self.vararg != NO_VARARG) else self.max_pos
+ parser_code = []
+ max_args = NO_VARARG if self.varpos else self.max_pos
if self.limited_capi:
- parser_code = []
if nargs != 'nargs':
nargs_def = f'Py_ssize_t nargs = {nargs};'
parser_code.append(libclinic.normalize_snippet(nargs_def, indent=4))
@@ -509,33 +575,27 @@ class ParseArgsCodeGen:
}}}}
""",
indent=4))
- else:
+ elif self.min_pos or max_args != NO_VARARG:
self.codegen.add_include('pycore_modsupport.h',
'_PyArg_CheckPositional()')
- parser_code = [libclinic.normalize_snippet(f"""
+ parser_code.append(libclinic.normalize_snippet(f"""
if (!_PyArg_CheckPositional("{{name}}", {nargs}, {self.min_pos}, {max_args})) {{{{
goto exit;
}}}}
- """, indent=4)]
+ """, indent=4))
has_optional = False
use_parser_code = True
for i, p in enumerate(self.parameters):
- if p.is_vararg():
- var = p.converter.parser_name
- if self.fastcall:
- code = f"{var} = args + {self.vararg};"
- else:
- code = f"{var} = _PyTuple_CAST(args)->ob_item;"
- formatted_code = libclinic.normalize_snippet(code, indent=4)
- parser_code.append(formatted_code)
- continue
-
displayname = p.get_displayname(i+1)
argname = argname_fmt % i
parsearg: str | None
parsearg = p.converter.parse_arg(argname, displayname, limited_capi=self.limited_capi)
if parsearg is None:
+ if self.varpos:
+ raise ValueError(
+ f"Using converter {p.converter} is not supported "
+ f"in function with var-positional parameter")
use_parser_code = False
parser_code = []
break
@@ -551,6 +611,8 @@ class ParseArgsCodeGen:
if use_parser_code:
if has_optional:
parser_code.append("skip_optional:")
+ if self.varpos:
+ parser_code.append(libclinic.normalize_snippet(self._parse_vararg(), indent=4))
else:
for parameter in self.parameters:
parameter.converter.use_converter()
@@ -575,7 +637,7 @@ class ParseArgsCodeGen:
goto exit;
}}
""", indent=4)]
- self.parser_body(*parser_code, declarations=self.declarations)
+ self.parser_body(*parser_code)
def parse_general(self, clang: CLanguage) -> None:
parsearg: str | None
@@ -589,7 +651,7 @@ class ParseArgsCodeGen:
has_optional_kw = (
max(self.pos_only, self.min_pos) + self.min_kw_only
- < len(self.converters) - int(self.vararg != NO_VARARG)
+ < len(self.converters)
)
use_parser_code = True
@@ -598,57 +660,53 @@ class ParseArgsCodeGen:
use_parser_code = False
self.fastcall = False
else:
- if self.vararg == NO_VARARG:
+ if not self.varpos:
self.codegen.add_include('pycore_modsupport.h',
'_PyArg_UnpackKeywords()')
- args_declaration = "_PyArg_UnpackKeywords", "%s, %s, %s" % (
- self.min_pos,
- self.max_pos,
- self.min_kw_only
- )
+ unpack_func = '_PyArg_UnpackKeywords'
nargs = "nargs"
else:
self.codegen.add_include('pycore_modsupport.h',
'_PyArg_UnpackKeywordsWithVararg()')
- args_declaration = "_PyArg_UnpackKeywordsWithVararg", "%s, %s, %s, %s" % (
- self.min_pos,
- self.max_pos,
- self.min_kw_only,
- self.vararg
- )
+ unpack_func = '_PyArg_UnpackKeywordsWithVararg'
nargs = f"Py_MIN(nargs, {self.max_pos})" if self.max_pos else "0"
if self.fastcall:
self.flags = "METH_FASTCALL|METH_KEYWORDS"
self.parser_prototype = PARSER_PROTOTYPE_FASTCALL_KEYWORDS
- argname_fmt = 'args[%d]'
self.declarations = declare_parser(self.func, codegen=self.codegen)
- self.declarations += "\nPyObject *argsbuf[%s];" % len(self.converters)
+ self.declarations += "\nPyObject *argsbuf[%s];" % (len(self.converters) or 1)
+ if self.varpos:
+ self.declarations += "\nPyObject * const *fastargs;"
+ argsname = 'fastargs'
+ argname_fmt = 'fastargs[%d]'
+ else:
+ argsname = 'args'
+ argname_fmt = 'args[%d]'
if has_optional_kw:
self.declarations += "\nPy_ssize_t noptargs = %s + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - %d;" % (nargs, self.min_pos + self.min_kw_only)
- parser_code = [libclinic.normalize_snippet("""
- args = %s(args, nargs, NULL, kwnames, &_parser, %s, argsbuf);
- if (!args) {{
- goto exit;
- }}
- """ % args_declaration, indent=4)]
+ unpack_args = 'args, nargs, NULL, kwnames'
else:
# positional-or-keyword arguments
self.flags = "METH_VARARGS|METH_KEYWORDS"
self.parser_prototype = PARSER_PROTOTYPE_KEYWORD
+ argsname = 'fastargs'
argname_fmt = 'fastargs[%d]'
self.declarations = declare_parser(self.func, codegen=self.codegen)
- self.declarations += "\nPyObject *argsbuf[%s];" % len(self.converters)
+ self.declarations += "\nPyObject *argsbuf[%s];" % (len(self.converters) or 1)
self.declarations += "\nPyObject * const *fastargs;"
self.declarations += "\nPy_ssize_t nargs = PyTuple_GET_SIZE(args);"
if has_optional_kw:
self.declarations += "\nPy_ssize_t noptargs = %s + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - %d;" % (nargs, self.min_pos + self.min_kw_only)
- parser_code = [libclinic.normalize_snippet("""
- fastargs = %s(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, %s, argsbuf);
- if (!fastargs) {{
- goto exit;
- }}
- """ % args_declaration, indent=4)]
+ unpack_args = '_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL'
+ unpack_args += (f', &_parser, {self.min_pos}, {self.max_pos}, '
+ f'{self.min_kw_only}, argsbuf')
+ parser_code = [libclinic.normalize_snippet(f"""
+ {argsname} = {unpack_func}({unpack_args});
+ if (!{argsname}) {{{{
+ goto exit;
+ }}}}
+ """, indent=4)]
if self.requires_defining_class:
self.flags = 'METH_METHOD|' + self.flags
@@ -697,8 +755,6 @@ class ParseArgsCodeGen:
else:
label = 'skip_optional_kwonly'
first_opt = self.max_pos + self.min_kw_only
- if self.vararg != NO_VARARG:
- first_opt += 1
if i == first_opt:
add_label = label
parser_code.append(libclinic.normalize_snippet("""
@@ -724,6 +780,8 @@ class ParseArgsCodeGen:
if use_parser_code:
if add_label:
parser_code.append("%s:" % add_label)
+ if self.varpos:
+ parser_code.append(libclinic.normalize_snippet(self._parse_vararg(), indent=4))
else:
for parameter in self.parameters:
parameter.converter.use_converter()
@@ -914,14 +972,14 @@ class ParseArgsCodeGen:
# previous call to parser_body. this is used for an awful hack.
self.parser_body_fields: tuple[str, ...] = ()
- if not self.parameters:
+ if not self.parameters and not self.varpos:
self.parse_no_args()
elif self.use_meth_o():
self.parse_one_arg()
elif self.has_option_groups():
self.parse_option_groups()
elif (not self.requires_defining_class
- and self.pos_only == len(self.parameters) - self.pseudo_args):
+ and self.pos_only == len(self.parameters)):
self.parse_pos_only()
else:
self.parse_general(clang)