diff options
Diffstat (limited to 'sources')
17 files changed, 422 insertions, 104 deletions
diff --git a/sources/pyside2/doc/deployment-briefcase.rst b/sources/pyside2/doc/deployment-briefcase.rst new file mode 100644 index 000000000..fec5e0d56 --- /dev/null +++ b/sources/pyside2/doc/deployment-briefcase.rst @@ -0,0 +1,199 @@ +|project| & Briefcase +####################### + +`Briefcase <https://briefcase.readthedocs.io>`_ is a packaging tool that lets you create a standalone package for a Python application. It supports the following installer formats: + + * .app application bundle for macOS + * MSI installer for Windows + * AppImage for Linux + +For more details, see the `official documentation <https://briefcase.readthedocs.io/en/latest/index.html>`_. + +Preparation +=========== + +Install `Briefcase` using the following **pip** command:: + + pip install briefcase + +You also need : docker on linux, `WixToolset`_ on windows, + +If you're using a virtual environment, remember to activate it before installing `Briefcase`. + +After installation, the `briefcase` binary is located in your virtual environment's `bin/` +directory, or where your Python executable is located. + +You can either create a brand new project using the briefcase assistant or setup your own. + +.. _`WixToolset`: https://wixtoolset.org/ + +Use Briefcase Assistant +======================= + +Run the following command and answer the questions to get started:: + + briefcase new + +Ensure that `PySide2` is chosen as the `GUI toolkit choice`. +Your PySide2 application is now configured. You can jump to `Build the package`_. + + +Set up your project +=================== + +Create a pyproject.toml +----------------------- + +At the root level of your project, create a `pyproject.toml` file:: + + [tool.briefcase] + project_name = "MyPySideApp" + bundle = "com.example" + version = "0.0.1" + url = "https://somwhere/on/the/net" + license = "GNU General Public License v3 (GPLv3)" + author = 'MyName Firstname' + author_email = "cool@mailexample.com" + + [tool.briefcase.app.mypysideapp] + formal_name = "A Cool App" + description = "The coolest app ever" + icon = "src/mypysideapp/resources/appicon" # Briecase will choose the right extension depending the os (png,ico,...) + sources = ['src/mypysideapp'] + requires = ['pyside2==5.15.0', + 'pony>=0.7.11,<0.8', + 'dickens==1.0.1', + 'Pillow==7.1.2', + 'mako==1.1.2', + 'beautifulsoup4'] + + + [tool.briefcase.app.mypysideapp.macOS] + requires = [] + + [tool.briefcase.app.mypysideapp.linux] + requires = [] + system_requires = [] + + [tool.briefcase.app.mypysideapp.windows] + requires = [] + + +Write some code +---------------- + +Let's say your project tree is like this:: + + pyproject.toml + setup.cfg + pytest.ini + src/ + + mypysideapp/ + resources/ + appicon.png + appicon.ico + __init__.py + __main__.py + app.py + + +Content of `__main__.py`:: + + import sys + from PySide2.QtWidgets import QApplication + from mypysideapp.app import MyWidget + + if __name__ == "__main__": + app = QApplication(sys.argv) + + widget = MyWidget() + widget.resize(800, 600) + widget.show() + + sys.exit(app.exec_()) + + +Content of `app.py`:: + + import random + from PySide2.QtWidgets import (QLabel, QPushButton, + QVBoxLayout, QWidget) + from PySide2.QtCore import Slot, Qt + + class MyWidget(QWidget): + def __init__(self): + QWidget.__init__(self) + + self.hello = ["Hallo Welt", "你好,世界", "Hei maailma", + "Hola Mundo", "Привет мир"] + + self.button = QPushButton("Click me!") + self.text = QLabel("Hello World") + self.text.setAlignment(Qt.AlignCenter) + + self.layout = QVBoxLayout() + self.layout.addWidget(self.text) + self.layout.addWidget(self.button) + self.setLayout(self.layout) + + # Connecting the signal + self.button.clicked.connect(self.magic) + + @Slot() + def magic(self): + self.text.setText(random.choice(self.hello)) + + +Build the package +================== + +Initialize the package +------------------------ + +Just run:: + + briefcase create + +Run the following command to initialize the building the packages for Windows, Linux, and macOS. +It creates a subdirectory each for the different platforms. +This step takes longer as it adds the packages listed in `requires` sections in the `pyproject.toml` file. + +Build the application +--------------- +:: + + briefcase build + +You'll get:: + + macOS/A Cool App/A Cool App.app + or + linux/A Cool App-x86_64-0.0.1.AppImage + or + windows\A Cool App + + +Run the application +----------- +:: + + briefcase run + +.. note:: You can run your project in `dev` mode (your source code not packaged) with `briefcase dev` + + +Build the installer (only Windows and macOS) +--------------------------------------------- + +macOS:: + + briefcase package --no-sign + +It's possible to sign, see the `documentation <https://briefcase.readthedocs.io/en/latest/how-to/code-signing/index.html>`_. You get `macOS/A Cool App-0.0.1.dmg` + +Windows:: + + briefcase package + +You get `windows\A_Cool_App-0.0.1.msi` diff --git a/sources/pyside2/doc/deployment.rst b/sources/pyside2/doc/deployment.rst index 78d6058da..414a468ed 100644 --- a/sources/pyside2/doc/deployment.rst +++ b/sources/pyside2/doc/deployment.rst @@ -12,6 +12,7 @@ Here are a few distribution options that you can use: 1. Send a normal ZIP file with the application's content. 2. Build a proper `Python package (wheel) <https://packaging.python.org/>`_. 3. Freeze the application into a single binary file or directory. + 4. Provide native installer (msi, dmg) If you choose Option 3, consider using one of these tools: * `fbs`_ @@ -19,12 +20,14 @@ If you choose Option 3, consider using one of these tools: * `cx_Freeze`_ * `py2exe`_ * `py2app`_ + * `briefcase`_ .. _fbs: https://build-system.fman.io/ .. _PyInstaller: https://www.pyinstaller.org/ .. _cx_Freeze: https://anthony-tuininga.github.io/cx_Freeze/ .. _py2exe: http://www.py2exe.org/ .. _py2app: https://py2app.readthedocs.io/en/latest/ +.. _briefcase: https://briefcase.readthedocs.io Since |project| is a cross-platform framework, we focus on solutions for the three major platforms that Qt supports: Windows, Linux, and macOS. @@ -79,10 +82,17 @@ The following table summarizes the platform support for those packaging tools: <td><p style="color: green;">yes</p></td> <td><p style="color: red;">no</p></td> </tr> + <tr> + <td><p>briefcase</p></td> + <td><p>BSD3</p></td> + <td><p style="color: green;">yes</p></td> + <td><p style="color: green;">yes</p></td> + <td><p style="color: green;">yes</p></td> + </tr> </tbody> </table> -Notice that only *fbs*, *cx_Freeze*, and *PyInstaller* meet our cross-platform requirement. +Notice that only *fbs*, *cx_Freeze*, *briefcase*, and *PyInstaller* meet our cross-platform requirement. Since these are command-line tools, you'll need special hooks or scripts to handle resources such as images, icons, and meta-information, before adding them to your package. Additionally, @@ -107,3 +117,4 @@ Here's a set of tutorials on how to use these tools: deployment-fbs.rst deployment-pyinstaller.rst deployment-cxfreeze.rst + deployment-briefcase.rst diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 2364cec7a..f9e34ba5a 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -1069,7 +1069,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem } metaClass->setTemplateArguments(template_args); - parseQ_Property(metaClass, classItem->propertyDeclarations()); + parseQ_Properties(metaClass, classItem->propertyDeclarations()); traverseEnums(classItem, metaClass, classItem->enumsDeclarations()); @@ -2782,51 +2782,77 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, return true; } -void AbstractMetaBuilderPrivate::parseQ_Property(AbstractMetaClass *metaClass, - const QStringList &declarations) +void AbstractMetaBuilderPrivate::parseQ_Properties(AbstractMetaClass *metaClass, + const QStringList &declarations) { const QStringList scopes = currentScope()->qualifiedName(); - + QString errorMessage; for (int i = 0; i < declarations.size(); ++i) { - const auto propertyTokens = declarations.at(i).splitRef(QLatin1Char(' ')); - - AbstractMetaType *type = nullptr; - for (int j = scopes.size(); j >= 0; --j) { - QStringList qualifiedName = scopes.mid(0, j); - qualifiedName.append(propertyTokens.at(0).toString()); - TypeInfo info; - info.setQualifiedName(qualifiedName); - - type = translateType(info, metaClass); - if (type) - break; + if (auto spec = parseQ_Property(metaClass, declarations.at(i), scopes, &errorMessage)) { + spec->setIndex(i); + metaClass->addPropertySpec(spec); + } else { + QString message; + QTextStream str(&message); + str << metaClass->sourceLocation() << errorMessage; + qCWarning(lcShiboken, "%s", qPrintable(message)); } + } +} - if (!type) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Unable to decide type of property: '%1' in class '%2'") - .arg(propertyTokens.at(0).toString(), metaClass->name()); - continue; - } +QPropertySpec *AbstractMetaBuilderPrivate::parseQ_Property(AbstractMetaClass *metaClass, + const QString &declaration, + const QStringList &scopes, + QString *errorMessage) +{ + errorMessage->clear(); - auto *spec = new QPropertySpec(type->typeEntry()); - spec->setName(propertyTokens.at(1).toString()); - spec->setIndex(i); + // Q_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged) - for (int pos = 2; pos + 1 < propertyTokens.size(); pos += 2) { - if (propertyTokens.at(pos) == QLatin1String("READ")) - spec->setRead(propertyTokens.at(pos + 1).toString()); - else if (propertyTokens.at(pos) == QLatin1String("WRITE")) - spec->setWrite(propertyTokens.at(pos + 1).toString()); - else if (propertyTokens.at(pos) == QLatin1String("DESIGNABLE")) - spec->setDesignable(propertyTokens.at(pos + 1).toString()); - else if (propertyTokens.at(pos) == QLatin1String("RESET")) - spec->setReset(propertyTokens.at(pos + 1).toString()); - } + auto propertyTokens = declaration.splitRef(QLatin1Char(' '), Qt::SkipEmptyParts); + if (propertyTokens.size() < 4) { + *errorMessage = QLatin1String("Insufficient number of tokens"); + return nullptr; + } - metaClass->addPropertySpec(spec); - delete type; + const QString typeName = propertyTokens.takeFirst().toString(); + const QString name = propertyTokens.takeFirst().toString(); + + QScopedPointer<AbstractMetaType> type; + for (int j = scopes.size(); j >= 0 && type.isNull(); --j) { + QStringList qualifiedName = scopes.mid(0, j); + qualifiedName.append(typeName); + TypeInfo info; + info.setQualifiedName(qualifiedName); + type.reset(translateType(info, metaClass)); + } + + if (!type) { + QTextStream str(errorMessage); + str << "Unable to decide type of property: \"" << name << "\" (" + << typeName << ')'; + return nullptr; + } + + QScopedPointer<QPropertySpec> spec(new QPropertySpec(type->typeEntry())); + spec->setName(name); + + for (int pos = 0; pos + 1 < propertyTokens.size(); pos += 2) { + if (propertyTokens.at(pos) == QLatin1String("READ")) + spec->setRead(propertyTokens.at(pos + 1).toString()); + else if (propertyTokens.at(pos) == QLatin1String("WRITE")) + spec->setWrite(propertyTokens.at(pos + 1).toString()); + else if (propertyTokens.at(pos) == QLatin1String("DESIGNABLE")) + spec->setDesignable(propertyTokens.at(pos + 1).toString()); + else if (propertyTokens.at(pos) == QLatin1String("RESET")) + spec->setReset(propertyTokens.at(pos + 1).toString()); + } + + if (!spec->isValid()) { + *errorMessage = QLatin1String("Incomplete specification"); + return nullptr; } + return spec.take(); } static AbstractMetaFunction* findCopyCtor(AbstractMetaClass* cls) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index 2686ebacb..2867e5f74 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -125,7 +125,9 @@ public: */ void fixReturnTypeOfConversionOperator(AbstractMetaFunction *metaFunction); - void parseQ_Property(AbstractMetaClass *metaClass, const QStringList &declarations); + void parseQ_Properties(AbstractMetaClass *metaClass, const QStringList &declarations); + QPropertySpec *parseQ_Property(AbstractMetaClass *metaClass, const QString &declaration, + const QStringList &scopes, QString *errorMessage); void setupEquals(AbstractMetaClass *metaClass); void setupComparable(AbstractMetaClass *metaClass); void setupClonable(AbstractMetaClass *cls); diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index a202c42d5..8e1f0d7e5 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -2735,6 +2735,11 @@ QString AbstractMetaEnum::package() const return m_typeEntry->targetLangPackage(); } +bool QPropertySpec::isValid() const +{ + return m_type != nullptr && !m_name.isEmpty() && !m_read.isEmpty(); +} + #ifndef QT_NO_DEBUG_STREAM void QPropertySpec::formatDebug(QDebug &d) const { diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 8169c4a30..d99a54fc2 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -1742,6 +1742,8 @@ class QPropertySpec public: explicit QPropertySpec(const TypeEntry *type) : m_type(type) {} + bool isValid() const; + const TypeEntry *type() const { return m_type; diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 001c6d902..54af34180 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -793,7 +793,7 @@ void CppGenerator::writeVirtualMethodCppCall(QTextStream &s, const CodeSnipList &snips, const AbstractMetaArgument *lastArg, const TypeEntry *retType, - const DefaultValue &defaultReturnExpr) + const QString &returnStatement) { if (!snips.isEmpty()) { writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, @@ -803,11 +803,8 @@ void CppGenerator::writeVirtualMethodCppCall(QTextStream &s, if (func->isAbstract()) { s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '" << func->ownerClass()->name() << '.' << funcName - << "()' not implemented.\");\n"; - s << INDENT << "return"; - if (retType) - s << ' ' << defaultReturnExpr.returnValue(); - s << ";\n"; + << "()' not implemented.\");\n" + << INDENT << returnStatement << '\n'; return; } @@ -826,6 +823,61 @@ void CppGenerator::writeVirtualMethodCppCall(QTextStream &s, s << INDENT << "return;\n"; } +// Determine the return statement (void or a result value). +QString CppGenerator::virtualMethodReturn(QTextStream &s, + const AbstractMetaFunction *func, + const FunctionModificationList &functionModifications) +{ + const AbstractMetaType *returnType = func->type(); + if (!returnType) + return QLatin1String("return;"); + for (const FunctionModification &mod : functionModifications) { + for (const ArgumentModification &argMod : mod.argument_mods) { + if (argMod.index == 0 && !argMod.replacedDefaultExpression.isEmpty()) { + static const QRegularExpression regex(QStringLiteral("%(\\d+)")); + Q_ASSERT(regex.isValid()); + QString expr = argMod.replacedDefaultExpression; + for (int offset = 0; ; ) { + const QRegularExpressionMatch match = regex.match(expr, offset); + if (!match.hasMatch()) + break; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const int argId = match.capturedView(1).toInt() - 1; +#else + const int argId = match.capturedRef(1).toInt() - 1; +#endif + if (argId < 0 || argId > func->arguments().count()) { + qCWarning(lcShiboken, "The expression used in return value contains an invalid index."); + break; + } + expr.replace(match.captured(0), func->arguments().at(argId)->name()); + offset = match.capturedStart(1); + } + DefaultValue defaultReturnExpr(DefaultValue::Custom, expr); + return QLatin1String("return ") + defaultReturnExpr.returnValue() + + QLatin1Char(';'); + } + } + } + const DefaultValue defaultReturnExpr = minimalConstructor(returnType); + if (!defaultReturnExpr.isValid()) { + QString errorMsg = QLatin1String(__FUNCTION__) + QLatin1String(": "); + if (const AbstractMetaClass *c = func->implementingClass()) + errorMsg += c->qualifiedCppName() + QLatin1String("::"); + errorMsg += func->signature(); + errorMsg = msgCouldNotFindMinimalConstructor(errorMsg, func->type()->cppSignature()); + qCWarning(lcShiboken).noquote().nospace() << errorMsg; + s << Qt::endl << INDENT << "#error " << errorMsg << Qt::endl; + } + if (returnType->referenceType() == LValueReference) { + s << INDENT << "static " << returnType->typeEntry()->qualifiedCppName() + << " result;\n"; + return QLatin1String("return result;"); + } + return QLatin1String("return ") + defaultReturnExpr.returnValue() + + QLatin1Char(';'); +} + void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFunction *func, int cacheIndex) @@ -845,57 +897,15 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, Indentation indentation(INDENT); const FunctionModificationList &functionModifications = func->modifications(); - DefaultValue defaultReturnExpr; - if (retType) { - for (const FunctionModification &mod : functionModifications) { - for (const ArgumentModification &argMod : mod.argument_mods) { - if (argMod.index == 0 && !argMod.replacedDefaultExpression.isEmpty()) { - static const QRegularExpression regex(QStringLiteral("%(\\d+)")); - Q_ASSERT(regex.isValid()); - QString expr = argMod.replacedDefaultExpression; - for (int offset = 0; ; ) { - const QRegularExpressionMatch match = regex.match(expr, offset); - if (!match.hasMatch()) - break; -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - const int argId = match.capturedView(1).toInt() - 1; -#else - const int argId = match.capturedRef(1).toInt() - 1; -#endif - if (argId < 0 || argId > func->arguments().count()) { - qCWarning(lcShiboken) << "The expression used in return value contains an invalid index."; - break; - } - expr.replace(match.captured(0), func->arguments().at(argId)->name()); - offset = match.capturedStart(1); - } - defaultReturnExpr.setType(DefaultValue::Custom); - defaultReturnExpr.setValue(expr); - } - } - } - if (!defaultReturnExpr.isValid()) - defaultReturnExpr = minimalConstructor(func->type()); - if (!defaultReturnExpr.isValid()) { - QString errorMsg = QLatin1String(__FUNCTION__) + QLatin1String(": "); - if (const AbstractMetaClass *c = func->implementingClass()) - errorMsg += c->qualifiedCppName() + QLatin1String("::"); - errorMsg += func->signature(); - errorMsg = msgCouldNotFindMinimalConstructor(errorMsg, func->type()->cppSignature()); - qCWarning(lcShiboken).noquote().nospace() << errorMsg; - s << Qt::endl << INDENT << "#error " << errorMsg << Qt::endl; - } - } else { - defaultReturnExpr.setType(DefaultValue::Void); - } + + const QString returnStatement = virtualMethodReturn(s, func, functionModifications); if (func->isAbstract() && func->isModifiedRemoved()) { qCWarning(lcShiboken).noquote().nospace() << QString::fromLatin1("Pure virtual method '%1::%2' must be implement but was "\ "completely removed on type system.") .arg(func->ownerClass()->name(), func->minimalSignature()); - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; - s << "}\n\n"; + s << INDENT << returnStatement << "\n}\n\n"; return; } @@ -925,7 +935,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, { Indentation indentation(INDENT); writeVirtualMethodCppCall(s, func, funcName, snips, lastArg, retType, - defaultReturnExpr); + returnStatement); } if (multi_line) s << INDENT << "}\n"; @@ -936,7 +946,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, s << INDENT << "if (PyErr_Occurred())\n"; { Indentation indentation(INDENT); - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; + s << INDENT << returnStatement << '\n'; } s << INDENT << "static PyObject *pyFuncName = Shiboken::String::createStaticString(\"" @@ -950,7 +960,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, if (useOverrideCaching(func->ownerClass())) s << INDENT << "m_PyMethodCache[" << cacheIndex << "] = true;\n"; writeVirtualMethodCppCall(s, func, funcName, snips, lastArg, retType, - defaultReturnExpr); + returnStatement); } s << INDENT << "}\n\n"; //WS @@ -1040,7 +1050,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, { Indentation indent(INDENT); s << INDENT << "PyErr_Print();\n"; - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; + s << INDENT << returnStatement << '\n'; } s << INDENT << "}\n"; @@ -1062,7 +1072,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, "\"Invalid return value in function %s, expected %s, got %s.\", \""; s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func); s << ", Py_TYPE(" << PYTHON_RETURN_VAR << ")->tp_name);\n"; - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; + s << INDENT << returnStatement << '\n'; } s << INDENT << "}\n"; @@ -1083,7 +1093,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, "\"Invalid return value in function %s, expected %s, got %s.\", \""; s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func); s << ", Py_TYPE(" << PYTHON_RETURN_VAR << ")->tp_name);\n"; - s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl; + s << INDENT << returnStatement << '\n'; } s << INDENT << "}\n"; @@ -2419,8 +2429,17 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream &s, s << ' ' << cppOut; } else if (treatAsPointer || isPointerOrObjectType) { s << " *" << cppOut; - if (!defaultValue.isEmpty()) - s << " = " << defaultValue; + if (!defaultValue.isEmpty()) { + const bool needsConstCast = !isNullPtr(defaultValue) + && type->indirections() == 1 && type->isConstant() + && type->referenceType() == NoReference; + s << " = "; + if (needsConstCast) + s << "const_cast<" << typeName << " *>("; + s << defaultValue; + if (needsConstCast) + s << ')'; + } } else if (type->referenceType() == LValueReference && !typeEntry->isPrimitive() && isNotContainerEnumOrFlags) { s << " *" << cppOut << " = &" << cppOutAux; } else { diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h index 16ee412c9..1cc6c1ca0 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.h +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h @@ -63,7 +63,10 @@ private: void writeVirtualMethodCppCall(QTextStream &s, const AbstractMetaFunction *func, const QString &funcName, const CodeSnipList &snips, const AbstractMetaArgument *lastArg, const TypeEntry *retType, - const DefaultValue &defaultReturnExpr); + const QString &returnStatement); + QString virtualMethodReturn(QTextStream &s, + const AbstractMetaFunction *func, + const FunctionModificationList &functionModifications); void writeMetaObjectMethod(QTextStream &s, const GeneratorContext &classContext); void writeMetaCast(QTextStream &s, const GeneratorContext &classContext); diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp index 6abaef698..43ebefe14 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -1145,6 +1145,12 @@ bool ShibokenGenerator::visibilityModifiedToPrivate(const AbstractMetaFunction * return false; } +bool ShibokenGenerator::isNullPtr(const QString &value) +{ + return value == QLatin1String("0") || value == QLatin1String("nullptr") + || value == QLatin1String("NULLPTR") || value == QLatin1String("{}"); +} + QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType *metaType, bool genericNumberType) { QString customCheck; diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h index d8259d245..da0c16851 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h @@ -301,6 +301,8 @@ protected: static bool visibilityModifiedToPrivate(const AbstractMetaFunction *func); + static bool isNullPtr(const QString &value); + QString converterObject(const AbstractMetaType *type); QString converterObject(const TypeEntry *type); diff --git a/sources/shiboken2/tests/libsample/objecttype.cpp b/sources/shiboken2/tests/libsample/objecttype.cpp index 855c08611..afaaa9d77 100644 --- a/sources/shiboken2/tests/libsample/objecttype.cpp +++ b/sources/shiboken2/tests/libsample/objecttype.cpp @@ -57,6 +57,12 @@ ObjectType::createWithChild() return parent; } +const ObjectType *ObjectType::defaultInstance() +{ + static ObjectType result; + return &result; +} + void ObjectType::removeChild(ObjectType* child) { diff --git a/sources/shiboken2/tests/libsample/objecttype.h b/sources/shiboken2/tests/libsample/objecttype.h index 1f2a9c7e8..caa50f02e 100644 --- a/sources/shiboken2/tests/libsample/objecttype.h +++ b/sources/shiboken2/tests/libsample/objecttype.h @@ -78,6 +78,8 @@ public: inline static ObjectType* create() { return new ObjectType(); } static ObjectType* createWithChild(); + static const ObjectType *defaultInstance(); + void setParent(ObjectType* parent); inline ObjectType* parent() const { return m_parent; } inline const ObjectTypeList& children() const { return m_children; } diff --git a/sources/shiboken2/tests/libsample/objecttypeholder.cpp b/sources/shiboken2/tests/libsample/objecttypeholder.cpp index ff2f14f12..be225a0d2 100644 --- a/sources/shiboken2/tests/libsample/objecttypeholder.cpp +++ b/sources/shiboken2/tests/libsample/objecttypeholder.cpp @@ -30,8 +30,14 @@ ObjectTypeHolder::ObjectTypeHolder(const char* objectName) { - m_objectType = new ObjectType(); - m_objectType->setObjectName(objectName); + auto object = new ObjectType(); + object->setObjectName(objectName); + m_objectType = object; +} + +ObjectTypeHolder::ObjectTypeHolder(const ObjectType *object) : + m_objectType(object) +{ } ObjectTypeHolder::~ObjectTypeHolder() diff --git a/sources/shiboken2/tests/libsample/objecttypeholder.h b/sources/shiboken2/tests/libsample/objecttypeholder.h index ce13de74f..7558b11ee 100644 --- a/sources/shiboken2/tests/libsample/objecttypeholder.h +++ b/sources/shiboken2/tests/libsample/objecttypeholder.h @@ -37,15 +37,16 @@ class LIBSAMPLE_API ObjectTypeHolder { public: explicit ObjectTypeHolder(const char* objectName); + explicit ObjectTypeHolder(const ObjectType *object = ObjectType::defaultInstance()); virtual ~ObjectTypeHolder(); - ObjectType* getObjecType() { return m_objectType; } + const ObjectType* getObjecType() { return m_objectType; } virtual Str passObjectTypeAsReference(const ObjectType& objectType); Str callPassObjectTypeAsReference(); private: - ObjectType* m_objectType; + const ObjectType *m_objectType; }; #endif diff --git a/sources/shiboken2/tests/libsample/virtualmethods.cpp b/sources/shiboken2/tests/libsample/virtualmethods.cpp index 294feca60..8f9c8f64d 100644 --- a/sources/shiboken2/tests/libsample/virtualmethods.cpp +++ b/sources/shiboken2/tests/libsample/virtualmethods.cpp @@ -57,6 +57,12 @@ VirtualMethods::getMargins(int* left, int* top, int* right, int* bottom) const *bottom = m_bottom; } +const Str & VirtualMethods::returnConstRef() const +{ + static const Str result; + return result; +} + double VirtualDaughter2::virtualMethod0(Point pt, int val, Complex cpx, bool b) { return 42 + VirtualMethods::virtualMethod0(pt, val, cpx, b); diff --git a/sources/shiboken2/tests/libsample/virtualmethods.h b/sources/shiboken2/tests/libsample/virtualmethods.h index 3e4c8c504..4937fab0d 100644 --- a/sources/shiboken2/tests/libsample/virtualmethods.h +++ b/sources/shiboken2/tests/libsample/virtualmethods.h @@ -106,6 +106,8 @@ public: virtual int recursionOnModifiedVirtual(Str arg) const { return 0; } int callRecursionOnModifiedVirtual(Str arg) const { return recursionOnModifiedVirtual(arg); } + virtual const Str & returnConstRef() const; + private: Str m_name; int m_left; diff --git a/sources/shiboken2/tests/shiboken_paths.py b/sources/shiboken2/tests/shiboken_paths.py index e5a8f2926..1f60baac2 100644 --- a/sources/shiboken2/tests/shiboken_paths.py +++ b/sources/shiboken2/tests/shiboken_paths.py @@ -42,7 +42,27 @@ def get_dir_env_var(var_name): def get_build_dir(): - return get_dir_env_var('BUILD_DIR') + """ + Return the env var `BUILD_DIR`. + If not set (interactive mode), take the last build history entry. + """ + try: + return get_dir_env_var('BUILD_DIR') + except ValueError: + look_for = "testing" + here = os.path.dirname(__file__) + while look_for not in os.listdir(here): + here = os.path.dirname(here) + if len(here) <= 3: + raise SystemError(look_for + " not found!") + try: + sys.path.insert(0, here) + from testing.buildlog import builds + if not builds.history: + raise + return builds.history[-1].build_dir + finally: + del sys.path[0] def _prepend_path_var(var_name, paths): |