bpo-41832: PyType_FromModuleAndSpec() now accepts NULL tp_doc (GH-23123)

This commit is contained in:
Hai Shi 2020-11-07 00:04:47 +08:00 committed by GitHub
parent 803187796f
commit 88c2cfd9ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 44 additions and 4 deletions

View File

@ -169,6 +169,10 @@ The following functions and structs are used to create
.. versionadded:: 3.9 .. versionadded:: 3.9
.. versionchanged:: 3.10
The function now accepts NULL ``tp_doc`` slot.
.. c:function:: PyObject* PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) .. c:function:: PyObject* PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
Equivalent to ``PyType_FromModuleAndSpec(NULL, spec, bases)``. Equivalent to ``PyType_FromModuleAndSpec(NULL, spec, bases)``.
@ -259,5 +263,3 @@ The following functions and structs are used to create
The desired value of the slot. In most cases, this is a pointer The desired value of the slot. In most cases, this is a pointer
to a function. to a function.
May not be ``NULL``.

View File

@ -401,6 +401,10 @@ New Features
reference count of an object and return the object. reference count of an object and return the object.
(Contributed by Victor Stinner in :issue:`42262`.) (Contributed by Victor Stinner in :issue:`42262`.)
* The :c:func:`PyType_FromModuleAndSpec` function now accepts NULL ``tp_doc``
slot.
(Contributed by Hai Shi in :issue:`41832`.)
Porting to Python 3.10 Porting to Python 3.10
---------------------- ----------------------

View File

@ -405,6 +405,9 @@ class CAPITest(unittest.TestCase):
self.assertEqual(_testcapi.HeapDocCType.__doc__, "somedoc") self.assertEqual(_testcapi.HeapDocCType.__doc__, "somedoc")
self.assertEqual(_testcapi.HeapDocCType.__text_signature__, "(arg1, arg2)") self.assertEqual(_testcapi.HeapDocCType.__text_signature__, "(arg1, arg2)")
def test_null_type_doc(self):
self.assertEqual(_testcapi.NullTpDocType.__doc__, None)
def test_subclass_of_heap_gc_ctype_with_tpdealloc_decrefs_once(self): def test_subclass_of_heap_gc_ctype_with_tpdealloc_decrefs_once(self):
class HeapGcCTypeSubclass(_testcapi.HeapGcCType): class HeapGcCTypeSubclass(_testcapi.HeapGcCType):
def __init__(self): def __init__(self):

View File

@ -0,0 +1,2 @@
The :c:func:`PyType_FromModuleAndSpec` function now accepts NULL ``tp_doc``
slot.

View File

@ -489,15 +489,15 @@ static PyStructSequence_Field profiler_subentry_fields[] = {
static PyStructSequence_Desc profiler_entry_desc = { static PyStructSequence_Desc profiler_entry_desc = {
.name = "_lsprof.profiler_entry", .name = "_lsprof.profiler_entry",
.doc = "",
.fields = profiler_entry_fields, .fields = profiler_entry_fields,
.doc = NULL,
.n_in_sequence = 6 .n_in_sequence = 6
}; };
static PyStructSequence_Desc profiler_subentry_desc = { static PyStructSequence_Desc profiler_subentry_desc = {
.name = "_lsprof.profiler_subentry", .name = "_lsprof.profiler_subentry",
.doc = "",
.fields = profiler_subentry_fields, .fields = profiler_subentry_fields,
.doc = NULL,
.n_in_sequence = 5 .n_in_sequence = 5
}; };

View File

@ -6508,6 +6508,23 @@ static PyType_Spec HeapDocCType_spec = {
HeapDocCType_slots HeapDocCType_slots
}; };
typedef struct {
PyObject_HEAD
} NullTpDocTypeObject;
static PyType_Slot NullTpDocType_slots[] = {
{Py_tp_doc, NULL},
{0, 0},
};
static PyType_Spec NullTpDocType_spec = {
"_testcapi.NullTpDocType",
sizeof(NullTpDocTypeObject),
0,
Py_TPFLAGS_DEFAULT,
NullTpDocType_slots
};
PyDoc_STRVAR(heapgctype__doc__, PyDoc_STRVAR(heapgctype__doc__,
"A heap type with GC, and with overridden dealloc.\n\n" "A heap type with GC, and with overridden dealloc.\n\n"
@ -7183,6 +7200,14 @@ PyInit__testcapi(void)
} }
PyModule_AddObject(m, "HeapDocCType", HeapDocCType); PyModule_AddObject(m, "HeapDocCType", HeapDocCType);
/* bpo-41832: Add a new type to test PyType_FromSpec()
now can accept a NULL tp_doc slot. */
PyObject *NullTpDocType = PyType_FromSpec(&NullTpDocType_spec);
if (NullTpDocType == NULL) {
return NULL;
}
PyModule_AddObject(m, "NullTpDocType", NullTpDocType);
PyObject *HeapGcCType = PyType_FromSpec(&HeapGcCType_spec); PyObject *HeapGcCType = PyType_FromSpec(&HeapGcCType_spec);
if (HeapGcCType == NULL) { if (HeapGcCType == NULL) {
return NULL; return NULL;

View File

@ -3012,6 +3012,10 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
else if (slot->slot == Py_tp_doc) { else if (slot->slot == Py_tp_doc) {
/* For the docstring slot, which usually points to a static string /* For the docstring slot, which usually points to a static string
literal, we need to make a copy */ literal, we need to make a copy */
if (slot->pfunc == NULL) {
type->tp_doc = NULL;
continue;
}
size_t len = strlen(slot->pfunc)+1; size_t len = strlen(slot->pfunc)+1;
char *tp_doc = PyObject_MALLOC(len); char *tp_doc = PyObject_MALLOC(len);
if (tp_doc == NULL) { if (tp_doc == NULL) {