diff options
author | Wenzel Jakob <wenzel.jakob@epfl.ch> | 2022-05-27 08:27:39 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-27 08:27:39 (GMT) |
commit | 5e34b494a08015e9b5a3deade23943bdba284a93 (patch) | |
tree | 829c824df2d307b14d0cf9efc51e2bbfcca92589 /Modules | |
parent | 20d30ba2ccf9182e4f08db112f428c909148a40b (diff) | |
download | cpython-5e34b494a08015e9b5a3deade23943bdba284a93.zip cpython-5e34b494a08015e9b5a3deade23943bdba284a93.tar.gz cpython-5e34b494a08015e9b5a3deade23943bdba284a93.tar.bz2 |
gh-60074: add new stable API function PyType_FromMetaclass (GH-93012)
Added a new stable API function ``PyType_FromMetaclass``, which mirrors
the behavior of ``PyType_FromModuleAndSpec`` except that it takes an
additional metaclass argument. This is, e.g., useful for language
binding tools that need to store additional information in the type
object.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_testcapimodule.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 3bc7761..37f4ded 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -308,6 +308,32 @@ test_dict_inner(int count) } } +static PyObject *pytype_fromspec_meta(PyObject* self, PyObject *meta) +{ + if (!PyType_Check(meta)) { + PyErr_SetString( + TestError, + "pytype_fromspec_meta: must be invoked with a type argument!"); + return NULL; + } + + PyType_Slot HeapCTypeViaMetaclass_slots[] = { + {0}, + }; + + PyType_Spec HeapCTypeViaMetaclass_spec = { + "_testcapi.HeapCTypeViaMetaclass", + sizeof(PyObject), + 0, + Py_TPFLAGS_DEFAULT, + HeapCTypeViaMetaclass_slots + }; + + return PyType_FromMetaclass( + (PyTypeObject *) meta, NULL, &HeapCTypeViaMetaclass_spec, NULL); +} + + static PyObject* test_dict_iteration(PyObject* self, PyObject *Py_UNUSED(ignored)) { @@ -5886,6 +5912,7 @@ static PyMethodDef TestMethods[] = { {"test_long_numbits", test_long_numbits, METH_NOARGS}, {"test_k_code", test_k_code, METH_NOARGS}, {"test_empty_argparse", test_empty_argparse, METH_NOARGS}, + {"pytype_fromspec_meta", pytype_fromspec_meta, METH_O}, {"parse_tuple_and_keywords", parse_tuple_and_keywords, METH_VARARGS}, {"pyobject_repr_from_null", pyobject_repr_from_null, METH_NOARGS}, {"pyobject_str_from_null", pyobject_str_from_null, METH_NOARGS}, @@ -7078,6 +7105,38 @@ static PyType_Spec HeapCTypeSubclassWithFinalizer_spec = { HeapCTypeSubclassWithFinalizer_slots }; +static PyType_Slot HeapCTypeMetaclass_slots[] = { + {0}, +}; + +static PyType_Spec HeapCTypeMetaclass_spec = { + "_testcapi.HeapCTypeMetaclass", + sizeof(PyHeapTypeObject), + sizeof(PyMemberDef), + Py_TPFLAGS_DEFAULT, + HeapCTypeMetaclass_slots +}; + +static PyObject * +heap_ctype_metaclass_custom_tp_new(PyTypeObject *tp, PyObject *args, PyObject *kwargs) +{ + return PyType_Type.tp_new(tp, args, kwargs); +} + +static PyType_Slot HeapCTypeMetaclassCustomNew_slots[] = { + { Py_tp_new, heap_ctype_metaclass_custom_tp_new }, + {0}, +}; + +static PyType_Spec HeapCTypeMetaclassCustomNew_spec = { + "_testcapi.HeapCTypeMetaclassCustomNew", + sizeof(PyHeapTypeObject), + sizeof(PyMemberDef), + Py_TPFLAGS_DEFAULT, + HeapCTypeMetaclassCustomNew_slots +}; + + typedef struct { PyObject_HEAD PyObject *dict; @@ -7591,6 +7650,20 @@ PyInit__testcapi(void) Py_DECREF(subclass_with_finalizer_bases); PyModule_AddObject(m, "HeapCTypeSubclassWithFinalizer", HeapCTypeSubclassWithFinalizer); + PyObject *HeapCTypeMetaclass = PyType_FromMetaclass( + &PyType_Type, m, &HeapCTypeMetaclass_spec, (PyObject *) &PyType_Type); + if (HeapCTypeMetaclass == NULL) { + return NULL; + } + PyModule_AddObject(m, "HeapCTypeMetaclass", HeapCTypeMetaclass); + + PyObject *HeapCTypeMetaclassCustomNew = PyType_FromMetaclass( + &PyType_Type, m, &HeapCTypeMetaclassCustomNew_spec, (PyObject *) &PyType_Type); + if (HeapCTypeMetaclassCustomNew == NULL) { + return NULL; + } + PyModule_AddObject(m, "HeapCTypeMetaclassCustomNew", HeapCTypeMetaclassCustomNew); + if (PyType_Ready(&ContainerNoGC_type) < 0) { return NULL; } |