From f98c574107fba1a67e98de77fb0a79cda9dc705b Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Wed, 23 Dec 2020 12:38:24 +0800 Subject: [PATCH 1/6] Add a PyType_GetName() to get type's name --- Doc/c-api/type.rst | 6 +++ Doc/data/refcounts.dat | 3 ++ Doc/whatsnew/3.10.rst | 3 ++ Include/object.h | 3 ++ .../2020-12-23-01-28-50.bpo-42035.S9eUm0.rst | 1 + Modules/_testcapimodule.c | 38 +++++++++++++++++++ Objects/typeobject.c | 11 ++++++ 7 files changed, 65 insertions(+) create mode 100644 Misc/NEWS.d/next/C API/2020-12-23-01-28-50.bpo-42035.S9eUm0.rst diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index a869859dd421d1..02a033b843ab53 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -95,6 +95,12 @@ Type Objects from a type's base class. Return ``0`` on success, or return ``-1`` and sets an exception on error. +.. c:function:: const char* PyType_GetName(PyTypeObject *type) + + Return the type's name. This function can accept heap or static types. + + .. versionadded:: 3.10 + .. 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 8a6ee718a012dd..5d03397b562803 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -2309,6 +2309,9 @@ PyType_GenericNew:PyObject*:kwds:0: PyType_GetFlags:unsigned long::: PyType_GetFlags:PyTypeObject*:type:0: +PyType_GetName:const char*::: +PyType_GetName:PyTypeObject*:type:0: + PyType_GetSlot:void*::: PyType_GetSlot:PyTypeObject*:type:0: PyType_GetSlot:int:slot:: diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index a6f9b0b1754d29..c45ee71d2712f1 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -606,6 +606,9 @@ New Features * The :c:func:`PyType_GetSlot` function can accept static types. (Contributed by Hai Shi and Petr Viktorin in :issue:`41073`.) +* Add a new :c:func:`PyType_GetName` function to get type's name. + (Contributed by Hai Shi in :issue:`42035`.) + Porting to Python 3.10 ---------------------- diff --git a/Include/object.h b/Include/object.h index 8d0039428e73af..d68b0ce3777aac 100644 --- a/Include/object.h +++ b/Include/object.h @@ -232,6 +232,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 >= 0x03100000 +PyAPI_FUNC(const char *) 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 00000000000000..d07eb606ba9ebc --- /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 name. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 4f97927fa23229..2e83f410f2ecd7 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -38,6 +38,7 @@ #endif static struct PyModuleDef _testcapimodule; +static PyType_Spec HeapTypeNameType_Spec; static PyObject *TestError; /* set to exception object in init */ @@ -1074,6 +1075,27 @@ test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) } +static PyObject * +test_get_type_name(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + const char *tp_name = PyType_GetName(&PyLong_Type); + assert(strcmp(tp_name, "int") == 0); + + tp_name = PyType_GetName(&PyModule_Type); + assert(strcmp(tp_name, "module") == 0); + + PyObject *HeapTypeNameType = PyType_FromSpec(&HeapTypeNameType_Spec); + if (HeapTypeNameType == NULL) { + Py_RETURN_NONE; + } + tp_name = PyType_GetName((PyTypeObject *)HeapTypeNameType); + assert(strcmp(tp_name, "HeapTypeNameType") == 0); + + Py_DECREF(HeapTypeNameType); + Py_RETURN_NONE; +} + + static PyObject * get_args(PyObject *self, PyObject *args) { @@ -5738,6 +5760,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}, @@ -6622,6 +6645,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 83bc877eb7d05c..049bbedf6471c0 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3152,6 +3152,17 @@ PyType_FromSpec(PyType_Spec *spec) return PyType_FromSpecWithBases(spec, NULL); } +const char * +PyType_GetName(PyTypeObject *type) +{ + assert(PyType_Check(type)); + if (_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { + return PyUnicode_AsUTF8(((PyHeapTypeObject *)type)->ht_name); + } else { + return type->tp_name; + } +} + void * PyType_GetSlot(PyTypeObject *type, int slot) { From ac19a57536c3fc235ceae16739305790fb63aad1 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Wed, 6 Jan 2021 00:39:28 +0800 Subject: [PATCH 2/6] apply petr's comment --- Doc/c-api/type.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index 02a033b843ab53..1ed1981d7dfeb5 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -97,7 +97,7 @@ Type Objects .. c:function:: const char* PyType_GetName(PyTypeObject *type) - Return the type's name. This function can accept heap or static types. + Return the type's name. .. versionadded:: 3.10 From 8ec352a6ebbbac2476bceb29f95f558108b9d785 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Thu, 7 Jan 2021 00:41:13 +0800 Subject: [PATCH 3/6] apply petr's comment --- Doc/c-api/type.rst | 4 +++- Modules/_testcapimodule.c | 2 +- Objects/typeobject.c | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index 1ed1981d7dfeb5..ae98c6341861e6 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -97,7 +97,9 @@ Type Objects .. c:function:: const char* PyType_GetName(PyTypeObject *type) - Return the type's name. + Return the type's name. The returned pointer includes the module name + if type's name have a prefix of module name. + Callers can hold this pointer until the type has been deallocated. .. versionadded:: 3.10 diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 2e83f410f2ecd7..1a25e940df1edd 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1089,7 +1089,7 @@ test_get_type_name(PyObject *self, PyObject *Py_UNUSED(ignored)) Py_RETURN_NONE; } tp_name = PyType_GetName((PyTypeObject *)HeapTypeNameType); - assert(strcmp(tp_name, "HeapTypeNameType") == 0); + assert(strcmp(tp_name, "_testcapi.HeapTypeNameType") == 0); Py_DECREF(HeapTypeNameType); Py_RETURN_NONE; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 049bbedf6471c0..d5afb1034166cd 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3157,10 +3157,10 @@ PyType_GetName(PyTypeObject *type) { assert(PyType_Check(type)); if (_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { - return PyUnicode_AsUTF8(((PyHeapTypeObject *)type)->ht_name); - } else { - return type->tp_name; + PyTypeObject ht_type = ((PyHeapTypeObject *)type)->ht_type; + return ht_type.tp_name; } + return type->tp_name; } void * From 9635bcf8e1d16a563d6b89039b778fd1c1904279 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Mon, 1 Feb 2021 20:21:51 +0800 Subject: [PATCH 4/6] PyType_GetName return a object --- Doc/c-api/type.rst | 6 ++---- Doc/data/refcounts.dat | 2 +- Doc/whatsnew/3.10.rst | 2 +- Include/object.h | 2 +- .../C API/2020-12-23-01-28-50.bpo-42035.S9eUm0.rst | 2 +- Modules/_testcapimodule.c | 11 +++++++---- Objects/typeobject.c | 9 +++++---- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index ae98c6341861e6..635c5c5951d3a0 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -95,11 +95,9 @@ Type Objects from a type's base class. Return ``0`` on success, or return ``-1`` and sets an exception on error. -.. c:function:: const char* PyType_GetName(PyTypeObject *type) +.. c:function:: PyObject* PyType_GetName(PyTypeObject *type) - Return the type's name. The returned pointer includes the module name - if type's name have a prefix of module name. - Callers can hold this pointer until the type has been deallocated. + Return the type's name. The returned object haven't a prefix of module name. .. versionadded:: 3.10 diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 5d03397b562803..e1166fa32c0253 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -2309,7 +2309,7 @@ PyType_GenericNew:PyObject*:kwds:0: PyType_GetFlags:unsigned long::: PyType_GetFlags:PyTypeObject*:type:0: -PyType_GetName:const char*::: +PyType_GetName:PyObject*::+1: PyType_GetName:PyTypeObject*:type:0: PyType_GetSlot:void*::: diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index c45ee71d2712f1..dc47c1d12822dc 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -606,7 +606,7 @@ New Features * The :c:func:`PyType_GetSlot` function can accept static types. (Contributed by Hai Shi and Petr Viktorin in :issue:`41073`.) -* Add a new :c:func:`PyType_GetName` function to get type's name. +* Add a new :c:func:`PyType_GetName` function to get type's short name. (Contributed by Hai Shi in :issue:`42035`.) diff --git a/Include/object.h b/Include/object.h index d68b0ce3777aac..98ce9f7e083bd4 100644 --- a/Include/object.h +++ b/Include/object.h @@ -233,7 +233,7 @@ PyAPI_FUNC(PyObject *) PyType_GetModule(struct _typeobject *); PyAPI_FUNC(void *) PyType_GetModuleState(struct _typeobject *); #endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03100000 -PyAPI_FUNC(const char *) PyType_GetName(PyTypeObject *); +PyAPI_FUNC(PyObject *) PyType_GetName(PyTypeObject *); #endif /* Generic type check */ 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 index d07eb606ba9ebc..8adb20e62d1c46 100644 --- 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 @@ -1 +1 @@ -Add a new :c:func:`PyType_GetName` function to get type's name. +Add a new :c:func:`PyType_GetName` function to get type's short name. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 1a25e940df1edd..e968a1d7c5a4c3 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1078,18 +1078,21 @@ test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) static PyObject * test_get_type_name(PyObject *self, PyObject *Py_UNUSED(ignored)) { - const char *tp_name = PyType_GetName(&PyLong_Type); - assert(strcmp(tp_name, "int") == 0); + 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(tp_name, "module") == 0); + 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(tp_name, "_testcapi.HeapTypeNameType") == 0); + assert(strcmp(PyUnicode_AsUTF8(tp_name), "HeapTypeNameType") == 0); + Py_DECREF(tp_name); Py_DECREF(HeapTypeNameType); Py_RETURN_NONE; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index d5afb1034166cd..c12f7377eb9cba 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3152,15 +3152,16 @@ PyType_FromSpec(PyType_Spec *spec) return PyType_FromSpecWithBases(spec, NULL); } -const char * +PyObject * PyType_GetName(PyTypeObject *type) { assert(PyType_Check(type)); if (_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { - PyTypeObject ht_type = ((PyHeapTypeObject *)type)->ht_type; - return ht_type.tp_name; + PyHeapTypeObject *ht_type = (PyHeapTypeObject *)type; + Py_INCREF(ht_type->ht_name); + return ht_type->ht_name; } - return type->tp_name; + return PyUnicode_FromString(_PyType_Name(type)); } void * From 4ba554d8281a3f19782efd1ab5f531dc01b00f61 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Thu, 25 Feb 2021 00:38:03 +0800 Subject: [PATCH 5/6] calling type_name() in PyType_GetName() --- Objects/typeobject.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index c12f7377eb9cba..be9097d94106ae 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3155,13 +3155,7 @@ PyType_FromSpec(PyType_Spec *spec) PyObject * PyType_GetName(PyTypeObject *type) { - assert(PyType_Check(type)); - if (_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { - PyHeapTypeObject *ht_type = (PyHeapTypeObject *)type; - Py_INCREF(ht_type->ht_name); - return ht_type->ht_name; - } - return PyUnicode_FromString(_PyType_Name(type)); + return type_name(type); } void * From 08d3453c2aaee78f0cd38203ddcf1d105419355b Mon Sep 17 00:00:00 2001 From: hai shi Date: Tue, 27 Jul 2021 23:53:01 +0800 Subject: [PATCH 6/6] apply petr's comments --- Doc/c-api/type.rst | 2 +- Doc/data/stable_abi.dat | 1 + Include/object.h | 2 +- Misc/stable_abi.txt | 4 ++++ PC/python3dll.c | 1 + 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index 0be072cb3fa4ea..46cb3768fcee4d 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -108,7 +108,7 @@ Type Objects .. c:function:: PyObject* PyType_GetName(PyTypeObject *type) - Return the type's name. The returned object haven't a prefix of module name. + Return the type's name. Equivalent to getting the type's ``__name__`` attribute. .. versionadded:: 3.11 diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index e373e2314a6517..c7dde01340a32a 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/Include/object.h b/Include/object.h index de2dac2eed4cb6..fd347719264fc1 100644 --- a/Include/object.h +++ b/Include/object.h @@ -239,7 +239,7 @@ 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 >= 0x03110000 +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030B0000 PyAPI_FUNC(PyObject *) PyType_GetName(PyTypeObject *); #endif diff --git a/Misc/stable_abi.txt b/Misc/stable_abi.txt index f104f84e451da1..62c0cdcc5d43b4 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/PC/python3dll.c b/PC/python3dll.c index 0ebb56efaecb2c..1659e9fc64f5cb 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)