diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index f387279d143eec..75b81396c6ebba 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -142,7 +142,13 @@ The following functions and structs are used to create .. c:function:: PyObject* PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) - Creates and returns a heap type object from the *spec* + Equivalent to ``PyMetaType_FromSpec(module, &PyType_Type, spec, bases)``. + + .. versionadded:: 3.9 + +.. c:function:: PyObject* PyMetaType_FromSpec(PyObject *module, PyTypeObject *meta_type, PyType_Spec *spec, PyObject *bases) + + Creates and returns a heap type object from the *spec* whose's metaclass is *meta_type* (:const:`Py_TPFLAGS_HEAPTYPE`). If *bases* is a tuple, the created heap type contains all types contained @@ -155,19 +161,23 @@ The following functions and structs are used to create If not ``NULL``, the module is associated with the new type and can later be retreived with :c:func:`PyType_GetModule`. - This function calls :c:func:`PyType_Ready` on the new type. + This function calls :c:func:`PyType_Ready` on the new type.' - .. versionadded:: 3.9 + .. note:: + + This method DOES NOT invoke ``PyTypeObject.tp_new`` on 'meta_type'. + + .. versionadded:: 3.10 .. c:function:: PyObject* PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) - Equivalent to ``PyType_FromModuleAndSpec(NULL, spec, bases)``. + Equivalent to ``PyMetaType_FromSpec(NULL, &PyType_Type, spec, bases)``. .. versionadded:: 3.3 .. c:function:: PyObject* PyType_FromSpec(PyType_Spec *spec) - Equivalent to ``PyType_FromSpecWithBases(spec, NULL)``. + Equivalent to ``PyMetaType_FromSpec(NULL, &PyType_Type, spec, NULL)``. .. c:type:: PyType_Spec diff --git a/Include/object.h b/Include/object.h index 537567040f9871..f3eae2341bd433 100644 --- a/Include/object.h +++ b/Include/object.h @@ -225,15 +225,16 @@ typedef struct{ PyType_Slot *slots; /* terminated by slot==0. */ } PyType_Spec; -PyAPI_FUNC(PyObject*) PyType_FromSpec(PyType_Spec*); +#define PyType_FromSpec(spec) PyMetaType_FromSpec(NULL, &PyType_Type, spec, NULL) +PyAPI_FUNC(PyObject*) PyMetaType_FromSpec(PyObject*, PyTypeObject*, PyType_Spec*, PyObject*); #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 -PyAPI_FUNC(PyObject*) PyType_FromSpecWithBases(PyType_Spec*, PyObject*); +#define PyType_FromSpecWithBases(spec, bases) PyMetaType_FromSpec(NULL, &PyType_Type, spec, bases) #endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03040000 PyAPI_FUNC(void*) PyType_GetSlot(PyTypeObject*, int); #endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000 -PyAPI_FUNC(PyObject*) PyType_FromModuleAndSpec(PyObject *, PyType_Spec *, PyObject *); +#define PyType_FromModuleAndSpec(module, spec, bases) PyMetaType_FromSpec(module, &PyType_Type, spec, bases) PyAPI_FUNC(PyObject *) PyType_GetModule(struct _typeobject *); PyAPI_FUNC(void *) PyType_GetModuleState(struct _typeobject *); #endif diff --git a/Misc/NEWS.d/next/C API/2020-06-30-16-31-15.bpo-41171.wFnoOM.rst b/Misc/NEWS.d/next/C API/2020-06-30-16-31-15.bpo-41171.wFnoOM.rst new file mode 100644 index 00000000000000..99e6b2dace47a9 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-06-30-16-31-15.bpo-41171.wFnoOM.rst @@ -0,0 +1 @@ +Added method "PyMetaType_FromSpec" to allow for specifying the metaclass for the type. \ No newline at end of file diff --git a/Objects/typeobject.c b/Objects/typeobject.c index f0e349ecd2bb92..80c408f9b413dd 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2880,14 +2880,13 @@ static const short slotoffsets[] = { }; PyObject * -PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) +PyMetaType_FromSpec(PyObject *module, PyTypeObject *meta_type, PyType_Spec *spec, PyObject *bases) { - return PyType_FromModuleAndSpec(NULL, spec, bases); -} + if (meta_type == NULL) { + PyErr_BadArgument(); + return NULL; + } -PyObject * -PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) -{ PyHeapTypeObject *res; PyObject *modname; PyTypeObject *type, *base; @@ -2924,7 +2923,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) } } - res = (PyHeapTypeObject*)PyType_GenericAlloc(&PyType_Type, nmembers); + res = (PyHeapTypeObject*)PyType_GenericAlloc(meta_type, nmembers); if (res == NULL) return NULL; res_start = (char*)res; @@ -3098,12 +3097,6 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) return NULL; } -PyObject * -PyType_FromSpec(PyType_Spec *spec) -{ - return PyType_FromSpecWithBases(spec, NULL); -} - void * PyType_GetSlot(PyTypeObject *type, int slot) { diff --git a/PC/python3dll.c b/PC/python3dll.c index f72f2c8af19d2b..96bb6abd59d121 100644 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -541,8 +541,7 @@ EXPORT_FUNC(PyTuple_Pack) EXPORT_FUNC(PyTuple_SetItem) EXPORT_FUNC(PyTuple_Size) EXPORT_FUNC(PyType_ClearCache) -EXPORT_FUNC(PyType_FromSpec) -EXPORT_FUNC(PyType_FromSpecWithBases) +EXPORT_FUNC(PyMetaType_FromSpec) EXPORT_FUNC(PyType_GenericAlloc) EXPORT_FUNC(PyType_GenericNew) EXPORT_FUNC(PyType_GetFlags)