diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index 7a677593d07..46cb3768fce 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -106,6 +106,12 @@ Type Objects GC protocol itself by at least implementing the :c:member:`~PyTypeObject.tp_traverse` handle. +.. c:function:: PyObject* PyType_GetName(PyTypeObject *type) + + Return the type's name. Equivalent to getting the type's ``__name__`` 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 22dae0c1ef1..8fd6c7bc7a2 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -2289,6 +2289,9 @@ PyType_GenericNew:PyObject*:kwds:0: PyType_GetFlags:unsigned long::: PyType_GetFlags:PyTypeObject*:type:0: +PyType_GetName:PyObject*::+1: +PyType_GetName: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 e373e2314a6..c7dde01340a 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -639,6 +639,7 @@ function,PyType_GenericNew,3.2, function,PyType_GetFlags,3.2, function,PyType_GetModule,3.10, function,PyType_GetModuleState,3.10, +function,PyType_GetName,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 e97162a17db..88b6f8fa731 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -295,6 +295,8 @@ Changes in the Python API C API Changes ============= +* Add a new :c:func:`PyType_GetName` function to get type's short name. + (Contributed by Hai Shi in :issue:`42035`.) New Features ------------ diff --git a/Include/object.h b/Include/object.h index 9e6a8f4656a..23ebad84ab4 100644 --- a/Include/object.h +++ b/Include/object.h @@ -239,6 +239,9 @@ PyAPI_FUNC(PyObject*) PyType_FromModuleAndSpec(PyObject *, PyType_Spec *, PyObje PyAPI_FUNC(PyObject *) PyType_GetModule(struct _typeobject *); PyAPI_FUNC(void *) PyType_GetModuleState(struct _typeobject *); #endif +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030B0000 +PyAPI_FUNC(PyObject *) PyType_GetName(PyTypeObject *); +#endif /* Generic type check */ PyAPI_FUNC(int) PyType_IsSubtype(PyTypeObject *, PyTypeObject *); diff --git a/Misc/NEWS.d/next/C API/2020-12-23-01-28-50.bpo-42035.S9eUm0.rst b/Misc/NEWS.d/next/C API/2020-12-23-01-28-50.bpo-42035.S9eUm0.rst new file mode 100644 index 00000000000..8adb20e62d1 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-12-23-01-28-50.bpo-42035.S9eUm0.rst @@ -0,0 +1 @@ +Add a new :c:func:`PyType_GetName` function to get type's short name. diff --git a/Misc/stable_abi.txt b/Misc/stable_abi.txt index f104f84e451..62c0cdcc5d4 100644 --- a/Misc/stable_abi.txt +++ b/Misc/stable_abi.txt @@ -2132,6 +2132,10 @@ function PyGC_Enable function PyGC_IsEnabled added 3.10 +# Add new C API in Python 3.11 + +function PyType_GetName + 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 7ac0e84d2ef..f338e89f426 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -37,6 +37,7 @@ #endif static struct PyModuleDef _testcapimodule; +static PyType_Spec HeapTypeNameType_Spec; static PyObject *TestError; /* set to exception object in init */ @@ -1134,6 +1135,30 @@ test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) } +static PyObject * +test_get_type_name(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject *tp_name = PyType_GetName(&PyLong_Type); + assert(strcmp(PyUnicode_AsUTF8(tp_name), "int") == 0); + Py_DECREF(tp_name); + + tp_name = PyType_GetName(&PyModule_Type); + assert(strcmp(PyUnicode_AsUTF8(tp_name), "module") == 0); + Py_DECREF(tp_name); + + PyObject *HeapTypeNameType = PyType_FromSpec(&HeapTypeNameType_Spec); + if (HeapTypeNameType == NULL) { + Py_RETURN_NONE; + } + tp_name = PyType_GetName((PyTypeObject *)HeapTypeNameType); + assert(strcmp(PyUnicode_AsUTF8(tp_name), "HeapTypeNameType") == 0); + Py_DECREF(tp_name); + + Py_DECREF(HeapTypeNameType); + Py_RETURN_NONE; +} + + static PyObject * get_args(PyObject *self, PyObject *args) { @@ -5624,6 +5649,7 @@ static PyMethodDef TestMethods[] = { {"test_buildvalue_issue38913", test_buildvalue_issue38913, METH_NOARGS}, {"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}, {"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs, METH_VARARGS|METH_KEYWORDS}, {"getargs_tuple", getargs_tuple, METH_VARARGS}, @@ -6512,6 +6538,21 @@ static PyType_Spec HeapDocCType_spec = { HeapDocCType_slots }; +typedef struct { + PyObject_HEAD +} HeapTypeNameObject; + +static PyType_Slot HeapTypeNameType_slots[] = { + {0}, +}; + +static PyType_Spec HeapTypeNameType_Spec = { + .name = "_testcapi.HeapTypeNameType", + .basicsize = sizeof(HeapTypeNameObject), + .flags = Py_TPFLAGS_DEFAULT, + .slots = HeapTypeNameType_slots, +}; + typedef struct { PyObject_HEAD } NullTpDocTypeObject; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 43b4d0725a4..2240f780bb9 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3628,6 +3628,12 @@ PyType_FromSpec(PyType_Spec *spec) return PyType_FromSpecWithBases(spec, NULL); } +PyObject * +PyType_GetName(PyTypeObject *type) +{ + return type_name(type, NULL); +} + void * PyType_GetSlot(PyTypeObject *type, int slot) { diff --git a/PC/python3dll.c b/PC/python3dll.c index 0ebb56efaec..1659e9fc64f 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -588,6 +588,7 @@ EXPORT_FUNC(PyType_GenericNew) EXPORT_FUNC(PyType_GetFlags) EXPORT_FUNC(PyType_GetModule) EXPORT_FUNC(PyType_GetModuleState) +EXPORT_FUNC(PyType_GetName) EXPORT_FUNC(PyType_GetSlot) EXPORT_FUNC(PyType_IsSubtype) EXPORT_FUNC(PyType_Modified)