Skip to content

Commit

Permalink
bpo-41832: PyType_FromModuleAndSpec() now accepts NULL tp_doc (python…
Browse files Browse the repository at this point in the history
  • Loading branch information
shihai1991 authored and Fidget-Spinner committed May 3, 2021
1 parent e6aa45f commit a2b620c
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 2 deletions.
6 changes: 4 additions & 2 deletions Doc/c-api/type.rst
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ The following functions and structs are used to create
.. versionadded:: 3.9
.. versionchanged:: 3.10
The function now accepts NULL ``tp_doc`` slot.
.. c:function:: PyObject* PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
Equivalent to ``PyType_FromModuleAndSpec(NULL, spec, bases)``.
Expand Down Expand Up @@ -263,5 +267,3 @@ The following functions and structs are used to create
The desired value of the slot. In most cases, this is a pointer
to a function.
May not be ``NULL``.
7 changes: 7 additions & 0 deletions Lib/test/test_capi.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,13 @@ def __del__(self):
del L
self.assertEqual(PyList.num, 0)

def test_heap_ctype_doc_and_text_signature(self):
self.assertEqual(_testcapi.HeapDocCType.__doc__, "somedoc")
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):
class HeapGcCTypeSubclass(_testcapi.HeapGcCType):
def __init__(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The :c:func:`PyType_FromModuleAndSpec` function now accepts NULL ``tp_doc``
slot.
55 changes: 55 additions & 0 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -6215,6 +6215,47 @@ static PyTypeObject MethodDescriptor2_Type = {
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL,
};

PyDoc_STRVAR(heapdocctype__doc__,
"HeapDocCType(arg1, arg2)\n"
"--\n"
"\n"
"somedoc");

typedef struct {
PyObject_HEAD
} HeapDocCTypeObject;

static PyType_Slot HeapDocCType_slots[] = {
{Py_tp_doc, (char*)heapdocctype__doc__},
{0},
};

static PyType_Spec HeapDocCType_spec = {
"_testcapi.HeapDocCType",
sizeof(HeapDocCTypeObject),
0,
Py_TPFLAGS_DEFAULT,
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__,
"A heap type with GC, and with overridden dealloc.\n\n"
"The 'value' attribute is set to 10 in __init__.");
Expand Down Expand Up @@ -6883,6 +6924,20 @@ PyInit__testcapi(void)
Py_INCREF(TestError);
PyModule_AddObject(m, "error", TestError);

PyObject *HeapDocCType = PyType_FromSpec(&HeapDocCType_spec);
if (HeapDocCType == NULL) {
return NULL;
}
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);
if (HeapGcCType == NULL) {
return NULL;
Expand Down
4 changes: 4 additions & 0 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3015,6 +3015,10 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
else if (slot->slot == Py_tp_doc) {
/* For the docstring slot, which usually points to a static string
literal, we need to make a copy */
if (slot->pfunc == NULL) {
type->tp_doc = NULL;
continue;
}
const char *old_doc = _PyType_DocWithoutSignature(type->tp_name, slot->pfunc);
size_t len = strlen(old_doc)+1;
char *tp_doc = PyObject_MALLOC(len);
Expand Down

0 comments on commit a2b620c

Please sign in to comment.