mirror of https://github.com/python/cpython
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
|
del L
|
||||||
self.assertEqual(PyList.num, 0)
|
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):
|
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 @@
|
||||||
|
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,
|
.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__,
|
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"
|
||||||
"The 'value' attribute is set to 10 in __init__.");
|
"The 'value' attribute is set to 10 in __init__.");
|
||||||
|
@ -7130,6 +7154,12 @@ PyInit__testcapi(void)
|
||||||
Py_INCREF(TestError);
|
Py_INCREF(TestError);
|
||||||
PyModule_AddObject(m, "error", 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);
|
PyObject *HeapGcCType = PyType_FromSpec(&HeapGcCType_spec);
|
||||||
if (HeapGcCType == NULL) {
|
if (HeapGcCType == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -3018,15 +3018,14 @@ 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 */
|
||||||
const char *old_doc = _PyType_DocWithoutSignature(type->tp_name, slot->pfunc);
|
size_t len = strlen(slot->pfunc)+1;
|
||||||
size_t len = strlen(old_doc)+1;
|
|
||||||
char *tp_doc = PyObject_MALLOC(len);
|
char *tp_doc = PyObject_MALLOC(len);
|
||||||
if (tp_doc == NULL) {
|
if (tp_doc == NULL) {
|
||||||
type->tp_doc = NULL;
|
type->tp_doc = NULL;
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
memcpy(tp_doc, old_doc, len);
|
memcpy(tp_doc, slot->pfunc, len);
|
||||||
type->tp_doc = tp_doc;
|
type->tp_doc = tp_doc;
|
||||||
}
|
}
|
||||||
else if (slot->slot == Py_tp_members) {
|
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();
|
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) {
|
if (weaklistoffset) {
|
||||||
type->tp_weaklistoffset = weaklistoffset;
|
type->tp_weaklistoffset = weaklistoffset;
|
||||||
if (PyDict_DelItemString((PyObject *)type->tp_dict, "__weaklistoffset__") < 0)
|
if (PyDict_DelItemString((PyObject *)type->tp_dict, "__weaklistoffset__") < 0)
|
||||||
|
|
Loading…
Reference in New Issue