aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-07-14 22:16:26 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-07-14 22:16:32 +0200
commitc577b499b9c347c798a12194ffc5f399e6d62835 (patch)
treea11b0081b5699d6663fe38cb2daaf68b28cf8b62 /sources
parent8757b8a9079d93bad4e1d9235b20aba1c2e33356 (diff)
parent96df55f9fdc7406971baba18a622ea8f947ec916 (diff)
Merge remote-tracking branch 'origin/5.15' into dev
Diffstat (limited to 'sources')
-rw-r--r--sources/pyside2/doc/deployment-briefcase.rst199
-rw-r--r--sources/pyside2/doc/deployment.rst13
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp100
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h4
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp5
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h2
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp137
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.h5
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp6
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.h2
-rw-r--r--sources/shiboken2/tests/libsample/objecttype.cpp6
-rw-r--r--sources/shiboken2/tests/libsample/objecttype.h2
-rw-r--r--sources/shiboken2/tests/libsample/objecttypeholder.cpp10
-rw-r--r--sources/shiboken2/tests/libsample/objecttypeholder.h5
-rw-r--r--sources/shiboken2/tests/libsample/virtualmethods.cpp6
-rw-r--r--sources/shiboken2/tests/libsample/virtualmethods.h2
-rw-r--r--sources/shiboken2/tests/shiboken_paths.py22
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):