bpo-41832: PyType_FromModuleAndSpec() now accepts NULL tp_doc (GH-23123)
This commit is contained in:
parent
803187796f
commit
88c2cfd9ff
|
@ -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``.
|
|
||||||
|
|
|
@ -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
|
||||||
----------------------
|
----------------------
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
The :c:func:`PyType_FromModuleAndSpec` function now accepts NULL ``tp_doc``
|
||||||
|
slot.
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue