diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2023-09-19 15:02:53 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2023-10-02 10:32:12 +0200 |
commit | 25a64e5eaddcb403095c2d9f32ba90a0d7c7b340 (patch) | |
tree | e286a14532e0067df53a77755718535f24943b77 /sources/shiboken6/generator/shiboken | |
parent | 1961d9ad766e59a9d72dfa2eb2317ba34e9e377d (diff) |
Add a __repr__ function for smart pointers
Add a generic repr function to the string utilities of libshiboken.
Add a new module sbksmartpointer with a specialized repr function
adding pointee information to libshiboken.
Generate code to call it into the smart pointer code.
Pick-to: 6.6
Task-number: PYSIDE-2462
Change-Id: Ie7b8956051bc1b7ef817c15d26deb1dc3099fd30
Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'sources/shiboken6/generator/shiboken')
3 files changed, 54 insertions, 16 deletions
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index 95eb61f9a..9a84c97ab 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -4289,8 +4289,9 @@ void CppGenerator::writeClassDefinition(TextStream &s, if (generateRichComparison(classContext)) tp_richcompare = cpythonBaseName(metaClass) + u"_richcompare"_s; + const bool isSmartPointer = classContext.forSmartPointer(); QString tp_getset; - if (shouldGenerateGetSetList(metaClass) && !classContext.forSmartPointer()) + if (shouldGenerateGetSetList(metaClass) && !isSmartPointer) tp_getset = cpythonGettersSettersDefinitionName(metaClass); // search for special functions @@ -4304,10 +4305,11 @@ void CppGenerator::writeClassDefinition(TextStream &s, it.value() = cpythonFunctionName(func); } if (m_tpFuncs.value(REPR_FUNCTION).isEmpty() - && metaClass->hasToStringCapability()) { - m_tpFuncs[REPR_FUNCTION] = writeReprFunction(s, - classContext, - metaClass->toStringCapabilityIndirections()); + && (isSmartPointer || metaClass->hasToStringCapability())) { + const QString name = isSmartPointer + ? writeSmartPointerReprFunction(s, classContext) + : writeReprFunction(s, classContext, metaClass->toStringCapabilityIndirections()); + m_tpFuncs[REPR_FUNCTION] = name; } // class or some ancestor has multiple inheritance @@ -6499,14 +6501,20 @@ void CppGenerator::writeIndexError(TextStream &s, const QString &errorMsg, << errorReturn << outdent << "}\n"; } +QString CppGenerator::writeReprFunctionHeader(TextStream &s, const GeneratorContext &context) +{ + QString funcName = cpythonBaseName(context.metaClass()) + REPR_FUNCTION; + s << "extern \"C\"\n{\n" + << "static PyObject *" << funcName << "(PyObject *self)\n{\n" << indent; + return funcName; +} + QString CppGenerator::writeReprFunction(TextStream &s, const GeneratorContext &context, uint indirections) { const auto metaClass = context.metaClass(); - QString funcName = cpythonBaseName(metaClass) + REPR_FUNCTION; - s << "extern \"C\"\n{\n" - << "static PyObject *" << funcName << "(PyObject *self)\n{\n" << indent; + QString funcName = writeReprFunctionHeader(s, context); writeCppSelfDefinition(s, context); s << R"(QBuffer buffer; buffer.open(QBuffer::ReadWrite); @@ -6529,7 +6537,12 @@ if (idx >= 0) << "return Shiboken::String::fromFormat(\"<%s.%s at %p>\"," " Shiboken::String::toCString(mod), str.constData(), self);\n" << outdent - << "return Shiboken::String::fromFormat(\"<%s at %p>\", str.constData(), self);\n" - << outdent << "}\n} // extern C\n\n"; + << "return Shiboken::String::fromFormat(\"<%s at %p>\", str.constData(), self);\n"; + writeReprFunctionFooter(s); return funcName; } + +void CppGenerator::writeReprFunctionFooter(TextStream &s) +{ + s << outdent << "}\n} // extern C\n\n"; +} diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index d66cfb90b..62e7a4309 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -507,9 +507,13 @@ private: static void writeIndexError(TextStream &s, const QString &errorMsg, ErrorReturn errorReturn); + static QString writeReprFunctionHeader(TextStream &s, const GeneratorContext &context); static QString writeReprFunction(TextStream &s, const GeneratorContext &context, uint indirections); + static QString writeSmartPointerReprFunction(TextStream &s, + const GeneratorContext &context); + static void writeReprFunctionFooter(TextStream &s); static void writePyMethodDefs(TextStream &s, const QString &className, const QString &methodsDefinitions); diff --git a/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp b/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp index ea65733e2..834345991 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp @@ -29,6 +29,19 @@ static QString smartPointerGetter(const GeneratorContext &context) return std::static_pointer_cast<const SmartPointerTypeEntry>(te)->getter(); } +struct callGetter +{ + explicit callGetter(const GeneratorContext &context) : m_context(context) {} + + const GeneratorContext &m_context; +}; + +TextStream &operator<<(TextStream &str, const callGetter &c) +{ + str << "PyObject_CallMethod(self, \"" << smartPointerGetter(c.m_context) << "\", 0)"; + return str; +} + // Helpers to collect all smart pointer pointee base classes static AbstractMetaClassCList findSmartPointeeBaseClasses(const ApiExtractorResult &api, @@ -102,6 +115,7 @@ void CppGenerator::generateSmartPointerClass(TextStream &s, const GeneratorConte IncludeGroup includes{u"Extra includes"_s, typeEntry->extraIncludes()}; if (hasPointeeClass) includes.append(classContext.pointeeClass()->typeEntry()->include()); + includes.includes.append({Include::IncludePath, u"sbksmartpointer.h"_s}); generateIncludes(s, classContext, {includes}); s << '\n'; @@ -390,9 +404,7 @@ void CppGenerator::writeSmartPointerSetattroFunction(TextStream &s, Q_ASSERT(context.forSmartPointer()); writeSetattroDefinition(s, context.metaClass()); s << smartPtrComment - << "if (auto *rawObj = PyObject_CallMethod(self, \"" - << smartPointerGetter(context) - << "\", 0)) {\n" << indent + << "if (auto *rawObj = " << callGetter(context) << ") {\n" << indent << "if (PyObject_HasAttr(rawObj, name) != 0)\n" << indent << "return PyObject_GenericSetAttr(rawObj, name, value);\n" << outdent << "Py_DECREF(rawObj);\n" << outdent @@ -428,9 +440,7 @@ return nullptr; // This generates the code which dispatches access to member functions // and fields from the smart pointer to its pointee. s << smartPtrComment - << "if (auto *rawObj = PyObject_CallMethod(self, \"" - << smartPointerGetter(context) - << "\", 0)) {\n" << indent + << "if (auto *rawObj = " << callGetter(context) << ") {\n" << indent << "if (auto *attribute = PyObject_GetAttr(rawObj, name))\n" << indent << "tmp = attribute;\n" << outdent << "Py_DECREF(rawObj);\n" << outdent @@ -444,3 +454,14 @@ PyErr_Format(PyExc_AttributeError, << "}\n" << "return tmp;\n" << outdent << "}\n\n"; } + +QString CppGenerator::writeSmartPointerReprFunction(TextStream &s, + const GeneratorContext &context) +{ + const auto metaClass = context.metaClass(); + QString funcName = writeReprFunctionHeader(s, context); + s << "Shiboken::AutoDecRef pointee(" << callGetter(context) << ");\n" + << "return Shiboken::SmartPointer::repr(self, pointee);\n"; + writeReprFunctionFooter(s); + return funcName; +} |