mirror of https://github.com/python/cpython
gh-122943: Rework support of var-positional parameter in Argument Clinic (GH-122945)
Move creation of a tuple for var-positional parameter out of _PyArg_UnpackKeywordsWithVararg(). Merge _PyArg_UnpackKeywordsWithVararg() with _PyArg_UnpackKeywords(). Add a new parameter in _PyArg_UnpackKeywords(). The "parameters" and "converters" attributes of ParseArgsCodeGen no longer contain the var-positional parameter. It is now available as the "varpos" attribute. Optimize code generation for var-positional parameter and reuse the same generating code for functions with and without keyword parameters. Add special converters for var-positional parameter. "tuple" represents it as a Python tuple and "array" represents it as a continuous array of PyObject*. "object" is a temporary alias of "tuple".
This commit is contained in:
parent
09d6f5dc78
commit
1f777396f5
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -4144,6 +4144,45 @@ PyDoc_STRVAR(test_vararg_and_posonly__doc__,
|
|||
"--\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, 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__},
|
||||
|
||||
|
@ -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
|
||||
|
@ -4926,6 +4989,41 @@ PyDoc_STRVAR(Test___init____doc__,
|
|||
"\n"
|
||||
"Varargs init method. For example, nargs is translated to PyTuple_GET_SIZE.");
|
||||
|
||||
static int
|
||||
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 *__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 = 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);
|
||||
|
||||
|
@ -4941,19 +5039,16 @@ Test___init__(PyObject *self, PyObject *args, PyObject *kwargs)
|
|||
!_PyArg_NoKeywords("Test", kwargs)) {
|
||||
goto exit;
|
||||
}
|
||||
if (!_PyArg_CheckPositional("Test", PyTuple_GET_SIZE(args), 0, PY_SSIZE_T_MAX)) {
|
||||
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]
|
||||
|
@ -4970,6 +5065,40 @@ PyDoc_STRVAR(Test__doc__,
|
|||
"\n"
|
||||
"Varargs new method. For example, nargs is translated to PyTuple_GET_SIZE.");
|
||||
|
||||
static PyObject *
|
||||
Test_impl(PyTypeObject *type, PyObject *args);
|
||||
|
||||
static PyObject *
|
||||
Test(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
PyTypeObject *base_tp = TestType;
|
||||
PyObject *__clinic_args = NULL;
|
||||
|
||||
if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
|
||||
!_PyArg_NoKeywords("Test", kwargs)) {
|
||||
goto exit;
|
||||
}
|
||||
__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);
|
||||
|
||||
|
@ -4984,19 +5113,16 @@ Test(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
|||
!_PyArg_NoKeywords("Test", kwargs)) {
|
||||
goto exit;
|
||||
}
|
||||
if (!_PyArg_CheckPositional("Test", PyTuple_GET_SIZE(args), 0, PY_SSIZE_T_MAX)) {
|
||||
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]
|
||||
|
|
|
@ -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),))
|
||||
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))
|
||||
|
||||
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)))
|
||||
@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)))
|
||||
|
||||
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)
|
||||
@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)))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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]*/
|
||||
|
|
|
@ -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]*/
|
||||
|
|
|
@ -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]*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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]*/
|
||||
|
|
|
@ -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[1]) {
|
||||
bound = fastargs[1];
|
||||
if (!--noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
}
|
||||
if (fastargs[2]) {
|
||||
bound = fastargs[2];
|
||||
default_value = fastargs[2];
|
||||
if (!--noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
}
|
||||
if (fastargs[3]) {
|
||||
default_value = fastargs[3];
|
||||
if (!--noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
}
|
||||
if (fastargs[4]) {
|
||||
covariant = PyObject_IsTrue(fastargs[4]);
|
||||
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]*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]*/
|
||||
|
|
168
Python/getargs.c
168
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, ¤t_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)
|
||||
{
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!")
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue