bpo-36974: inherit the vectorcall protocol (GH-13498) · python/cpython@735e8af

@@ -5814,6 +5814,29 @@ static PyTypeObject Generic_Type = {

5814581458155815

/* Test PEP 590 */

581658165817+

typedef struct {

5818+

PyObject_HEAD

5819+

vectorcallfunc vectorcall;

5820+

} MethodDescriptorObject;

5821+5822+

static PyObject *

5823+

MethodDescriptor_vectorcall(PyObject *callable, PyObject *const *args,

5824+

size_t nargsf, PyObject *kwnames)

5825+

{

5826+

/* True if using the vectorcall function in MethodDescriptorObject

5827+

* but False for MethodDescriptor2Object */

5828+

MethodDescriptorObject *md = (MethodDescriptorObject *)callable;

5829+

return PyBool_FromLong(md->vectorcall != NULL);

5830+

}

5831+5832+

static PyObject *

5833+

MethodDescriptor_new(PyTypeObject* type, PyObject* args, PyObject *kw)

5834+

{

5835+

MethodDescriptorObject *op = PyObject_New(MethodDescriptorObject, type);

5836+

op->vectorcall = MethodDescriptor_vectorcall;

5837+

return (PyObject *)op;

5838+

}

5839+58175840

static PyObject *

58185841

func_descr_get(PyObject *func, PyObject *obj, PyObject *type)

58195842

{

@@ -5831,10 +5854,22 @@ nop_descr_get(PyObject *func, PyObject *obj, PyObject *type)

58315854

return func;

58325855

}

583358565857+

static PyObject *

5858+

call_return_args(PyObject *self, PyObject *args, PyObject *kwargs)

5859+

{

5860+

Py_INCREF(args);

5861+

return args;

5862+

}

5863+58345864

static PyTypeObject MethodDescriptorBase_Type = {

58355865

PyVarObject_HEAD_INIT(NULL, 0)

58365866

"MethodDescriptorBase",

5837-

.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_METHOD_DESCRIPTOR,

5867+

sizeof(MethodDescriptorObject),

5868+

.tp_new = MethodDescriptor_new,

5869+

.tp_call = PyVectorcall_Call,

5870+

.tp_vectorcall_offset = offsetof(MethodDescriptorObject, vectorcall),

5871+

.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |

5872+

Py_TPFLAGS_METHOD_DESCRIPTOR | _Py_TPFLAGS_HAVE_VECTORCALL,

58385873

.tp_descr_get = func_descr_get,

58395874

};

58405875

@@ -5848,9 +5883,34 @@ static PyTypeObject MethodDescriptorNopGet_Type = {

58485883

PyVarObject_HEAD_INIT(NULL, 0)

58495884

"MethodDescriptorNopGet",

58505885

.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,

5886+

.tp_call = call_return_args,

58515887

.tp_descr_get = nop_descr_get,

58525888

};

585358895890+

typedef struct {

5891+

MethodDescriptorObject base;

5892+

vectorcallfunc vectorcall;

5893+

} MethodDescriptor2Object;

5894+5895+

static PyObject *

5896+

MethodDescriptor2_new(PyTypeObject* type, PyObject* args, PyObject *kw)

5897+

{

5898+

MethodDescriptor2Object *op = PyObject_New(MethodDescriptor2Object, type);

5899+

op->base.vectorcall = NULL;

5900+

op->vectorcall = MethodDescriptor_vectorcall;

5901+

return (PyObject *)op;

5902+

}

5903+5904+

static PyTypeObject MethodDescriptor2_Type = {

5905+

PyVarObject_HEAD_INIT(NULL, 0)

5906+

"MethodDescriptor2",

5907+

sizeof(MethodDescriptor2Object),

5908+

.tp_new = MethodDescriptor2_new,

5909+

.tp_call = PyVectorcall_Call,

5910+

.tp_vectorcall_offset = offsetof(MethodDescriptor2Object, vectorcall),

5911+

.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | _Py_TPFLAGS_HAVE_VECTORCALL,

5912+

};

5913+5854591458555915

static struct PyModuleDef _testcapimodule = {

58565916

PyModuleDef_HEAD_INIT,

@@ -5916,6 +5976,12 @@ PyInit__testcapi(void)

59165976

Py_INCREF(&MethodDescriptorNopGet_Type);

59175977

PyModule_AddObject(m, "MethodDescriptorNopGet", (PyObject *)&MethodDescriptorNopGet_Type);

591859785979+

MethodDescriptor2_Type.tp_base = &MethodDescriptorBase_Type;

5980+

if (PyType_Ready(&MethodDescriptor2_Type) < 0)

5981+

return NULL;

5982+

Py_INCREF(&MethodDescriptor2_Type);

5983+

PyModule_AddObject(m, "MethodDescriptor2", (PyObject *)&MethodDescriptor2_Type);

5984+59195985

if (PyType_Ready(&GenericAlias_Type) < 0)

59205986

return NULL;

59215987

Py_INCREF(&GenericAlias_Type);