commit 581b4faa6c9786617f50158ca031d2494d358f51 Author: Victor Stinner Date: Wed Jan 26 00:54:40 2022 +0100 bpo-45476: Add PyDescr_New() function Add new PyDescr_New() function to create a descriptor object. Add Include/cpython/descrobject.h header file: move C API excluded from the limited C API there. diff --git a/Doc/c-api/descriptor.rst b/Doc/c-api/descriptor.rst index b32c113e5f..08f9f025c9 100644 --- a/Doc/c-api/descriptor.rst +++ b/Doc/c-api/descriptor.rst @@ -15,6 +15,15 @@ found in the dictionary of type objects. The type object for the built-in descriptor types. +.. c:function:: PyObject* PyDescr_New(PyTypeObject *desc_type, PyTypeObject *type, const char *name) + + Create a descriptor object. + + *descr_type*, *type* and *name* must not be ``NULL``. + + .. versionadded:: 3.11 + + .. c:function:: PyObject* PyDescr_NewGetSet(PyTypeObject *type, struct PyGetSetDef *getset) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 4328ee6a50..53d6a0c7d7 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -677,6 +677,9 @@ New Features :c:macro:`PY_VERSION_HEX`. (Contributed by Gabriele N. Tornetta in :issue:`43931`.) +* Add new :c:func:`PyDescr_New` function to create a descriptor object. + (Contributed by Victor Stinner in :issue:`45476`.) + Porting to Python 3.11 ---------------------- diff --git a/Misc/NEWS.d/next/C API/2022-01-26-00-59-53.bpo-45476.xqT1YV.rst b/Misc/NEWS.d/next/C API/2022-01-26-00-59-53.bpo-45476.xqT1YV.rst new file mode 100644 index 0000000000..d30a5c8f79 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2022-01-26-00-59-53.bpo-45476.xqT1YV.rst @@ -0,0 +1 @@ +Add new :c:func:`PyDescr_New` function to create a descriptor object. diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 962136beae..8910e40bc3 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -876,24 +876,30 @@ PyTypeObject PyWrapperDescr_Type = { 0, /* tp_descr_set */ }; -static PyDescrObject * -descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name) +PyDescrObject * +PyDescr_New(PyTypeObject *descr_type, PyTypeObject *type, const char *name) { - PyDescrObject *descr; + assert(descr_type != NULL); + assert(type != NULL); + assert(name != NULL); + assert(_PyType_IS_GC(descr_type)); - descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0); - if (descr != NULL) { - Py_XINCREF(type); - descr->d_type = type; - descr->d_name = PyUnicode_InternFromString(name); - if (descr->d_name == NULL) { - Py_DECREF(descr); - descr = NULL; - } - else { - descr->d_qualname = NULL; - } + PyObject *name_obj = PyUnicode_InternFromString(name); + if (name_obj == NULL) { + return NULL; } + + PyDescrObject *descr = (PyDescrObject *)_PyType_AllocNoTrack(descr_type, 0); + if (descr == NULL) { + Py_DECREF(name_obj); + return NULL; + } + + descr->d_type = (PyTypeObject*)Py_NewRef(type); + descr->d_name = name_obj; + descr->d_qualname = NULL; + _PyObject_GC_TRACK(descr); + return descr; } @@ -934,8 +940,8 @@ PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method) PyMethodDescrObject *descr; - descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type, - type, method->ml_name); + descr = (PyMethodDescrObject *)PyDescr_New(&PyMethodDescr_Type, + type, method->ml_name); if (descr != NULL) { descr->d_method = method; descr->vectorcall = vectorcall; @@ -948,8 +954,8 @@ PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method) { PyMethodDescrObject *descr; - descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type, - type, method->ml_name); + descr = (PyMethodDescrObject *)PyDescr_New(&PyClassMethodDescr_Type, + type, method->ml_name); if (descr != NULL) descr->d_method = method; return (PyObject *)descr; @@ -960,8 +966,8 @@ PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member) { PyMemberDescrObject *descr; - descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type, - type, member->name); + descr = (PyMemberDescrObject *)PyDescr_New(&PyMemberDescr_Type, + type, member->name); if (descr != NULL) descr->d_member = member; return (PyObject *)descr; @@ -972,8 +978,8 @@ PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset) { PyGetSetDescrObject *descr; - descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type, - type, getset->name); + descr = (PyGetSetDescrObject *)PyDescr_New(&PyGetSetDescr_Type, + type, getset->name); if (descr != NULL) descr->d_getset = getset; return (PyObject *)descr; @@ -984,8 +990,8 @@ PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped) { PyWrapperDescrObject *descr; - descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type, - type, base->name); + descr = (PyWrapperDescrObject *)PyDescr_New(&PyWrapperDescr_Type, + type, base->name); if (descr != NULL) { descr->d_base = base; descr->d_wrapped = wrapped;