From 68bcc8ec491edca74b2dc79ee9e0fa3450f0fe30 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Tue, 17 Sep 2019 13:24:45 +0200 Subject: PySide: Clean up indentation, fix refcounts and improve generated code Change-Id: I5795526cd9d18dda329c9d6694e2fc1269c9d771 Reviewed-by: Friedemann Kleint --- .../shiboken2/generator/shiboken2/cppgenerator.cpp | 44 ++++++++++++---------- 1 file changed, 24 insertions(+), 20 deletions(-) (limited to 'sources/shiboken2/generator/shiboken2/cppgenerator.cpp') diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 5a4aa8eba..dd6c5ee96 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -1860,18 +1860,19 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction // For custom classes, operations like __radd__ and __rmul__ // will enter an infinite loop. if (rfunc->isBinaryOperator() && revOpName.contains(QLatin1String("shift"))) { + s << INDENT << "Shiboken::AutoDecRef attrName(Py_BuildValue(\"s\", \"" << revOpName << "\"));" << endl; s << INDENT << "if (!isReverse" << endl; { Indentation indent(INDENT); s << INDENT << "&& Shiboken::Object::checkType(" << PYTHON_ARG << ")" << endl; s << INDENT << "&& !PyObject_TypeCheck(" << PYTHON_ARG << ", self->ob_type)" << endl; - s << INDENT << "&& PyObject_HasAttrString(" << PYTHON_ARG << ", const_cast(\"" << revOpName << "\"))) {" << endl; + s << INDENT << "&& PyObject_HasAttr(" << PYTHON_ARG << ", attrName)) {" << endl; // This PyObject_CallMethod call will emit lots of warnings like // "deprecated conversion from string constant to char *" during compilation // due to the method name argument being declared as "char *" instead of "const char *" // issue 6952 http://bugs.python.org/issue6952 - s << INDENT << "PyObject *revOpMethod = PyObject_GetAttrString(" << PYTHON_ARG << ", const_cast(\"" << revOpName << "\"));" << endl; + s << INDENT << "PyObject *revOpMethod = PyObject_GetAttr(" << PYTHON_ARG << ", attrName);" << endl; s << INDENT << "if (revOpMethod && PyCallable_Check(revOpMethod)) {" << endl; { Indentation indent(INDENT); @@ -3039,29 +3040,31 @@ void CppGenerator::writeNamedArgumentResolution(QTextStream &s, const AbstractMe QString pyArgName = usePyArgs ? pythonArgsAt(pyArgIndex) : QLatin1String(PYTHON_ARG); s << INDENT << "keyName = Py_BuildValue(\"s\",\"" << arg->name() << "\");" << endl; s << INDENT << "if (PyDict_Contains(kwds, keyName)) {" << endl; - s << INDENT << "value = PyDict_GetItemString(kwds, \"" << arg->name() << "\");" << endl; - s << INDENT << "if (value && " << pyArgName << ") {" << endl; { Indentation indent(INDENT); - s << INDENT << pyErrString.arg(arg->name()) << endl; - s << INDENT << returnStatement(m_currentErrorCode) << endl; - } - s << INDENT << INDENT << "} else if (value) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << pyArgName << " = value;" << endl; - s << INDENT << "if (!"; - writeTypeCheck(s, arg->type(), pyArgName, isNumber(arg->type()->typeEntry()), func->typeReplaced(arg->argumentIndex() + 1)); - s << ')' << endl; + s << INDENT << "value = PyDict_GetItem(kwds, keyName);" << endl; + s << INDENT << "if (value && " << pyArgName << ") {" << endl; + { + Indentation indent(INDENT); + s << INDENT << pyErrString.arg(arg->name()) << endl; + s << INDENT << returnStatement(m_currentErrorCode) << endl; + } + s << INDENT << '}' << endl; + s << INDENT << "if (value) {" << endl; { Indentation indent(INDENT); - s << INDENT << "goto " << cpythonFunctionName(func) << "_TypeError;" << endl; + s << INDENT << pyArgName << " = value;" << endl; + s << INDENT << "if (!"; + writeTypeCheck(s, arg->type(), pyArgName, isNumber(arg->type()->typeEntry()), func->typeReplaced(arg->argumentIndex() + 1)); + s << ')' << endl; + { + Indentation indent(INDENT); + s << INDENT << "goto " << cpythonFunctionName(func) << "_TypeError;" << endl; + } } + s << INDENT << '}' << endl; } s << INDENT << '}' << endl; - if (arg != args.constLast()) - s << INDENT; - s << "}" << endl; } } s << INDENT << '}' << endl; @@ -5541,10 +5544,11 @@ bool CppGenerator::finishGeneration() { Indentation indentation(INDENT); s << INDENT << "PyObject *pyType = reinterpret_cast(" << cppApiVariableName() << "[i]);" << endl; - s << INDENT << "if (pyType && PyObject_HasAttrString(pyType, \"staticMetaObject\"))"<< endl; + s << INDENT << "Shiboken::AutoDecRef attrName(Py_BuildValue(\"s\", \"staticMetaObject\"));" << endl; + s << INDENT << "if (pyType && PyObject_HasAttr(pyType, attrName))"<< endl; { Indentation indentation(INDENT); - s << INDENT << "PyObject_SetAttrString(pyType, \"staticMetaObject\", Py_None);" << endl; + s << INDENT << "PyObject_SetAttr(pyType, attrName, Py_None);" << endl; } } s << INDENT << "}" << endl; -- cgit v1.2.3 From 9c5950320814d6e0cfe7d6ebe9850ae49c18ae06 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Tue, 17 Sep 2019 14:14:04 +0200 Subject: Ignore deprecation warning about QSysInfo class Amends 1bb4368a420ef12e3714bd4edfff34b8b3c983a8 . QSysInfo is deprecated and replaced by the QOperatingSystemVersion class which already exists. Before Qt 6.0 is out, we can not remove these classes. Fortunately, the warning can be suppressed by setting QT_WARNING_DISABLE_DEPRECATED. The options was already in the generated code, but the placement was too late. The qsysinfo include happens in the line // module include #include "pyside2_qtcore_python.h" which comes right after the first "usePySideExtensions" section. Furthermore, the used template in headergenerator.cpp needed the setting when the deprecated enum ocurred. The section after "// Macros for type check" got the setting, too, so that all calls to HeaderGenerator::writeSbkTypeFunction were excluded from warnings. Change-Id: Ife96f5ade26437b23cb756ee1b94af23d4a81faa Reviewed-by: Friedemann Kleint --- sources/shiboken2/generator/shiboken2/cppgenerator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sources/shiboken2/generator/shiboken2/cppgenerator.cpp') diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index dd6c5ee96..a2b67b91b 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -317,7 +317,10 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) s << "#include " << endl; s << "#include " << endl; s << "#include " << endl; - } + s << endl; + s << "QT_WARNING_DISABLE_DEPRECATED" << endl; + s << endl; + } s << "#include " << endl; if (usePySideExtensions() && metaClass->isQObject()) { @@ -368,9 +371,6 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) if (metaClass->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated) s << "#Deprecated" << endl; - if (usePySideExtensions()) - s << "\nQT_WARNING_DISABLE_DEPRECATED\n"; - // Use class base namespace { const AbstractMetaClass *context = metaClass->enclosingClass(); -- cgit v1.2.3 From 45fdb9c06d8934e5c8de208e584d4c35943cd3b8 Mon Sep 17 00:00:00 2001 From: Andreas Beckermann Date: Thu, 12 Sep 2019 14:56:35 +0200 Subject: Remove trailing whitespace from __repr__ QDebug normally prints a trailing ' ', however the repr implementation does not expect so. Remove the trailing space, if it is there. This makes sure that e.g. PySide2.QtCore.QRegularExpression() is printed as instead of (note the double space before 'at') Change-Id: I6c088069a6a8ca42933a442cce7b576327a9d151 Reviewed-by: Christian Tismer Reviewed-by: Friedemann Kleint --- sources/shiboken2/generator/shiboken2/cppgenerator.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'sources/shiboken2/generator/shiboken2/cppgenerator.cpp') diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 68bcfe508..7de0cfc09 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -6030,6 +6030,7 @@ QString CppGenerator::writeReprFunction(QTextStream &s, GeneratorContext &contex Indentation indent(INDENT); s << INDENT << "str.replace(0, idx, Py_TYPE(self)->tp_name);" << endl; } + s << INDENT << "str = str.trimmed();" << endl; s << INDENT << "PyObject *mod = PyDict_GetItemString(Py_TYPE(self)->tp_dict, \"__module__\");" << endl; // PYSIDE-595: The introduction of heap types has the side effect that the module name // is always prepended to the type name. Therefore the strchr check: -- cgit v1.2.3 From b4989b9c2b33772f23dd5f9763622e6fd3cf41a8 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Sat, 21 Sep 2019 18:34:13 +0200 Subject: Enable the Function Registry for 5.14 The function registry was not enabled for versions greater than 5.12 . This is now needed, since the function registry will be used in the tests for the improved NumPy support. There were new cases of Python keywords touched by enums which had to be renamed. This was moved into the code generator instead of the runtime overhead. The formatting of the enums was rewritten and reports all enums now that can be found (also those which are copied into the parent class). The formatting of the function registry had not been used for a long time and had entries that showed the wrong number of subclasses. The usage of the registry was also simplified by using the full names of functions. They can now directly be accessed. Task-number: PYSIDE-795 Change-Id: I734f6811205f3c3528a911975677eb677fedd2dd Reviewed-by: Friedemann Kleint --- sources/shiboken2/generator/shiboken2/cppgenerator.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'sources/shiboken2/generator/shiboken2/cppgenerator.cpp') diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index a2b67b91b..85ce8f954 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -4611,6 +4611,15 @@ void CppGenerator::writeEnumsInitialization(QTextStream &s, AbstractMetaEnumList } } +static QString mangleName(QString name) +{ + if ( name == QLatin1String("None") + || name == QLatin1String("False") + || name == QLatin1String("True")) + name += QLatin1Char('_'); + return name; +} + void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnum *cppEnum) { const AbstractMetaClass *enclosingClass = getProperEnclosingClassForEnum(cppEnum); @@ -4690,7 +4699,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu Indentation indent(INDENT); s << INDENT << "PyObject *anonEnumItem = PyInt_FromLong(" << enumValueText << ");" << endl; s << INDENT << "if (PyDict_SetItemString(reinterpret_cast(reinterpret_cast(" << enclosingObjectVariable - << "))->tp_dict, \"" << enumValue->name() << "\", anonEnumItem) < 0)" << endl; + << "))->tp_dict, \"" << mangleName(enumValue->name()) << "\", anonEnumItem) < 0)" << endl; { Indentation indent(INDENT); s << INDENT << returnStatement(m_currentErrorCode) << endl; @@ -4699,7 +4708,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu } s << INDENT << '}' << endl; } else { - s << INDENT << "if (PyModule_AddIntConstant(module, \"" << enumValue->name() << "\", "; + s << INDENT << "if (PyModule_AddIntConstant(module, \"" << mangleName(enumValue->name()) << "\", "; s << enumValueText << ") < 0)" << endl; { Indentation indent(INDENT); @@ -4712,7 +4721,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem" : "createGlobalEnumItem"); s << '(' << enumVarTypeObj << ',' << endl; Indentation indent(INDENT); - s << INDENT << enclosingObjectVariable << ", \"" << enumValue->name() << "\", "; + s << INDENT << enclosingObjectVariable << ", \"" << mangleName(enumValue->name()) << "\", "; s << enumValueText << "))" << endl; s << INDENT << returnStatement(m_currentErrorCode) << endl; } @@ -4721,7 +4730,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu s << INDENT << "if (!Shiboken::Enum::createScopedEnumItem(" << enumVarTypeObj << ',' << endl; Indentation indent(INDENT); - s << INDENT << enumVarTypeObj<< ", \"" << enumValue->name() << "\", " + s << INDENT << enumVarTypeObj<< ", \"" << mangleName(enumValue->name()) << "\", " << enumValueText << "))" << endl << INDENT << returnStatement(m_currentErrorCode) << endl; } -- cgit v1.2.3 From 12300111a002926d38afb69e5addb60146f2b2a5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 20 Sep 2019 09:50:01 +0200 Subject: Speed: Avoid some repeated string constant initialization This patch introduces a basic concept to avoid the repetition of string constant creation in Python by using helper functions returning static instances. There is currently no real shiboken finalization, so we postpone finalization until shiboken has one: - call the finalize_strings() function - build finalization for other stuff (all signatures etc) Initial-patch-by: Christian Tismer Task-number: PYSIDE-1087 Change-Id: If3483ba91f719ee0472eb53583460ba35163bc9d Reviewed-by: Christian Tismer --- sources/shiboken2/generator/shiboken2/cppgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sources/shiboken2/generator/shiboken2/cppgenerator.cpp') diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 85ce8f954..5e9d9378e 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -6018,7 +6018,7 @@ QString CppGenerator::writeReprFunction(QTextStream &s, GeneratorContext &contex Indentation indent(INDENT); s << INDENT << "str.replace(0, idx, Py_TYPE(self)->tp_name);" << endl; } - s << INDENT << "PyObject *mod = PyDict_GetItemString(Py_TYPE(self)->tp_dict, \"__module__\");" << endl; + s << INDENT << "PyObject *mod = PyDict_GetItem(Py_TYPE(self)->tp_dict, Shiboken::PyMagicName::module());" << endl; // PYSIDE-595: The introduction of heap types has the side effect that the module name // is always prepended to the type name. Therefore the strchr check: s << INDENT << "if (mod && !strchr(str, '.'))" << endl; -- cgit v1.2.3 From e52ebf296e8fcd84fa4055c80a3c489ae1431c9e Mon Sep 17 00:00:00 2001 From: Andreas Beckermann Date: Thu, 12 Sep 2019 15:10:46 +0200 Subject: Add support for __repr__ in QObject derived classes Currently shiboken generates classes without __repr__ for QObject derived classes. However for all non-QObject classes that have an operator<<() for QDebug, it *does* add a valid repr implementation. Extend this behavior to QObject classes as well. In order for this to become more useful, also check for the indirection of operator<<(): If operator<<(QDebug, Foo*) is available, use the current non-value-type behavior, (i.e. provide cppSelf to operator<<()), but if operator<<(QDebug, const Foo&) is available instead, use the same behavior as for value-types, i.e. provide *cppSelf. This greatly increases the number of classes where operator<<() provides useful results. Also make sure to check for operator<<() in namespaces (recursively), not just at global scope. Change-Id: Ief9158455a25e332f07169f09692cafb8097078b Reviewed-by: Friedemann Kleint --- sources/shiboken2/generator/shiboken2/cppgenerator.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'sources/shiboken2/generator/shiboken2/cppgenerator.cpp') diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 7de0cfc09..61429b383 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -3933,9 +3933,10 @@ void CppGenerator::writeClassDefinition(QTextStream &s, m_tpFuncs[func->name()] = cpythonFunctionName(func); } if (m_tpFuncs.value(QLatin1String("__repr__")).isEmpty() - && !metaClass->isQObject() && metaClass->hasToStringCapability()) { - m_tpFuncs[QLatin1String("__repr__")] = writeReprFunction(s, classContext); + m_tpFuncs[QLatin1String("__repr__")] = writeReprFunction(s, + classContext, + metaClass->toStringCapabilityIndirections()); } // class or some ancestor has multiple inheritance @@ -6006,7 +6007,9 @@ void CppGenerator::writeIndexError(QTextStream &s, const QString &errorMsg) s << INDENT << '}' << endl; } -QString CppGenerator::writeReprFunction(QTextStream &s, GeneratorContext &context) +QString CppGenerator::writeReprFunction(QTextStream &s, + GeneratorContext &context, + uint indirections) { const AbstractMetaClass *metaClass = context.metaClass(); QString funcName = cpythonBaseName(metaClass) + QLatin1String("__repr__"); @@ -6019,7 +6022,7 @@ QString CppGenerator::writeReprFunction(QTextStream &s, GeneratorContext &contex s << INDENT << "buffer.open(QBuffer::ReadWrite);" << endl; s << INDENT << "QDebug dbg(&buffer);" << endl; s << INDENT << "dbg << "; - if (metaClass->typeEntry()->isValue()) + if (metaClass->typeEntry()->isValue() || indirections == 0) s << '*'; s << CPP_SELF_VAR << ';' << endl; s << INDENT << "buffer.close();" << endl; -- cgit v1.2.3 From 46d44749d01b7bd195e8838e681b227aef4b5f06 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Sat, 10 Aug 2019 18:09:17 +0200 Subject: Improve the NumPy Support by iterables Working example, by overriding cppgenerator: >>> from PySide2 import * >>> QtCore.QUrl.fromStringList(("asd", "def")) [PySide2.QtCore.QUrl('asd'), PySide2.QtCore.QUrl('def')] >>> def func(lis): ... for thing in lis: ... yield thing ... >>> QtCore.QUrl.fromStringList(func(["asd", "def"])) [PySide2.QtCore.QUrl('asd'), PySide2.QtCore.QUrl('def')] Also working, by overriding shibokengenerator >>> QtGui.QMatrix4x4(func(range(16))) And all other QMatrix sizes as well: >>> QtGui.QMatrix2x2(func(range(4))) >>> QtGui.QMatrix2x3(func(range(6))) The PySequence cases seem to be quite completely covered. Supporting lists and QVector is not yet clear and needs more research. Note.. QtOpenGLFunctions is not tested at all and nothing works on macOS, segfault. Ignored for now! A simple numpy test shows how versatile this solution is. We now need to improve signatures and error messages to optimize the experience. Task-number: PYSIDE-795 Change-Id: I195cd46cf47c2eb83276fe48fce8e6070cf30fda Reviewed-by: Cristian Maureira-Fredes --- sources/shiboken2/generator/shiboken2/cppgenerator.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sources/shiboken2/generator/shiboken2/cppgenerator.cpp') diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 547aecc61..146a53d2d 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -2155,6 +2155,8 @@ void CppGenerator::writeTypeCheck(QTextStream &s, const AbstractMetaType *argTyp QString customCheck; if (!customType.isEmpty()) { AbstractMetaType *metaType; + // PYSIDE-795: Note: XML-Overrides are handled in this shibokengenerator function! + // This enables iterables for QMatrix4x4 for instance. customCheck = guessCPythonCheckFunction(customType, &metaType); if (metaType) argType = metaType; @@ -2940,6 +2942,9 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s, typeCheck = QLatin1String("PyType_Check(%in)"); else if (pyTypeName == QLatin1String("PyObject")) typeCheck = QLatin1String("PyObject_TypeCheck(%in, &PyBaseObject_Type)"); + // PYSIDE-795: We abuse PySequence for iterables + else if (pyTypeName == QLatin1String("PySequence")) + typeCheck = QLatin1String("Shiboken::String::checkIterable(%in)"); else if (pyTypeName.startsWith(QLatin1String("Py"))) typeCheck = pyTypeName + QLatin1String("_Check(%in)"); } -- cgit v1.2.3