1
1
#include "Python.h"
2
2
#include "pycore_moduleobject.h" // _PyModule_GetState()
3
+ #include "structmember.h" // PyMemberDef
3
4
#include "clinic/_operator.c.h"
4
5
5
6
typedef struct {
@@ -953,8 +954,15 @@ typedef struct {
953
954
Py_ssize_t nitems ;
954
955
PyObject * item ;
955
956
Py_ssize_t index ; // -1 unless *item* is a single non-negative integer index
957
+ vectorcallfunc vectorcall ;
956
958
} itemgetterobject ;
957
959
960
+ // Forward declarations
961
+ static PyObject *
962
+ itemgetter_vectorcall (PyObject * , PyObject * const * , size_t , PyObject * );
963
+ static PyObject *
964
+ itemgetter_call_impl (itemgetterobject * , PyObject * );
965
+
958
966
/* AC 3.5: treats first argument as an iterable, otherwise uses *args */
959
967
static PyObject *
960
968
itemgetter_new (PyTypeObject * type , PyObject * args , PyObject * kwds )
@@ -1000,6 +1008,7 @@ itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1000
1008
}
1001
1009
}
1002
1010
1011
+ ig -> vectorcall = (vectorcallfunc )itemgetter_vectorcall ;
1003
1012
PyObject_GC_Track (ig );
1004
1013
return (PyObject * )ig ;
1005
1014
}
@@ -1032,16 +1041,33 @@ itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg)
1032
1041
static PyObject *
1033
1042
itemgetter_call (itemgetterobject * ig , PyObject * args , PyObject * kw )
1034
1043
{
1035
- PyObject * obj , * result ;
1036
- Py_ssize_t i , nitems = ig -> nitems ;
1037
-
1038
1044
assert (PyTuple_CheckExact (args ));
1039
1045
if (!_PyArg_NoKeywords ("itemgetter" , kw ))
1040
1046
return NULL ;
1041
1047
if (!_PyArg_CheckPositional ("itemgetter" , PyTuple_GET_SIZE (args ), 1 , 1 ))
1042
1048
return NULL ;
1049
+ return itemgetter_call_impl (ig , PyTuple_GET_ITEM (args , 0 ));
1050
+ }
1043
1051
1044
- obj = PyTuple_GET_ITEM (args , 0 );
1052
+ static PyObject *
1053
+ itemgetter_vectorcall (PyObject * ig , PyObject * const * args ,
1054
+ size_t nargsf , PyObject * kwnames )
1055
+ {
1056
+ if (!_PyArg_NoKwnames ("itemgetter" , kwnames )) {
1057
+ return NULL ;
1058
+ }
1059
+ Py_ssize_t nargs = PyVectorcall_NARGS (nargsf );
1060
+ if (!_PyArg_CheckPositional ("itemgetter" , nargs , 1 , 1 )) {
1061
+ return NULL ;
1062
+ }
1063
+ return itemgetter_call_impl ((itemgetterobject * )ig , args [0 ]);
1064
+ }
1065
+
1066
+ static PyObject *
1067
+ itemgetter_call_impl (itemgetterobject * ig , PyObject * obj )
1068
+ {
1069
+ PyObject * result ;
1070
+ Py_ssize_t i , nitems = ig -> nitems ;
1045
1071
if (nitems == 1 ) {
1046
1072
if (ig -> index >= 0
1047
1073
&& PyTuple_CheckExact (obj )
@@ -1109,20 +1135,27 @@ static PyMethodDef itemgetter_methods[] = {
1109
1135
{NULL }
1110
1136
};
1111
1137
1138
+ static PyMemberDef itemgetter_members [] = {
1139
+ {"__vectorcalloffset__" , T_PYSSIZET , offsetof(itemgetterobject , vectorcall ), READONLY },
1140
+ {NULL } /* Sentinel */
1141
+ };
1142
+
1112
1143
PyDoc_STRVAR (itemgetter_doc ,
1113
1144
"itemgetter(item, ...) --> itemgetter object\n\
1114
1145
\n\
1115
1146
Return a callable object that fetches the given item(s) from its operand.\n\
1116
1147
After f = itemgetter(2), the call f(r) returns r[2].\n\
1117
1148
After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])" );
1118
1149
1150
+
1119
1151
static PyType_Slot itemgetter_type_slots [] = {
1120
1152
{Py_tp_doc , (void * )itemgetter_doc },
1121
1153
{Py_tp_dealloc , itemgetter_dealloc },
1122
1154
{Py_tp_call , itemgetter_call },
1123
1155
{Py_tp_traverse , itemgetter_traverse },
1124
1156
{Py_tp_clear , itemgetter_clear },
1125
1157
{Py_tp_methods , itemgetter_methods },
1158
+ {Py_tp_members , itemgetter_members },
1126
1159
{Py_tp_new , itemgetter_new },
1127
1160
{Py_tp_getattro , PyObject_GenericGetAttr },
1128
1161
{Py_tp_repr , itemgetter_repr },
@@ -1134,7 +1167,7 @@ static PyType_Spec itemgetter_type_spec = {
1134
1167
.basicsize = sizeof (itemgetterobject ),
1135
1168
.itemsize = 0 ,
1136
1169
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1137
- Py_TPFLAGS_IMMUTABLETYPE ),
1170
+ Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_VECTORCALL ),
1138
1171
.slots = itemgetter_type_slots ,
1139
1172
};
1140
1173
0 commit comments