closes bpo-41689: Preserve text signature from tp_doc in C heap type creation. (GH-22058)
This commit is contained in:
parent
5a4a963a6c
commit
3940333637
|
@ -401,6 +401,10 @@ class CAPITest(unittest.TestCase):
|
|||
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_subclass_of_heap_gc_ctype_with_tpdealloc_decrefs_once(self):
|
||||
class HeapGcCTypeSubclass(_testcapi.HeapGcCType):
|
||||
def __init__(self):
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Types created with :c:func:`PyType_FromSpec` now make any signature in their
|
||||
``tp_doc`` slot accessible from ``__text_signature__``.
|
|
@ -6462,6 +6462,30 @@ 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
|
||||
};
|
||||
|
||||
|
||||
PyDoc_STRVAR(heapgctype__doc__,
|
||||
"A heap type with GC, and with overridden dealloc.\n\n"
|
||||
"The 'value' attribute is set to 10 in __init__.");
|
||||
|
@ -7130,6 +7154,12 @@ 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);
|
||||
|
||||
PyObject *HeapGcCType = PyType_FromSpec(&HeapGcCType_spec);
|
||||
if (HeapGcCType == NULL) {
|
||||
return NULL;
|
||||
|
|
|
@ -3018,15 +3018,14 @@ 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 */
|
||||
const char *old_doc = _PyType_DocWithoutSignature(type->tp_name, slot->pfunc);
|
||||
size_t len = strlen(old_doc)+1;
|
||||
size_t len = strlen(slot->pfunc)+1;
|
||||
char *tp_doc = PyObject_MALLOC(len);
|
||||
if (tp_doc == NULL) {
|
||||
type->tp_doc = NULL;
|
||||
PyErr_NoMemory();
|
||||
goto fail;
|
||||
}
|
||||
memcpy(tp_doc, old_doc, len);
|
||||
memcpy(tp_doc, slot->pfunc, len);
|
||||
type->tp_doc = tp_doc;
|
||||
}
|
||||
else if (slot->slot == Py_tp_members) {
|
||||
|
@ -3058,6 +3057,16 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
|
|||
res->ht_cached_keys = _PyDict_NewKeysForClass();
|
||||
}
|
||||
|
||||
if (type->tp_doc) {
|
||||
PyObject *__doc__ = PyUnicode_FromString(_PyType_DocWithoutSignature(type->tp_name, type->tp_doc));
|
||||
if (!__doc__)
|
||||
goto fail;
|
||||
int ret = _PyDict_SetItemId(type->tp_dict, &PyId___doc__, __doc__);
|
||||
Py_DECREF(__doc__);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (weaklistoffset) {
|
||||
type->tp_weaklistoffset = weaklistoffset;
|
||||
if (PyDict_DelItemString((PyObject *)type->tp_dict, "__weaklistoffset__") < 0)
|
||||
|
|
Loading…
Reference in New Issue