Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

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

Provide feedback

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

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9af34c9

Browse files
authored
bpo-20201: variadic arguments support for AC (GH-18609)
Implement support for `*args` in AC, and port `print()` to use it.
1 parent7915c96 commit9af34c9

File tree

8 files changed

+664
-100
lines changed

8 files changed

+664
-100
lines changed

‎Include/modsupport.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ PyAPI_FUNC(PyObject *) Py_BuildValue(const char *, ...);
5050
PyAPI_FUNC(PyObject*)_Py_BuildValue_SizeT(constchar*, ...);
5151

5252

53+
#defineANY_VARARGS(n) (n == PY_SSIZE_T_MAX)
5354
#ifndefPy_LIMITED_API
5455
PyAPI_FUNC(int)_PyArg_UnpackStack(
5556
PyObject*const*args,
@@ -73,7 +74,7 @@ PyAPI_FUNC(void) _PyArg_BadArgument(const char *, const char *, const char *, Py
7374
PyAPI_FUNC(int)_PyArg_CheckPositional(constchar*,Py_ssize_t,
7475
Py_ssize_t,Py_ssize_t);
7576
#define_PyArg_CheckPositional(funcname,nargs,min,max) \
76-
(((min) <= (nargs) && (nargs) <= (max)) \
77+
((!ANY_VARARGS(max) &&(min) <= (nargs) && (nargs) <= (max)) \
7778
|| _PyArg_CheckPositional((funcname), (nargs), (min), (max)))
7879

7980
#endif
@@ -127,6 +128,14 @@ PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywords(
127128
struct_PyArg_Parser*parser,
128129
intminpos,intmaxpos,intminkw,
129130
PyObject**buf);
131+
132+
PyAPI_FUNC(PyObject*const*)_PyArg_UnpackKeywordsWithVararg(
133+
PyObject*const*args,Py_ssize_tnargs,
134+
PyObject*kwargs,PyObject*kwnames,
135+
struct_PyArg_Parser*parser,
136+
intminpos,intmaxpos,intminkw,
137+
intvararg,PyObject**buf);
138+
130139
#define_PyArg_UnpackKeywords(args,nargs,kwargs,kwnames,parser,minpos,maxpos,minkw,buf) \
131140
(((minkw) == 0 && (kwargs) == NULL && (kwnames) == NULL && \
132141
(minpos) <= (nargs) && (nargs) <= (maxpos) && args != NULL) ? (args) : \

‎Lib/test/clinic.test

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3304,3 +3304,223 @@ test_preprocessor_guarded_else(PyObject *module, PyObject *Py_UNUSED(ignored))
33043304
#define TEST_PREPROCESSOR_GUARDED_ELSE_METHODDEF
33053305
#endif /* !defined(TEST_PREPROCESSOR_GUARDED_ELSE_METHODDEF) */
33063306
/*[clinic end generated code: output=3804bb18d454038c input=3fc80c9989d2f2e1]*/
3307+
3308+
/*[clinic input]
3309+
test_vararg_and_posonly
3310+
3311+
3312+
a: object
3313+
*args: object
3314+
/
3315+
3316+
[clinic start generated code]*/
3317+
3318+
PyDoc_STRVAR(test_vararg_and_posonly__doc__,
3319+
"test_vararg_and_posonly($module, a, /, *args)\n"
3320+
"--\n"
3321+
"\n");
3322+
3323+
#define TEST_VARARG_AND_POSONLY_METHODDEF \
3324+
{"test_vararg_and_posonly", (PyCFunction)(void(*)(void))test_vararg_and_posonly, METH_FASTCALL, test_vararg_and_posonly__doc__},
3325+
3326+
static PyObject *
3327+
test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args);
3328+
3329+
static PyObject *
3330+
test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
3331+
{
3332+
PyObject *return_value = NULL;
3333+
PyObject *a;
3334+
PyObject *__clinic_args = NULL;
3335+
3336+
if (!_PyArg_CheckPositional("test_vararg_and_posonly", nargs, 1, PY_SSIZE_T_MAX)) {
3337+
goto exit;
3338+
}
3339+
a = args[0];
3340+
__clinic_args = PyTuple_New(nargs - 1);
3341+
for (Py_ssize_t i = 0; i < nargs - 1; ++i) {
3342+
PyTuple_SET_ITEM(__clinic_args, i, args[1 + i]);
3343+
}
3344+
return_value = test_vararg_and_posonly_impl(module, a, __clinic_args);
3345+
3346+
exit:
3347+
Py_XDECREF(__clinic_args);
3348+
return return_value;
3349+
}
3350+
3351+
static PyObject *
3352+
test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
3353+
/*[clinic end generated code: output=ada613d2d87c9341 input=08dc2bf7afbf1613]*/
3354+
3355+
/*[clinic input]
3356+
test_vararg
3357+
3358+
3359+
a: object
3360+
*args: object
3361+
3362+
[clinic start generated code]*/
3363+
3364+
PyDoc_STRVAR(test_vararg__doc__,
3365+
"test_vararg($module, /, a, *args)\n"
3366+
"--\n"
3367+
"\n");
3368+
3369+
#define TEST_VARARG_METHODDEF \
3370+
{"test_vararg", (PyCFunction)(void(*)(void))test_vararg, METH_FASTCALL|METH_KEYWORDS, test_vararg__doc__},
3371+
3372+
static PyObject *
3373+
test_vararg_impl(PyObject *module, PyObject *a, PyObject *args);
3374+
3375+
static PyObject *
3376+
test_vararg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
3377+
{
3378+
PyObject *return_value = NULL;
3379+
static const char * const _keywords[] = {"a", NULL};
3380+
static _PyArg_Parser _parser = {NULL, _keywords, "test_vararg", 0};
3381+
PyObject *argsbuf[2];
3382+
Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
3383+
PyObject *a;
3384+
PyObject *__clinic_args = NULL;
3385+
3386+
args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
3387+
if (!args) {
3388+
goto exit;
3389+
}
3390+
a = args[0];
3391+
__clinic_args = args[1];
3392+
return_value = test_vararg_impl(module, a, __clinic_args);
3393+
3394+
exit:
3395+
Py_XDECREF(__clinic_args);
3396+
return return_value;
3397+
}
3398+
3399+
static PyObject *
3400+
test_vararg_impl(PyObject *module, PyObject *a, PyObject *args)
3401+
/*[clinic end generated code: output=f721025731c3bfe8 input=81d33815ad1bae6e]*/
3402+
3403+
/*[clinic input]
3404+
test_vararg_with_default
3405+
3406+
3407+
a: object
3408+
*args: object
3409+
b: bool = False
3410+
3411+
[clinic start generated code]*/
3412+
3413+
PyDoc_STRVAR(test_vararg_with_default__doc__,
3414+
"test_vararg_with_default($module, /, a, *args, b=False)\n"
3415+
"--\n"
3416+
"\n");
3417+
3418+
#define TEST_VARARG_WITH_DEFAULT_METHODDEF \
3419+
{"test_vararg_with_default", (PyCFunction)(void(*)(void))test_vararg_with_default, METH_FASTCALL|METH_KEYWORDS, test_vararg_with_default__doc__},
3420+
3421+
static PyObject *
3422+
test_vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args,
3423+
int b);
3424+
3425+
static PyObject *
3426+
test_vararg_with_default(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
3427+
{
3428+
PyObject *return_value = NULL;
3429+
static const char * const _keywords[] = {"a", "b", NULL};
3430+
static _PyArg_Parser _parser = {NULL, _keywords, "test_vararg_with_default", 0};
3431+
PyObject *argsbuf[3];
3432+
Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
3433+
PyObject *a;
3434+
PyObject *__clinic_args = NULL;
3435+
int b = 0;
3436+
3437+
args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
3438+
if (!args) {
3439+
goto exit;
3440+
}
3441+
a = args[0];
3442+
__clinic_args = args[1];
3443+
if (!noptargs) {
3444+
goto skip_optional_kwonly;
3445+
}
3446+
b = PyObject_IsTrue(args[2]);
3447+
if (b < 0) {
3448+
goto exit;
3449+
}
3450+
skip_optional_kwonly:
3451+
return_value = test_vararg_with_default_impl(module, a, __clinic_args, b);
3452+
3453+
exit:
3454+
Py_XDECREF(__clinic_args);
3455+
return return_value;
3456+
}
3457+
3458+
static PyObject *
3459+
test_vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args,
3460+
int b)
3461+
/*[clinic end generated code: output=63b34d3241c52fda input=6e110b54acd9b22d]*/
3462+
3463+
/*[clinic input]
3464+
test_vararg_with_only_defaults
3465+
3466+
3467+
*args: object
3468+
b: bool = False
3469+
c: object = ' '
3470+
3471+
[clinic start generated code]*/
3472+
3473+
PyDoc_STRVAR(test_vararg_with_only_defaults__doc__,
3474+
"test_vararg_with_only_defaults($module, /, *args, b=False, c=\' \')\n"
3475+
"--\n"
3476+
"\n");
3477+
3478+
#define TEST_VARARG_WITH_ONLY_DEFAULTS_METHODDEF \
3479+
{"test_vararg_with_only_defaults", (PyCFunction)(void(*)(void))test_vararg_with_only_defaults, METH_FASTCALL|METH_KEYWORDS, test_vararg_with_only_defaults__doc__},
3480+
3481+
static PyObject *
3482+
test_vararg_with_only_defaults_impl(PyObject *module, PyObject *args, int b,
3483+
PyObject *c);
3484+
3485+
static PyObject *
3486+
test_vararg_with_only_defaults(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
3487+
{
3488+
PyObject *return_value = NULL;
3489+
static const char * const _keywords[] = {"b", "c", NULL};
3490+
static _PyArg_Parser _parser = {NULL, _keywords, "test_vararg_with_only_defaults", 0};
3491+
PyObject *argsbuf[3];
3492+
Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
3493+
PyObject *__clinic_args = NULL;
3494+
int b = 0;
3495+
PyObject *c = " ";
3496+
3497+
args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf);
3498+
if (!args) {
3499+
goto exit;
3500+
}
3501+
__clinic_args = args[0];
3502+
if (!noptargs) {
3503+
goto skip_optional_kwonly;
3504+
}
3505+
if (args[1]) {
3506+
b = PyObject_IsTrue(args[1]);
3507+
if (b < 0) {
3508+
goto exit;
3509+
}
3510+
if (!--noptargs) {
3511+
goto skip_optional_kwonly;
3512+
}
3513+
}
3514+
c = args[2];
3515+
skip_optional_kwonly:
3516+
return_value = test_vararg_with_only_defaults_impl(module, __clinic_args, b, c);
3517+
3518+
exit:
3519+
Py_XDECREF(__clinic_args);
3520+
return return_value;
3521+
}
3522+
3523+
static PyObject *
3524+
test_vararg_with_only_defaults_impl(PyObject *module, PyObject *args, int b,
3525+
PyObject *c)
3526+
/*[clinic end generated code: output=dc29ce6ebc2ec10c input=fa56a709a035666e]*/

‎Lib/test/test_call.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def test_varargs16_kw(self):
129129
min,0,default=1,key=2,foo=3)
130130

131131
deftest_varargs17_kw(self):
132-
msg=r"^print\(\) takes at most 4keywordarguments \(5 given\)$"
132+
msg=r"'foo' is an invalidkeywordargument for print\(\)$"
133133
self.assertRaisesRegex(TypeError,msg,
134134
print,0,sep=1,end=2,file=3,flush=4,foo=5)
135135

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added support for variadic positional parameters in Argument Clinic.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp