Skip to content

Commit b3a7915

Browse files
bpo-29464: Rename METH_FASTCALL to METH_FASTCALL|METH_KEYWORDS and make
the bare METH_FASTCALL be used for functions with positional-only parameters. Generated Argument Clinic code will be updated in the following commit.
1 parent aa0aa04 commit b3a7915

File tree

10 files changed

+49
-69
lines changed

10 files changed

+49
-69
lines changed

Include/methodobject.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ PyAPI_DATA(PyTypeObject) PyCFunction_Type;
1616
#define PyCFunction_Check(op) (Py_TYPE(op) == &PyCFunction_Type)
1717

1818
typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
19-
typedef PyObject *(*_PyCFunctionFast) (PyObject *self, PyObject **args,
20-
Py_ssize_t nargs, PyObject *kwnames);
19+
typedef PyObject *(*_PyCFunctionFast) (PyObject *, PyObject **, Py_ssize_t);
2120
typedef PyObject *(*PyCFunctionWithKeywords)(PyObject *, PyObject *,
2221
PyObject *);
22+
typedef PyObject *(*_PyCFunctionFastWithKeywords) (PyObject *,
23+
PyObject **, Py_ssize_t,
24+
PyObject *);
2325
typedef PyObject *(*PyNoArgsFunction)(PyObject *);
2426

2527
PyAPI_FUNC(PyCFunction) PyCFunction_GetFunction(PyObject *);

Modules/_collectionsmodule.c

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -912,14 +912,10 @@ _deque_rotate(dequeobject *deque, Py_ssize_t n)
912912
}
913913

914914
static PyObject *
915-
deque_rotate(dequeobject *deque, PyObject **args, Py_ssize_t nargs,
916-
PyObject *kwnames)
915+
deque_rotate(dequeobject *deque, PyObject **args, Py_ssize_t nargs)
917916
{
918917
Py_ssize_t n=1;
919918

920-
if (!_PyArg_NoStackKeywords("rotate", kwnames)) {
921-
return NULL;
922-
}
923919
if (!_PyArg_ParseStack(args, nargs, "|n:rotate", &n)) {
924920
return NULL;
925921
}
@@ -1052,8 +1048,7 @@ deque_len(dequeobject *deque)
10521048
}
10531049

10541050
static PyObject *
1055-
deque_index(dequeobject *deque, PyObject **args, Py_ssize_t nargs,
1056-
PyObject *kwnames)
1051+
deque_index(dequeobject *deque, PyObject **args, Py_ssize_t nargs)
10571052
{
10581053
Py_ssize_t i, n, start=0, stop=Py_SIZE(deque);
10591054
PyObject *v, *item;
@@ -1062,9 +1057,6 @@ deque_index(dequeobject *deque, PyObject **args, Py_ssize_t nargs,
10621057
size_t start_state = deque->state;
10631058
int cmp;
10641059

1065-
if (!_PyArg_NoStackKeywords("index", kwnames)) {
1066-
return NULL;
1067-
}
10681060
if (!_PyArg_ParseStack(args, nargs, "O|O&O&:index", &v,
10691061
_PyEval_SliceIndexNotNone, &start,
10701062
_PyEval_SliceIndexNotNone, &stop)) {
@@ -1133,17 +1125,13 @@ PyDoc_STRVAR(index_doc,
11331125
*/
11341126

11351127
static PyObject *
1136-
deque_insert(dequeobject *deque, PyObject **args, Py_ssize_t nargs,
1137-
PyObject *kwnames)
1128+
deque_insert(dequeobject *deque, PyObject **args, Py_ssize_t nargs)
11381129
{
11391130
Py_ssize_t index;
11401131
Py_ssize_t n = Py_SIZE(deque);
11411132
PyObject *value;
11421133
PyObject *rv;
11431134

1144-
if (!_PyArg_NoStackKeywords("insert", kwnames)) {
1145-
return NULL;
1146-
}
11471135
if (!_PyArg_ParseStack(args, nargs, "nO:insert", &index, &value)) {
11481136
return NULL;
11491137
}

Modules/_elementtree.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2774,7 +2774,7 @@ typedef struct {
27742774
} XMLParserObject;
27752775

27762776
static PyObject*
2777-
_elementtree_XMLParser_doctype(XMLParserObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames);
2777+
_elementtree_XMLParser_doctype(XMLParserObject *self, PyObject **args, Py_ssize_t nargs);
27782778
static PyObject *
27792779
_elementtree_XMLParser_doctype_impl(XMLParserObject *self, PyObject *name,
27802780
PyObject *pubid, PyObject *system);

Modules/_hashopenssl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,7 @@ generate_hash_name_list(void)
967967

968968
/* a PyMethodDef structure for the constructor */
969969
#define CONSTRUCTOR_METH_DEF(NAME) \
970-
{"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, METH_FASTCALL, \
970+
{"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, METH_FASTCALL | METH_KEYWORDS, \
971971
PyDoc_STR("Returns a " #NAME \
972972
" hash object; optionally initialized with a string") \
973973
}

Modules/_struct.c

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,15 +1817,12 @@ to the format string S.format. See help(struct) for more on format\n\
18171817
strings.");
18181818

18191819
static PyObject *
1820-
s_pack(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
1820+
s_pack(PyObject *self, PyObject **args, Py_ssize_t nargs)
18211821
{
18221822
PyStructObject *soself;
18231823
PyObject *result;
18241824

18251825
/* Validate arguments. */
1826-
if (!_PyArg_NoStackKeywords("pack", kwnames)) {
1827-
return NULL;
1828-
}
18291826
soself = (PyStructObject *)self;
18301827
assert(PyStruct_Check(self));
18311828
assert(soself->s_codes != NULL);
@@ -1859,16 +1856,13 @@ offset. Note that the offset is a required argument. See\n\
18591856
help(struct) for more on format strings.");
18601857

18611858
static PyObject *
1862-
s_pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
1859+
s_pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs)
18631860
{
18641861
PyStructObject *soself;
18651862
Py_buffer buffer;
18661863
Py_ssize_t offset;
18671864

18681865
/* Validate arguments. +1 is for the first arg as buffer. */
1869-
if (!_PyArg_NoStackKeywords("pack_into", kwnames)) {
1870-
return NULL;
1871-
}
18721866
soself = (PyStructObject *)self;
18731867
assert(PyStruct_Check(self));
18741868
assert(soself->s_codes != NULL);
@@ -2126,15 +2120,11 @@ Return a bytes object containing the values v1, v2, ... packed according\n\
21262120
to the format string. See help(struct) for more on format strings.");
21272121

21282122
static PyObject *
2129-
pack(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
2123+
pack(PyObject *self, PyObject **args, Py_ssize_t nargs)
21302124
{
21312125
PyObject *s_object = NULL;
21322126
PyObject *format, *result;
21332127

2134-
if (!_PyArg_NoStackKeywords("pack", kwnames)) {
2135-
return NULL;
2136-
}
2137-
21382128
if (nargs == 0) {
21392129
PyErr_SetString(PyExc_TypeError, "missing format argument");
21402130
return NULL;
@@ -2144,7 +2134,7 @@ pack(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
21442134
if (!cache_struct_converter(format, &s_object)) {
21452135
return NULL;
21462136
}
2147-
result = s_pack(s_object, args + 1, nargs - 1, kwnames);
2137+
result = s_pack(s_object, args + 1, nargs - 1);
21482138
Py_DECREF(s_object);
21492139
return result;
21502140
}
@@ -2158,15 +2148,11 @@ that the offset is a required argument. See help(struct) for more\n\
21582148
on format strings.");
21592149

21602150
static PyObject *
2161-
pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
2151+
pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs)
21622152
{
21632153
PyObject *s_object = NULL;
21642154
PyObject *format, *result;
21652155

2166-
if (!_PyArg_NoStackKeywords("pack_into", kwnames)) {
2167-
return NULL;
2168-
}
2169-
21702156
if (nargs == 0) {
21712157
PyErr_SetString(PyExc_TypeError, "missing format argument");
21722158
return NULL;
@@ -2176,7 +2162,7 @@ pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
21762162
if (!cache_struct_converter(format, &s_object)) {
21772163
return NULL;
21782164
}
2179-
result = s_pack_into(s_object, args + 1, nargs - 1, kwnames);
2165+
result = s_pack_into(s_object, args + 1, nargs - 1);
21802166
Py_DECREF(s_object);
21812167
return result;
21822168
}

Objects/call.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,10 +520,20 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg
520520
}
521521

522522
case METH_FASTCALL:
523+
{
524+
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
525+
goto no_keyword_error;
526+
}
527+
528+
result = (*(_PyCFunctionFast)meth) (self, args, nargs);
529+
break;
530+
}
531+
532+
case METH_FASTCALL | METH_KEYWORDS:
523533
{
524534
PyObject **stack;
525535
PyObject *kwnames;
526-
_PyCFunctionFast fastmeth = (_PyCFunctionFast)meth;
536+
_PyCFunctionFastWithKeywords fastmeth = (_PyCFunctionFastWithKeywords)meth;
527537

528538
if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) {
529539
goto exit;
@@ -631,8 +641,15 @@ _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, PyObject *
631641
break;
632642

633643
case METH_FASTCALL:
644+
if (nkwargs) {
645+
goto no_keyword_error;
646+
}
647+
result = ((_PyCFunctionFast)meth) (self, args, nargs);
648+
break;
649+
650+
case METH_FASTCALL | METH_KEYWORDS:
634651
/* Fast-path: avoid temporary dict to pass keyword arguments */
635-
result = ((_PyCFunctionFast)meth) (self, args, nargs, kwnames);
652+
result = ((_PyCFunctionFastWithKeywords)meth) (self, args, nargs, kwnames);
636653
break;
637654

638655
case METH_VARARGS:

Objects/dictobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,8 +2341,8 @@ dict_update_common(PyObject *self, PyObject *args, PyObject *kwds,
23412341
}
23422342

23432343
/* Note: dict.update() uses the METH_VARARGS|METH_KEYWORDS calling convention.
2344-
Using METH_FASTCALL would make dict.update(**dict2) calls slower, see the
2345-
issue #29312. */
2344+
Using METH_FASTCALL|METH_KEYWORDS would make dict.update(**dict2) calls
2345+
slower, see the issue #29312. */
23462346
static PyObject *
23472347
dict_update(PyObject *self, PyObject *args, PyObject *kwds)
23482348
{

Objects/typeobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3340,7 +3340,7 @@ static PyMethodDef type_methods[] = {
33403340
TYPE_MRO_METHODDEF
33413341
TYPE___SUBCLASSES___METHODDEF
33423342
{"__prepare__", (PyCFunction)type_prepare,
3343-
METH_FASTCALL | METH_CLASS,
3343+
METH_FASTCALL | METH_KEYWORDS | METH_CLASS,
33443344
PyDoc_STR("__prepare__() -> dict\n"
33453345
"used to create the namespace for the class statement")},
33463346
TYPE___INSTANCECHECK___METHODDEF

Python/bltinmodule.c

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -991,16 +991,11 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
991991

992992
/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
993993
static PyObject *
994-
builtin_getattr(PyObject *self, PyObject **args, Py_ssize_t nargs,
995-
PyObject *kwnames)
994+
builtin_getattr(PyObject *self, PyObject **args, Py_ssize_t nargs)
996995
{
997996
PyObject *v, *result, *dflt = NULL;
998997
PyObject *name;
999998

1000-
if (!_PyArg_NoStackKeywords("getattr", kwnames)) {
1001-
return NULL;
1002-
}
1003-
1004999
if (!_PyArg_UnpackStack(args, nargs, "getattr", 2, 3, &v, &name, &dflt))
10051000
return NULL;
10061001

@@ -1301,16 +1296,11 @@ PyTypeObject PyMap_Type = {
13011296

13021297
/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
13031298
static PyObject *
1304-
builtin_next(PyObject *self, PyObject **args, Py_ssize_t nargs,
1305-
PyObject *kwnames)
1299+
builtin_next(PyObject *self, PyObject **args, Py_ssize_t nargs)
13061300
{
13071301
PyObject *it, *res;
13081302
PyObject *def = NULL;
13091303

1310-
if (!_PyArg_NoStackKeywords("next", kwnames)) {
1311-
return NULL;
1312-
}
1313-
13141304
if (!_PyArg_UnpackStack(args, nargs, "next", 1, 2, &it, &def))
13151305
return NULL;
13161306

@@ -2130,7 +2120,7 @@ PyDoc_STRVAR(builtin_sorted__doc__,
21302120
"reverse flag can be set to request the result in descending order.");
21312121

21322122
#define BUILTIN_SORTED_METHODDEF \
2133-
{"sorted", (PyCFunction)builtin_sorted, METH_FASTCALL, builtin_sorted__doc__},
2123+
{"sorted", (PyCFunction)builtin_sorted, METH_FASTCALL | METH_KEYWORDS, builtin_sorted__doc__},
21342124

21352125
static PyObject *
21362126
builtin_sorted(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
@@ -2622,7 +2612,7 @@ PyTypeObject PyZip_Type = {
26222612

26232613
static PyMethodDef builtin_methods[] = {
26242614
{"__build_class__", (PyCFunction)builtin___build_class__,
2625-
METH_FASTCALL, build_class_doc},
2615+
METH_FASTCALL | METH_KEYWORDS, build_class_doc},
26262616
{"__import__", (PyCFunction)builtin___import__, METH_VARARGS | METH_KEYWORDS, import_doc},
26272617
BUILTIN_ABS_METHODDEF
26282618
BUILTIN_ALL_METHODDEF
@@ -2656,7 +2646,7 @@ static PyMethodDef builtin_methods[] = {
26562646
BUILTIN_OCT_METHODDEF
26572647
BUILTIN_ORD_METHODDEF
26582648
BUILTIN_POW_METHODDEF
2659-
{"print", (PyCFunction)builtin_print, METH_FASTCALL, print_doc},
2649+
{"print", (PyCFunction)builtin_print, METH_FASTCALL | METH_KEYWORDS, print_doc},
26602650
BUILTIN_REPR_METHODDEF
26612651
{"round", (PyCFunction)builtin_round, METH_VARARGS | METH_KEYWORDS, round_doc},
26622652
BUILTIN_SETATTR_METHODDEF

Tools/clinic/clinic.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,11 @@ def output_templates(self, f):
709709
""")
710710

711711
parser_prototype_fastcall = normalize_snippet("""
712+
static PyObject *
713+
{c_basename}({self_type}{self_name}, PyObject **args, Py_ssize_t nargs)
714+
""")
715+
716+
parser_prototype_fastcall_keywords = normalize_snippet("""
712717
static PyObject *
713718
{c_basename}({self_type}{self_name}, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
714719
""")
@@ -828,10 +833,6 @@ def insert_keywords(s):
828833
parser_prototype = parser_prototype_fastcall
829834

830835
parser_definition = parser_body(parser_prototype, normalize_snippet("""
831-
if ({self_type_check}!_PyArg_NoStackKeywords("{name}", kwnames)) {{
832-
goto exit;
833-
}}
834-
835836
if (!_PyArg_UnpackStack(args, nargs, "{name}",
836837
{unpack_min}, {unpack_max},
837838
{parse_arguments})) {{
@@ -859,10 +860,6 @@ def insert_keywords(s):
859860
parser_prototype = parser_prototype_fastcall
860861

861862
parser_definition = parser_body(parser_prototype, normalize_snippet("""
862-
if ({self_type_check}!_PyArg_NoStackKeywords("{name}", kwnames)) {{
863-
goto exit;
864-
}}
865-
866863
if (!_PyArg_ParseStack(args, nargs, "{format_units}:{name}",
867864
{parse_arguments})) {{
868865
goto exit;
@@ -883,9 +880,9 @@ def insert_keywords(s):
883880
""", indent=4))
884881

885882
elif not new_or_init:
886-
flags = "METH_FASTCALL"
883+
flags = "METH_FASTCALL|METH_KEYWORDS"
887884

888-
parser_prototype = parser_prototype_fastcall
885+
parser_prototype = parser_prototype_fastcall_keywords
889886

890887
body = normalize_snippet("""
891888
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,

0 commit comments

Comments
 (0)