From a940aafd8e41b5303412e323ecb02d061ff62cf5 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Fri, 30 Jul 2021 23:58:03 +0800 Subject: [PATCH 1/2] Add a PyType_GetQualName() to get type's qualified name. --- Doc/c-api/type.rst | 7 ++++ Doc/data/refcounts.dat | 3 ++ Doc/data/stable_abi.dat | 1 + Doc/whatsnew/3.11.rst | 3 ++ Include/object.h | 1 + .../2021-08-02-20-49-36.bpo-42035.HTBcZt.rst | 2 ++ Misc/stable_abi.txt | 2 ++ Modules/_testcapimodule.c | 34 +++++++++++++++++++ Objects/typeobject.c | 6 ++++ PC/python3dll.c | 1 + 10 files changed, 60 insertions(+) create mode 100644 Misc/NEWS.d/next/C API/2021-08-02-20-49-36.bpo-42035.HTBcZt.rst diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index 46cb3768fcee4d..2d05bc1d16ae3d 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -112,6 +112,13 @@ Type Objects .. versionadded:: 3.11 +.. c:function:: PyObject* PyType_GetQualName(PyTypeObject *type) + + Return the type's qualified name. Equivalent to getting the + type's ``__qualname__`` attribute. + + .. versionadded:: 3.11 + .. c:function:: void* PyType_GetSlot(PyTypeObject *type, int slot) Return the function pointer stored in the given slot. If the diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 8fd6c7bc7a2bc3..d297354860d273 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -2292,6 +2292,9 @@ PyType_GetFlags:PyTypeObject*:type:0: PyType_GetName:PyObject*::+1: PyType_GetName:PyTypeObject*:type:0: +PyType_GetQualName:PyObject*::+1: +PyType_GetQualName:PyTypeObject*:type:0: + PyType_GetSlot:void*::: PyType_GetSlot:PyTypeObject*:type:0: PyType_GetSlot:int:slot:: diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index c7dde01340a32a..613d7044ca1824 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -640,6 +640,7 @@ function,PyType_GetFlags,3.2, function,PyType_GetModule,3.10, function,PyType_GetModuleState,3.10, function,PyType_GetName,3.11, +function,PyType_GetQualName,3.11, function,PyType_GetSlot,3.4, function,PyType_IsSubtype,3.2, function,PyType_Modified,3.2, diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 88b6f8fa7314e0..c546ec0fc6d9b4 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -298,6 +298,9 @@ C API Changes * Add a new :c:func:`PyType_GetName` function to get type's short name. (Contributed by Hai Shi in :issue:`42035`.) +* Add a new :c:func:`PyType_GetQualName` function to get type's qualified name. + (Contributed by Hai Shi in :issue:`42035`.) + New Features ------------ diff --git a/Include/object.h b/Include/object.h index 23ebad84ab4672..fb8a63fc7dbe84 100644 --- a/Include/object.h +++ b/Include/object.h @@ -241,6 +241,7 @@ PyAPI_FUNC(void *) PyType_GetModuleState(struct _typeobject *); #endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030B0000 PyAPI_FUNC(PyObject *) PyType_GetName(PyTypeObject *); +PyAPI_FUNC(PyObject *) PyType_GetQualName(PyTypeObject *); #endif /* Generic type check */ diff --git a/Misc/NEWS.d/next/C API/2021-08-02-20-49-36.bpo-42035.HTBcZt.rst b/Misc/NEWS.d/next/C API/2021-08-02-20-49-36.bpo-42035.HTBcZt.rst new file mode 100644 index 00000000000000..4631c43fdd5312 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-08-02-20-49-36.bpo-42035.HTBcZt.rst @@ -0,0 +1,2 @@ +Add a new :c:func:`PyType_GetQualName` function to get type's qualified +name. diff --git a/Misc/stable_abi.txt b/Misc/stable_abi.txt index 62c0cdcc5d43b4..4fc1d6c73cb5ee 100644 --- a/Misc/stable_abi.txt +++ b/Misc/stable_abi.txt @@ -2136,6 +2136,8 @@ function PyGC_IsEnabled function PyType_GetName added 3.11 +function PyType_GetQualName + added 3.11 # (Detailed comments aren't really needed for further entries: from here on # we can use version control logs.) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index f338e89f426da0..081c79da691dfe 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1159,6 +1159,39 @@ test_get_type_name(PyObject *self, PyObject *Py_UNUSED(ignored)) } +static PyObject * +test_get_type_qualname(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject *tp_qualname = PyType_GetQualName(&PyLong_Type); + assert(strcmp(PyUnicode_AsUTF8(tp_qualname), "int") == 0); + Py_DECREF(tp_qualname); + + tp_qualname = PyType_GetQualName(&_PyNamespace_Type); + assert(strcmp(PyUnicode_AsUTF8(tp_qualname), "SimpleNamespace") == 0); + Py_DECREF(tp_qualname); + + PyObject *HeapTypeNameType = PyType_FromSpec(&HeapTypeNameType_Spec); + if (HeapTypeNameType == NULL) { + Py_RETURN_NONE; + } + PyObject *spec_name = PyUnicode_FromString(HeapTypeNameType_Spec.name); + if (PyObject_SetAttrString(HeapTypeNameType, + "__qualname__", spec_name) < 0) { + Py_DECREF(spec_name); + Py_DECREF(HeapTypeNameType); + Py_RETURN_NONE; + } + tp_qualname = PyType_GetQualName((PyTypeObject *)HeapTypeNameType); + assert(strcmp(PyUnicode_AsUTF8(tp_qualname), + "_testcapi.HeapTypeNameType") == 0); + Py_DECREF(spec_name); + Py_DECREF(tp_qualname); + + Py_DECREF(HeapTypeNameType); + Py_RETURN_NONE; +} + + static PyObject * get_args(PyObject *self, PyObject *args) { @@ -5650,6 +5683,7 @@ static PyMethodDef TestMethods[] = { {"get_args", get_args, METH_VARARGS}, {"test_get_statictype_slots", test_get_statictype_slots, METH_NOARGS}, {"test_get_type_name", test_get_type_name, METH_NOARGS}, + {"test_get_type_qualname", test_get_type_qualname, METH_NOARGS}, {"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs, METH_VARARGS|METH_KEYWORDS}, {"getargs_tuple", getargs_tuple, METH_VARARGS}, diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 2240f780bb9ceb..83f5ca73c133f9 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3634,6 +3634,12 @@ PyType_GetName(PyTypeObject *type) return type_name(type, NULL); } +PyObject * +PyType_GetQualName(PyTypeObject *type) +{ + return type_qualname(type, NULL); +} + void * PyType_GetSlot(PyTypeObject *type, int slot) { diff --git a/PC/python3dll.c b/PC/python3dll.c index 1659e9fc64f5cb..fe567cc93ff41f 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -589,6 +589,7 @@ EXPORT_FUNC(PyType_GetFlags) EXPORT_FUNC(PyType_GetModule) EXPORT_FUNC(PyType_GetModuleState) EXPORT_FUNC(PyType_GetName) +EXPORT_FUNC(PyType_GetQualName) EXPORT_FUNC(PyType_GetSlot) EXPORT_FUNC(PyType_IsSubtype) EXPORT_FUNC(PyType_Modified) From 4cfebb2078d9349d6627fcc6606587529c93259f Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Fri, 6 Aug 2021 01:15:37 +0800 Subject: [PATCH 2/2] apply petr's comment --- Modules/_testcapimodule.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 081c79da691dfe..2a5ae5125a1523 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1174,12 +1174,18 @@ test_get_type_qualname(PyObject *self, PyObject *Py_UNUSED(ignored)) if (HeapTypeNameType == NULL) { Py_RETURN_NONE; } + tp_qualname = PyType_GetQualName((PyTypeObject *)HeapTypeNameType); + assert(strcmp(PyUnicode_AsUTF8(tp_qualname), "HeapTypeNameType") == 0); + Py_DECREF(tp_qualname); + PyObject *spec_name = PyUnicode_FromString(HeapTypeNameType_Spec.name); + if (spec_name == NULL) { + goto done; + } if (PyObject_SetAttrString(HeapTypeNameType, "__qualname__", spec_name) < 0) { Py_DECREF(spec_name); - Py_DECREF(HeapTypeNameType); - Py_RETURN_NONE; + goto done; } tp_qualname = PyType_GetQualName((PyTypeObject *)HeapTypeNameType); assert(strcmp(PyUnicode_AsUTF8(tp_qualname), @@ -1187,6 +1193,7 @@ test_get_type_qualname(PyObject *self, PyObject *Py_UNUSED(ignored)) Py_DECREF(spec_name); Py_DECREF(tp_qualname); + done: Py_DECREF(HeapTypeNameType); Py_RETURN_NONE; }