From 9a37b64bbee7573578f63334b76a3eca533ea539 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Fri, 28 Aug 2020 15:22:14 +0200 Subject: shiboken: Fix __doc__ setter for derived types This setter makes sure that __doc__ for derived SbkObject types behaves like a data descriptor. Change-Id: I4ca1d4a224755304d9a9223b9fd6244af94d981f Fixes: PYSIDE-1177 Task-number: PYSIDE-908 Reviewed-by: Friedemann Kleint Reviewed-by: Cristian Maureira-Fredes --- sources/shiboken2/libshiboken/basewrapper.cpp | 28 +++++++++++++++++++++- sources/shiboken2/libshiboken/sbkstaticstrings.cpp | 2 ++ sources/shiboken2/libshiboken/sbkstaticstrings.h | 2 ++ sources/shiboken2/libshiboken/signature.cpp | 5 ++-- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index 1960e5932..961c6c739 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -99,12 +99,38 @@ static SelectableFeatureHook SelectFeatureSet = nullptr; static PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void *context); // forward +static int +check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *name) +{ + if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { + PyErr_Format(PyExc_TypeError, + "can't set %s.%s", type->tp_name, name); + return 0; + } + if (!value) { + PyErr_Format(PyExc_TypeError, + "can't delete %s.%s", type->tp_name, name); + return 0; + } + return 1; +} + +// PYSIDE-1177: Add a setter to allow setting type doc. +static int +type_set_doc(PyTypeObject *type, PyObject *value, void *context) +{ + if (!check_set_special_type_attr(type, value, "__doc__")) + return -1; + PyType_Modified(type); + return PyDict_SetItem(type->tp_dict, Shiboken::PyMagicName::doc(), value); +} + // PYSIDE-908: The function PyType_Modified does not work in PySide, so we need to // explicitly pass __doc__. For __signature__ it _did_ actually work, because // it was not existing before. We add them both for clarity. static PyGetSetDef SbkObjectType_Type_getsetlist[] = { {const_cast("__signature__"), (getter)Sbk_TypeGet___signature__}, - {const_cast("__doc__"), (getter)Sbk_TypeGet___doc__}, + {const_cast("__doc__"), (getter)Sbk_TypeGet___doc__, (setter)type_set_doc}, {const_cast("__dict__"), (getter)Sbk_TypeGet___dict__}, {nullptr} // Sentinel }; diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp index 9dd98eef3..602c0619b 100644 --- a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp +++ b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp @@ -78,8 +78,10 @@ namespace PyMagicName { // exported: STATIC_STRING_IMPL(class_, "__class__") STATIC_STRING_IMPL(dict, "__dict__") +STATIC_STRING_IMPL(doc, "__doc__") STATIC_STRING_IMPL(ecf, "__ecf__") STATIC_STRING_IMPL(file, "__file__") +STATIC_STRING_IMPL(get, "__get__") STATIC_STRING_IMPL(members, "__members__") STATIC_STRING_IMPL(module, "__module__") STATIC_STRING_IMPL(name, "__name__") diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.h b/sources/shiboken2/libshiboken/sbkstaticstrings.h index ebb64579c..df0c683b0 100644 --- a/sources/shiboken2/libshiboken/sbkstaticstrings.h +++ b/sources/shiboken2/libshiboken/sbkstaticstrings.h @@ -64,8 +64,10 @@ namespace PyMagicName { LIBSHIBOKEN_API PyObject *class_(); LIBSHIBOKEN_API PyObject *dict(); +LIBSHIBOKEN_API PyObject *doc(); LIBSHIBOKEN_API PyObject *ecf(); LIBSHIBOKEN_API PyObject *file(); +LIBSHIBOKEN_API PyObject *get(); LIBSHIBOKEN_API PyObject *members(); LIBSHIBOKEN_API PyObject *module(); LIBSHIBOKEN_API PyObject *name(); diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp index e4dc27ea7..e2c02a196 100644 --- a/sources/shiboken2/libshiboken/signature.cpp +++ b/sources/shiboken2/libshiboken/signature.cpp @@ -731,8 +731,9 @@ handle_doc(PyObject *ob, PyObject *old_descr) name = reinterpret_cast(ob_type_mod.object())->tp_name; if (handle_doc_in_progress || name == nullptr || strncmp(name, "PySide2.", 8) != 0) - return PyObject_CallMethod(old_descr, const_cast("__get__"), - const_cast("(O)"), ob); + return PyObject_CallMethodObjArgs(old_descr, + Shiboken::PyMagicName::get(), + ob, nullptr); handle_doc_in_progress++; PyObject *res = PyObject_CallFunction( pyside_globals->make_helptext_func, -- cgit v1.2.3