aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-05-25 16:33:12 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-05-25 16:33:12 +0200
commit39ac266455cc1c0ae970a47c34d3a6bc7372d750 (patch)
tree9577fe06bcb0e3096ef85af929a91eb37b037452
parent9115712ef3a1be8b401c9cd306792dbc30c89bf0 (diff)
parent6717d3540fac74c91d9381958a08e60f6532d402 (diff)
Merge remote-tracking branch 'origin/5.14' into 5.14.2
-rw-r--r--sources/pyside2/PySide2/QtCore/typesystem_core_common.xml4
-rw-r--r--sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp11
-rw-r--r--sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml36
-rw-r--r--sources/pyside2/PySide2/glue/qtcore.cpp16
-rw-r--r--sources/pyside2/PySide2/glue/qtuitools.cpp138
-rw-r--r--sources/pyside2/PySide2/support/deprecated.py2
-rw-r--r--sources/pyside2/PySide2/support/generate_pyi.py8
-rw-r--r--sources/pyside2/doc/inheritance_diagram.py2
-rw-r--r--sources/pyside2/libpyside/pysideclassinfo.cpp4
-rw-r--r--sources/pyside2/libpyside/pysidemetafunction.cpp7
-rw-r--r--sources/pyside2/libpyside/pysideproperty.cpp9
-rw-r--r--sources/pyside2/libpyside/pysideqflags.cpp4
-rw-r--r--sources/pyside2/libpyside/pysidesignal.cpp14
-rw-r--r--sources/pyside2/libpyside/pysideslot.cpp7
-rw-r--r--sources/pyside2/libpyside/pysideweakref.cpp9
-rw-r--r--sources/pyside2/tests/QtCore/qenum_test.py50
-rw-r--r--sources/pyside2/tests/QtUiTools/loadUiType_test.py75
-rw-r--r--sources/pyside2/tests/QtWidgets/qwidget_test.py4
-rw-r--r--sources/pyside2/tests/registry/existence_test.py16
-rw-r--r--sources/shiboken2/ApiExtractor/CMakeLists.txt2
-rw-r--r--sources/shiboken2/generator/CMakeLists.txt2
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp9
-rw-r--r--sources/shiboken2/libshiboken/autodecref.h4
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp85
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.h4
-rw-r--r--sources/shiboken2/libshiboken/pep384impl.cpp32
-rw-r--r--sources/shiboken2/libshiboken/pep384impl.h10
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.cpp153
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.h2
-rw-r--r--sources/shiboken2/libshiboken/sbkstaticstrings.cpp1
-rw-r--r--sources/shiboken2/libshiboken/sbkstaticstrings.h1
-rw-r--r--sources/shiboken2/libshiboken/signature.cpp46
-rw-r--r--sources/shiboken2/libshiboken/voidptr.cpp15
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/backport_inspect.py17
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py4
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py2
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py16
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py8
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py10
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/typing27.py7
-rw-r--r--sources/shiboken2/shibokenmodule/typesystem_shiboken.xml6
41 files changed, 724 insertions, 128 deletions
diff --git a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml
index 53ab29382..26193a0aa 100644
--- a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml
+++ b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml
@@ -223,9 +223,9 @@
</primitive-type>
<primitive-type name="quintptr" target-lang-api-name="PyLong">
<conversion-rule>
- <native-to-target file="../glue/qtcore.cpp" snippet="return-pylong-unsigned"/>
+ <native-to-target file="../glue/qtcore.cpp" snippet="return-pylong-quintptr"/>
<target-to-native>
- <add-conversion type="PyLong" file="../glue/qtcore.cpp" snippet="conversion-pylong-unsigned"/>
+ <add-conversion type="PyLong" file="../glue/qtcore.cpp" snippet="conversion-pylong-quintptr"/>
</target-to-native>
</conversion-rule>
</primitive-type>
diff --git a/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp b/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp
index fb9a5a0cf..efc86a048 100644
--- a/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp
+++ b/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp
@@ -240,7 +240,7 @@ static PyType_Slot PropertyListType_slots[] = {
{0, 0}
};
static PyType_Spec PropertyListType_spec = {
- "PySide2.QtQml.ListProperty",
+ "2:PySide2.QtQml.ListProperty",
sizeof(PySideProperty),
0,
Py_TPFLAGS_DEFAULT,
@@ -253,7 +253,7 @@ PyTypeObject *PropertyListTypeF(void)
static PyTypeObject *type = nullptr;
if (!type) {
PyObject *bases = Py_BuildValue("(O)", PySidePropertyTypeF());
- type = (PyTypeObject *)PyType_FromSpecWithBases(&PropertyListType_spec, bases);
+ type = (PyTypeObject *)SbkType_FromSpecWithBases(&PropertyListType_spec, bases);
Py_XDECREF(bases);
}
return type;
@@ -454,7 +454,7 @@ static PyType_Slot QtQml_VolatileBoolType_slots[] = {
{0, 0}
};
static PyType_Spec QtQml_VolatileBoolType_spec = {
- "PySide2.QtQml.VolatileBool",
+ "2:PySide2.QtQml.VolatileBool",
sizeof(QtQml_VolatileBoolObject),
0,
Py_TPFLAGS_DEFAULT,
@@ -464,9 +464,8 @@ static PyType_Spec QtQml_VolatileBoolType_spec = {
PyTypeObject *QtQml_VolatileBoolTypeF(void)
{
- static PyTypeObject *type = nullptr;
- if (!type)
- type = (PyTypeObject *)PyType_FromSpec(&QtQml_VolatileBoolType_spec);
+ static PyTypeObject *type = reinterpret_cast<PyTypeObject *>(
+ SbkType_FromSpec(&QtQml_VolatileBoolType_spec));
return type;
}
diff --git a/sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml b/sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml
index 7b27e8783..2ca12e788 100644
--- a/sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml
+++ b/sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml
@@ -139,4 +139,40 @@
</add-function>
</object-type>
+ <!--
+ After the removal of the 'pysideuic' Python module, many users were unable to generate and
+ load UI classes dynamically.
+ This function was created to provide an equivalent solution to the 'loadUiType' function from
+ Riverbank's PyQt.
+ -->
+ <add-function signature="loadUiType(const QString&amp; @uifile@)" return-type="PyObject*">
+ <inject-documentation format="target" mode="append">
+ This function will allow users to generate and load a `.ui` file at runtime, and it returns
+ a `tuple` containing the reference to the Python class, and the base class.
+
+ We don't recommend this approach since the workflow should be to generate a Python file
+ from the `.ui` file, and then import and load it to use it, but we do understand that
+ there are some corner cases when such functionality is required.
+
+ The internal process relies on `uic` being in the PATH, which is the same requirement for
+ the new `pyside2-uic` to work (which is just a wrapper around `uic -g python`)
+
+ A Simple use can be:
+
+ .. code-block:: python
+
+ from PySide2.QtUiTools import loadUiType
+
+ generated_class, base_class = loadUiType("themewidget.ui")
+ # the values will be:
+ # (&lt;class '__main__.Ui_ThemeWidgetForm'&gt;, &lt;class 'PySide2.QtWidgets.QWidget'&gt;)
+
+
+ In that case, `generated_class` will be a reference to the Python class,
+ and `base_class` will be a reference to the base class.
+ </inject-documentation>
+ <inject-code file="../glue/qtuitools.cpp" snippet="loaduitype"/>
+ </add-function>
+
+
</typesystem>
diff --git a/sources/pyside2/PySide2/glue/qtcore.cpp b/sources/pyside2/PySide2/glue/qtcore.cpp
index 834383679..111e324b9 100644
--- a/sources/pyside2/PySide2/glue/qtcore.cpp
+++ b/sources/pyside2/PySide2/glue/qtcore.cpp
@@ -1678,6 +1678,14 @@ Py_END_ALLOW_THREADS
%out = %OUTTYPE(PyLong_AsUnsignedLong(%in));
// @snippet conversion-pylong-unsigned
+// @snippet conversion-pylong-quintptr
+#if defined(IS_PY3K) && QT_POINTER_SIZE == 8
+%out = %OUTTYPE(PyLong_AsUnsignedLongLong(%in));
+#else
+%out = %OUTTYPE(PyLong_AsUnsignedLong(%in));
+#endif
+// @snippet conversion-pylong-quintptr
+
// @snippet conversion-pyunicode
#ifndef Py_LIMITED_API
Py_UNICODE *unicode = PyUnicode_AS_UNICODE(%in);
@@ -1870,6 +1878,14 @@ return PyLong_FromLong(%in);
return PyLong_FromUnsignedLong(%in);
// @snippet return-pylong-unsigned
+// @snippet return-pylong-quintptr
+#if defined(IS_PY3K) && QT_POINTER_SIZE == 8
+return PyLong_FromUnsignedLongLong(%in);
+#else
+return PyLong_FromUnsignedLong(%in);
+#endif
+// @snippet return-pylong-quintptr
+
// @snippet return-pyunicode
QByteArray ba = %in.toUtf8();
return PyUnicode_FromStringAndSize(ba.constData(), ba.size());
diff --git a/sources/pyside2/PySide2/glue/qtuitools.cpp b/sources/pyside2/PySide2/glue/qtuitools.cpp
index 00fc8e44a..668b512e4 100644
--- a/sources/pyside2/PySide2/glue/qtuitools.cpp
+++ b/sources/pyside2/PySide2/glue/qtuitools.cpp
@@ -109,3 +109,141 @@ registerCustomWidget(%PYARG_1);
// Avoid calling the original function: %CPPSELF.%FUNCTION_NAME()
%PYARG_0 = QUiLoaderLoadUiFromFileName(%CPPSELF, %1, %2);
// @snippet quiloader-load-2
+
+// @snippet loaduitype
+/*
+Arguments:
+ %PYARG_1 (uifile)
+*/
+// 1. Generate the Python code from the UI file
+#ifdef IS_PY3K
+PyObject *strObj = PyUnicode_AsUTF8String(%PYARG_1);
+char *arg1 = PyBytes_AsString(strObj);
+QByteArray uiFileName(arg1);
+Py_DECREF(strObj);
+#else
+QByteArray uiFileName(PyBytes_AsString(%PYARG_1));
+#endif
+
+QFile uiFile(uiFileName);
+
+if (!uiFile.exists()) {
+ qCritical().noquote() << "File" << uiFileName << "does not exists";
+ Py_RETURN_NONE;
+}
+
+if (uiFileName.isEmpty()) {
+ qCritical() << "Error converting the UI filename to QByteArray";
+ Py_RETURN_NONE;
+}
+
+QString uicBin("uic");
+QStringList uicArgs = {"-g", "python", QString::fromUtf8(uiFileName)};
+
+QProcess uicProcess;
+uicProcess.start(uicBin, uicArgs);
+if (!uicProcess.waitForFinished()) {
+ qCritical() << "Cannot run 'uic': " << uicProcess.errorString() << " - "
+ << "Exit status " << uicProcess.exitStatus()
+ << " (" << uicProcess.exitCode() << ")\n"
+ << "Check if 'uic' is in PATH";
+ Py_RETURN_NONE;
+}
+QByteArray uiFileContent = uicProcess.readAllStandardOutput();
+QByteArray errorOutput = uicProcess.readAllStandardError();
+
+if (!errorOutput.isEmpty()) {
+ qCritical().noquote() << errorOutput;
+ Py_RETURN_NONE;
+}
+
+// 2. Obtain the 'classname' and the Qt base class.
+QByteArray className;
+QByteArray baseClassName;
+
+// Problem
+// The generated Python file doesn't have the Qt Base class information.
+
+// Solution
+// Use the XML file
+if (!uiFile.open(QIODevice::ReadOnly))
+ Py_RETURN_NONE;
+
+// This will look for the first <widget> tag, e.g.:
+// <widget class="QWidget" name="ThemeWidgetForm">
+// and then extract the information from "class", and "name",
+// to get the baseClassName and className respectively
+QXmlStreamReader reader(&uiFile);
+while (!reader.atEnd() && baseClassName.isEmpty() && className.isEmpty()) {
+ auto token = reader.readNext();
+ if (token == QXmlStreamReader::StartElement && reader.name() == "widget") {
+ baseClassName = reader.attributes().value(QLatin1String("class")).toUtf8();
+ className = reader.attributes().value(QLatin1String("name")).toUtf8();
+ }
+}
+
+uiFile.close();
+
+if (className.isEmpty() || baseClassName.isEmpty() || reader.hasError()) {
+ qCritical() << "An error occurred when parsing the UI file while looking for the class info "
+ << reader.errorString();
+ Py_RETURN_NONE;
+}
+
+QByteArray pyClassName("Ui_"+className);
+
+PyObject *module = PyImport_ImportModule("__main__");
+PyObject *loc = PyModule_GetDict(module);
+
+// 3. exec() the code so the class exists in the context: exec(uiFileContent)
+// The context of PyRun_SimpleString is __main__.
+// 'Py_file_input' is the equivalent to using exec(), since it will execute
+// the code, without returning anything.
+Shiboken::AutoDecRef codeUi(Py_CompileString(uiFileContent.constData(), "<stdin>", Py_file_input));
+if (codeUi.isNull()) {
+ qCritical() << "Error while compiling the generated Python file";
+ Py_RETURN_NONE;
+}
+PyObject *uiObj = nullptr;
+#ifdef IS_PY3K
+uiObj = PyEval_EvalCode(codeUi, loc, loc);
+#else
+uiObj = PyEval_EvalCode(reinterpret_cast<PyCodeObject *>(codeUi.object()), loc, loc);
+#endif
+
+if (uiObj == nullptr) {
+ qCritical() << "Error while running exec() on the generated code";
+ Py_RETURN_NONE;
+}
+
+// 4. eval() the name of the class on a variable to return
+// 'Py_eval_input' is the equivalent to using eval(), since it will just
+// evaluate an expression.
+Shiboken::AutoDecRef codeClass(Py_CompileString(pyClassName.constData(),"<stdin>", Py_eval_input));
+if (codeClass.isNull()) {
+ qCritical() << "Error while compiling the Python class";
+ Py_RETURN_NONE;
+}
+
+Shiboken::AutoDecRef codeBaseClass(Py_CompileString(baseClassName.constData(), "<stdin>", Py_eval_input));
+if (codeBaseClass.isNull()) {
+ qCritical() << "Error while compiling the base class";
+ Py_RETURN_NONE;
+}
+
+#ifdef IS_PY3K
+PyObject *classObj = PyEval_EvalCode(codeClass, loc, loc);
+PyObject *baseClassObj = PyEval_EvalCode(codeBaseClass, loc, loc);
+#else
+PyObject *classObj = PyEval_EvalCode(reinterpret_cast<PyCodeObject *>(codeClass.object()), loc, loc);
+PyObject *baseClassObj = PyEval_EvalCode(reinterpret_cast<PyCodeObject *>(codeBaseClass.object()), loc, loc);
+#endif
+
+%PYARG_0 = PyTuple_New(2);
+if (%PYARG_0 == nullptr) {
+ qCritical() << "Error while creating the return Tuple";
+ Py_RETURN_NONE;
+}
+PyTuple_SET_ITEM(%PYARG_0, 0, classObj);
+PyTuple_SET_ITEM(%PYARG_0, 1, baseClassObj);
+// @snippet loaduitype
diff --git a/sources/pyside2/PySide2/support/deprecated.py b/sources/pyside2/PySide2/support/deprecated.py
index 8538826e4..57f33d9e2 100644
--- a/sources/pyside2/PySide2/support/deprecated.py
+++ b/sources/pyside2/PySide2/support/deprecated.py
@@ -64,7 +64,7 @@ class PySideDeprecationWarningRemovedInQt6(Warning):
def constData(self):
cls = self.__class__
- name = cls.__name__
+ name = cls.__qualname__
warnings.warn(dedent("""
{name}.constData is unpythonic and will be removed in Qt For Python 6.0 .
Please use {name}.data instead."""
diff --git a/sources/pyside2/PySide2/support/generate_pyi.py b/sources/pyside2/PySide2/support/generate_pyi.py
index f92367c82..af9f4d4f5 100644
--- a/sources/pyside2/PySide2/support/generate_pyi.py
+++ b/sources/pyside2/PySide2/support/generate_pyi.py
@@ -1,7 +1,7 @@
# This Python file uses the following encoding: utf-8
#############################################################################
##
-## Copyright (C) 2019 The Qt Company Ltd.
+## Copyright (C) 2020 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
@@ -169,12 +169,6 @@ class Formatter(Writer):
else:
self.print("{spaces}class {class_str}: ...".format(**locals()))
yield
- if "<" in class_name:
- # This is happening in QtQuick for some reason:
- ## class QSharedPointer<QQuickItemGrabResult >:
- # We simply skip over this class.
- self.outfile.seek(here)
- self.outfile.truncate()
@contextmanager
def function(self, func_name, signature, modifier=None):
diff --git a/sources/pyside2/doc/inheritance_diagram.py b/sources/pyside2/doc/inheritance_diagram.py
index 054cb7be9..875e17b50 100644
--- a/sources/pyside2/doc/inheritance_diagram.py
+++ b/sources/pyside2/doc/inheritance_diagram.py
@@ -176,7 +176,7 @@ class InheritanceGraph(object):
if module == '__builtin__':
fullname = cls.__name__
else:
- fullname = '%s.%s' % (module, cls.__name__)
+ fullname = '%s.%s' % (module, cls.__qualname__)
if parts == 0:
return fullname
name_parts = fullname.split('.')
diff --git a/sources/pyside2/libpyside/pysideclassinfo.cpp b/sources/pyside2/libpyside/pysideclassinfo.cpp
index c4bace77e..375a31b57 100644
--- a/sources/pyside2/libpyside/pysideclassinfo.cpp
+++ b/sources/pyside2/libpyside/pysideclassinfo.cpp
@@ -64,7 +64,7 @@ static PyType_Slot PySideClassInfoType_slots[] = {
{0, 0}
};
static PyType_Spec PySideClassInfoType_spec = {
- "PySide2.QtCore.ClassInfo",
+ "2:PySide2.QtCore.ClassInfo",
sizeof(PySideClassInfo),
0,
Py_TPFLAGS_DEFAULT,
@@ -75,7 +75,7 @@ static PyType_Spec PySideClassInfoType_spec = {
PyTypeObject *PySideClassInfoTypeF(void)
{
static PyTypeObject *type =
- reinterpret_cast<PyTypeObject *>(PyType_FromSpec(&PySideClassInfoType_spec));
+ reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideClassInfoType_spec));
return type;
}
diff --git a/sources/pyside2/libpyside/pysidemetafunction.cpp b/sources/pyside2/libpyside/pysidemetafunction.cpp
index 637aa0598..f4b95385a 100644
--- a/sources/pyside2/libpyside/pysidemetafunction.cpp
+++ b/sources/pyside2/libpyside/pysidemetafunction.cpp
@@ -66,7 +66,7 @@ static PyType_Slot PySideMetaFunctionType_slots[] = {
{0, 0}
};
static PyType_Spec PySideMetaFunctionType_spec = {
- "PySide2.QtCore.MetaFunction",
+ "2:PySide2.QtCore.MetaFunction",
sizeof(PySideMetaFunction),
0,
Py_TPFLAGS_DEFAULT,
@@ -76,9 +76,8 @@ static PyType_Spec PySideMetaFunctionType_spec = {
PyTypeObject *PySideMetaFunctionTypeF(void)
{
- static PyTypeObject *type = nullptr;
- if (!type)
- type = (PyTypeObject *)PyType_FromSpec(&PySideMetaFunctionType_spec);
+ static PyTypeObject *type = reinterpret_cast<PyTypeObject *>(
+ SbkType_FromSpec(&PySideMetaFunctionType_spec));
return type;
}
diff --git a/sources/pyside2/libpyside/pysideproperty.cpp b/sources/pyside2/libpyside/pysideproperty.cpp
index bdabf1202..77dc6f3fc 100644
--- a/sources/pyside2/libpyside/pysideproperty.cpp
+++ b/sources/pyside2/libpyside/pysideproperty.cpp
@@ -88,9 +88,9 @@ static PyType_Slot PySidePropertyType_slots[] = {
{Py_tp_getset, PySidePropertyType_getset},
{0, 0}
};
-// Dotted modulename is crucial for PyType_FromSpec to work. Is this name right?
+// Dotted modulename is crucial for SbkType_FromSpec to work. Is this name right?
static PyType_Spec PySidePropertyType_spec = {
- "PySide2.QtCore.Property",
+ "2:PySide2.QtCore.Property",
sizeof(PySideProperty),
0,
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_BASETYPE,
@@ -100,9 +100,8 @@ static PyType_Spec PySidePropertyType_spec = {
PyTypeObject *PySidePropertyTypeF(void)
{
- static PyTypeObject *type = nullptr;
- if (!type)
- type = (PyTypeObject *)PyType_FromSpec(&PySidePropertyType_spec);
+ static PyTypeObject *type = reinterpret_cast<PyTypeObject *>(
+ SbkType_FromSpec(&PySidePropertyType_spec));
return type;
}
diff --git a/sources/pyside2/libpyside/pysideqflags.cpp b/sources/pyside2/libpyside/pysideqflags.cpp
index 8cf9aa7b2..d7e6b4f4c 100644
--- a/sources/pyside2/libpyside/pysideqflags.cpp
+++ b/sources/pyside2/libpyside/pysideqflags.cpp
@@ -174,7 +174,7 @@ namespace QFlags
char qualname[200];
// PYSIDE-747: Here we insert now the full class name.
strcpy(qualname, name);
- // Careful: PyType_FromSpec does not allocate the string.
+ // Careful: SbkType_FromSpec does not allocate the string.
PyType_Spec *newspec = new PyType_Spec;
newspec->name = strdup(qualname);
newspec->basicsize = SbkNewQFlagsType_spec.basicsize;
@@ -186,7 +186,7 @@ namespace QFlags
SbkNewQFlagsType_slots[idx].pfunc = numberMethods[idx].pfunc;
}
newspec->slots = SbkNewQFlagsType_spec.slots;
- PyTypeObject *type = (PyTypeObject *)PyType_FromSpec(newspec);
+ PyTypeObject *type = (PyTypeObject *)SbkType_FromSpec(newspec);
Py_TYPE(type) = &PyType_Type;
PySideQFlagsType *flagsType = reinterpret_cast<PySideQFlagsType *>(type);
diff --git a/sources/pyside2/libpyside/pysidesignal.cpp b/sources/pyside2/libpyside/pysidesignal.cpp
index be4c367f7..0fa33254c 100644
--- a/sources/pyside2/libpyside/pysidesignal.cpp
+++ b/sources/pyside2/libpyside/pysidesignal.cpp
@@ -115,9 +115,9 @@ static PyType_Slot PySideMetaSignalType_slots[] = {
{0, 0}
};
static PyType_Spec PySideMetaSignalType_spec = {
- "PySide2.QtCore.MetaSignal",
+ "2:PySide2.QtCore.MetaSignal",
0,
- // sizeof(PyHeapTypeObject) is filled in by PyType_FromSpecWithBases
+ // sizeof(PyHeapTypeObject) is filled in by SbkType_FromSpecWithBases
// which calls PyType_Ready which calls inherit_special.
0,
Py_TPFLAGS_DEFAULT,
@@ -130,7 +130,7 @@ PyTypeObject *PySideMetaSignalTypeF(void)
static PyTypeObject *type = nullptr;
if (!type) {
PyObject *bases = Py_BuildValue("(O)", &PyType_Type);
- type = (PyTypeObject *)PyType_FromSpecWithBases(&PySideMetaSignalType_spec, bases);
+ type = (PyTypeObject *)SbkType_FromSpecWithBases(&PySideMetaSignalType_spec, bases);
Py_XDECREF(bases);
}
return type;
@@ -147,7 +147,7 @@ static PyType_Slot PySideSignalType_slots[] = {
{0, 0}
};
static PyType_Spec PySideSignalType_spec = {
- "PySide2.QtCore.Signal",
+ "2:PySide2.QtCore.Signal",
sizeof(PySideSignal),
0,
Py_TPFLAGS_DEFAULT,
@@ -159,7 +159,7 @@ PyTypeObject *PySideSignalTypeF(void)
{
static PyTypeObject *type = nullptr;
if (!type) {
- type = (PyTypeObject *)PyType_FromSpec(&PySideSignalType_spec);
+ type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideSignalType_spec));
PyTypeObject *hold = Py_TYPE(type);
Py_TYPE(type) = PySideMetaSignalTypeF();
Py_INCREF(Py_TYPE(type));
@@ -186,7 +186,7 @@ static PyType_Slot PySideSignalInstanceType_slots[] = {
{0, 0}
};
static PyType_Spec PySideSignalInstanceType_spec = {
- "PySide2.QtCore.SignalInstance",
+ "2:PySide2.QtCore.SignalInstance",
sizeof(PySideSignalInstance),
0,
Py_TPFLAGS_DEFAULT,
@@ -197,7 +197,7 @@ static PyType_Spec PySideSignalInstanceType_spec = {
PyTypeObject *PySideSignalInstanceTypeF(void)
{
static PyTypeObject *type =
- (PyTypeObject *)PyType_FromSpec(&PySideSignalInstanceType_spec);
+ reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideSignalInstanceType_spec));
return type;
}
diff --git a/sources/pyside2/libpyside/pysideslot.cpp b/sources/pyside2/libpyside/pysideslot.cpp
index 04212a64e..e60115450 100644
--- a/sources/pyside2/libpyside/pysideslot.cpp
+++ b/sources/pyside2/libpyside/pysideslot.cpp
@@ -75,7 +75,7 @@ static PyType_Slot PySideSlotType_slots[] = {
{0, 0}
};
static PyType_Spec PySideSlotType_spec = {
- "PySide2.QtCore.Slot",
+ "2:PySide2.QtCore.Slot",
sizeof(PySideSlot),
0,
Py_TPFLAGS_DEFAULT,
@@ -85,9 +85,8 @@ static PyType_Spec PySideSlotType_spec = {
static PyTypeObject *PySideSlotTypeF(void)
{
- static PyTypeObject *type = nullptr;
- if (!type)
- type = (PyTypeObject *)PyType_FromSpec(&PySideSlotType_spec);
+ static PyTypeObject *type = reinterpret_cast<PyTypeObject *>(
+ SbkType_FromSpec(&PySideSlotType_spec));
return type;
}
diff --git a/sources/pyside2/libpyside/pysideweakref.cpp b/sources/pyside2/libpyside/pysideweakref.cpp
index faa3abe82..cd90634bd 100644
--- a/sources/pyside2/libpyside/pysideweakref.cpp
+++ b/sources/pyside2/libpyside/pysideweakref.cpp
@@ -57,7 +57,7 @@ static PyType_Slot PySideCallableObjectType_slots[] = {
{0, 0}
};
static PyType_Spec PySideCallableObjectType_spec = {
- const_cast<char *>("PySide.Callable"),
+ "1:PySide.Callable",
sizeof(PySideCallableObject),
0,
Py_TPFLAGS_DEFAULT,
@@ -68,7 +68,7 @@ static PyType_Spec PySideCallableObjectType_spec = {
static PyTypeObject *PySideCallableObjectTypeF()
{
static PyTypeObject *type =
- (PyTypeObject *)PyType_FromSpec(&PySideCallableObjectType_spec);
+ reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideCallableObjectType_spec));
return type;
}
@@ -98,11 +98,6 @@ PyObject *create(PyObject *obj, PySideWeakRefFunction func, void *userData)
PySideCallableObject *callable = PyObject_New(PySideCallableObject, type);
if (!callable || PyErr_Occurred())
return 0;
- if (!PepRuntime_38_flag) {
- // PYSIDE-939: Handling references correctly.
- // Workaround for Python issue 35810; no longer necessary in Python 3.8
- Py_INCREF(type);
- }
PyObject *weak = PyWeakref_NewRef(obj, reinterpret_cast<PyObject *>(callable));
if (!weak || PyErr_Occurred())
diff --git a/sources/pyside2/tests/QtCore/qenum_test.py b/sources/pyside2/tests/QtCore/qenum_test.py
index dd91d1581..1edb8981a 100644
--- a/sources/pyside2/tests/QtCore/qenum_test.py
+++ b/sources/pyside2/tests/QtCore/qenum_test.py
@@ -30,15 +30,18 @@
'''Test cases for QEnum and QFlags'''
+import gc
import os
import sys
+import pickle
import unittest
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from init_paths import init_test_paths
init_test_paths(False)
-from PySide2.QtCore import *
+from PySide2.QtCore import Qt, QIODevice
+
class TestEnum(unittest.TestCase):
@@ -73,6 +76,23 @@ class TestEnum(unittest.TestCase):
with self.assertRaises(TypeError):
a = k*2.0
+ @unittest.skipUnless(getattr(sys, "getobjects", None), "requires debug build")
+ def testEnumNew_NoLeak(self):
+ gc.collect()
+ total = sys.gettotalrefcount()
+ for idx in range(1000):
+ ret = Qt.Key(42)
+ gc.collect()
+ delta = sys.gettotalrefcount() - total
+ print("delta total refcount =", delta)
+ if abs(delta) >= 10:
+ all = sys.getobjects(0)
+ all.sort(key=lambda x: sys.getrefcount(x), reverse=True)
+ for ob in all[:10]:
+ print(sys.getrefcount(ob), ob)
+ self.assertTrue(abs(delta) < 10)
+
+
class TestQFlags(unittest.TestCase):
def testToItn(self):
om = QIODevice.NotOpen
@@ -94,5 +114,33 @@ class TestQFlags(unittest.TestCase):
except:
pass
+
+# PYSIDE-15: Pickling of enums
+class TestEnumPickling(unittest.TestCase):
+ def testPickleEnum(self):
+
+ # Pickling of enums with different depth works.
+ ret = pickle.loads(pickle.dumps(QIODevice.Append))
+ self.assertEqual(ret, QIODevice.Append)
+
+ ret = pickle.loads(pickle.dumps(Qt.Key.Key_Asterisk))
+ self.assertEqual(ret, Qt.Key.Key_Asterisk)
+ self.assertEqual(ret, Qt.Key(42))
+
+ # We can also pickle the whole enum class (built in):
+ ret = pickle.loads(pickle.dumps(QIODevice))
+
+ # This works also with nested classes for Python 3, after we
+ # introduced the correct __qualname__ attribute.
+
+ # Note: For Python 2, we would need quite strange patches.
+ func = lambda: pickle.loads(pickle.dumps(Qt.Key))
+ if sys.version_info[0] < 3:
+ with self.assertRaises(pickle.PicklingError):
+ func()
+ else:
+ func()
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/pyside2/tests/QtUiTools/loadUiType_test.py b/sources/pyside2/tests/QtUiTools/loadUiType_test.py
new file mode 100644
index 000000000..9a3756376
--- /dev/null
+++ b/sources/pyside2/tests/QtUiTools/loadUiType_test.py
@@ -0,0 +1,75 @@
+#############################################################################
+##
+## Copyright (C) 2020 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+import os
+import sys
+import unittest
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+from init_paths import init_test_paths
+init_test_paths(False)
+
+from helper.usesqapplication import UsesQApplication
+
+from PySide2.QtWidgets import QWidget, QFrame, QPushButton
+from PySide2.QtUiTools import loadUiType
+
+class loadUiTypeTester(UsesQApplication):
+ def testFunction(self):
+ filePath = os.path.join(os.path.dirname(__file__), "minimal.ui")
+ loaded = loadUiType(filePath)
+ self.assertNotEqual(loaded, None)
+
+ # (<class '__main__.Ui_Form'>, <class 'PySide2.QtWidgets.QFrame'>)
+ generated, base = loaded
+
+ # Generated class contains retranslateUi method
+ self.assertTrue("retranslateUi" in dir(generated))
+
+ # Base class instance will be QFrame for this example
+ self.assertTrue(isinstance(base(), QFrame))
+
+ anotherFileName = os.path.join(os.path.dirname(__file__), "test.ui")
+ another = loadUiType(anotherFileName)
+ self.assertNotEqual(another, None)
+
+ generated, base = another
+ # Base class instance will be QWidget for this example
+ self.assertTrue(isinstance(base(), QWidget))
+
+ w = base()
+ ui = generated()
+ ui.setupUi(w)
+
+ self.assertTrue(isinstance(ui.child_object, QFrame))
+ self.assertTrue(isinstance(ui.grandson_object, QPushButton))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside2/tests/QtWidgets/qwidget_test.py b/sources/pyside2/tests/QtWidgets/qwidget_test.py
index 74e97d7be..5e94a8248 100644
--- a/sources/pyside2/tests/QtWidgets/qwidget_test.py
+++ b/sources/pyside2/tests/QtWidgets/qwidget_test.py
@@ -61,7 +61,9 @@ class QWidgetTest(UsesQApplication):
if sys.version_info[0] < 3:
def testCallType_Issue_816(self):
thing = type(QWidget).__new__(type(QWidget), "", (), {})
- self.assertEqual(repr(thing), "<class '__main__.'>")
+ # PYSIDE-1286: This works now like in Python 3
+ #self.assertEqual(repr(thing), "<class '__main__.'>")
+ self.assertEqual(repr(thing), "<class '__main__.ObjectType'>")
class QWidgetVisible(UsesQApplication):
diff --git a/sources/pyside2/tests/registry/existence_test.py b/sources/pyside2/tests/registry/existence_test.py
index 4bfd63cc3..b8a42058d 100644
--- a/sources/pyside2/tests/registry/existence_test.py
+++ b/sources/pyside2/tests/registry/existence_test.py
@@ -1,6 +1,6 @@
#############################################################################
##
-## Copyright (C) 2019 The Qt Company Ltd.
+## Copyright (C) 2020 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
@@ -67,6 +67,7 @@ List entry
"""
import os
+import re
import sys
from textwrap import dedent
import unittest
@@ -144,8 +145,19 @@ class TestSignaturesExists(unittest.TestCase):
name = key.rsplit(".", 1)[-1]
if name in ("next", "__next__"): # ignore problematic cases
continue
+ if "<" in key:
+ # Skip over remaining crap in "<...>"
+ continue
+ if key.startswith("sample.SampleNamespace"):
+ # We cannot work with sample namespaces after the change to __qualname__.
+ continue
+ if (key.startswith("smart.SharedPtr") or
+ re.match(r"PySide2\..*?\.QSharedPointer_", key)):
+ # These mangled names are not supported.
+ # We should fix them.
+ continue
if key not in found_sigs:
- warn("missing key: '{}'".format(key), stacklevel=3)
+ warn("missing key: '{} value={}'".format(key, value), stacklevel=3)
else:
found_val = found_sigs[key]
if type(value) is list and (
diff --git a/sources/shiboken2/ApiExtractor/CMakeLists.txt b/sources/shiboken2/ApiExtractor/CMakeLists.txt
index 65150eb92..4232fef66 100644
--- a/sources/shiboken2/ApiExtractor/CMakeLists.txt
+++ b/sources/shiboken2/ApiExtractor/CMakeLists.txt
@@ -84,7 +84,7 @@ endif()
target_compile_definitions(apiextractor PRIVATE CMAKE_CXX_COMPILER="${CMAKE_CXX_COMPILER}")
-set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE)
+set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE)
if (BUILD_TESTS)
find_package(Qt5Test 5.12 REQUIRED)
diff --git a/sources/shiboken2/generator/CMakeLists.txt b/sources/shiboken2/generator/CMakeLists.txt
index 15b965d9d..51623414b 100644
--- a/sources/shiboken2/generator/CMakeLists.txt
+++ b/sources/shiboken2/generator/CMakeLists.txt
@@ -30,7 +30,7 @@ configure_file(shibokenconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/shibokenconfig.h
install(TARGETS shiboken2
EXPORT Shiboken2Targets
- DESTINATION bin)
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
set(shiboken_generator_package_name "shiboken2_generator")
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index c0c54f274..64467e3d1 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -4037,8 +4037,10 @@ void CppGenerator::writeClassDefinition(QTextStream &s,
}
s << INDENT << "{0, " << NULL_PTR << "}\n";
s << "};\n";
+
+ int packageLevel = packageName().count(QLatin1Char('.')) + 1;
s << "static PyType_Spec " << className << "_spec = {\n";
- s << INDENT << "\"" << computedClassTargetFullName << "\",\n";
+ s << INDENT << '"' << packageLevel << ':' << computedClassTargetFullName << "\",\n";
s << INDENT << "sizeof(SbkObject),\n";
s << INDENT << "0,\n";
s << INDENT << tp_flags << ",\n";
@@ -4667,6 +4669,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu
QString enumVarTypeObj;
if (!cppEnum->isAnonymous()) {
+ int packageLevel = packageName().count(QLatin1Char('.')) + 1;
FlagsTypeEntry *flags = enumTypeEntry->flags();
if (flags) {
// The following could probably be made nicer:
@@ -4674,7 +4677,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu
QString fullPath = getClassTargetFullName(cppEnum);
fullPath.truncate(fullPath.lastIndexOf(QLatin1Char('.')) + 1);
s << INDENT << cpythonTypeNameExt(flags) << " = PySide::QFlags::create(\""
- << fullPath << flags->flagsName() << "\", "
+ << packageLevel << ':' << fullPath << flags->flagsName() << "\", "
<< cpythonEnumName(cppEnum) << "_number_slots);\n";
}
@@ -4686,7 +4689,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu
{
Indentation indent(INDENT);
s << INDENT << '"' << cppEnum->name() << "\",\n";
- s << INDENT << '"' << getClassTargetFullName(cppEnum) << "\",\n";
+ s << INDENT << '"' << packageLevel << ':' << getClassTargetFullName(cppEnum) << "\",\n";
s << INDENT << '"' << (cppEnum->enclosingClass() ? (cppEnum->enclosingClass()->qualifiedCppName() + QLatin1String("::")) : QString());
s << cppEnum->name() << '"';
if (flags)
diff --git a/sources/shiboken2/libshiboken/autodecref.h b/sources/shiboken2/libshiboken/autodecref.h
index d3353b1e4..498b1aec4 100644
--- a/sources/shiboken2/libshiboken/autodecref.h
+++ b/sources/shiboken2/libshiboken/autodecref.h
@@ -96,8 +96,10 @@ public:
*/
void reset(PyObject *other)
{
- Py_XDECREF(m_pyObj);
+ // Safely decref m_pyObj. See Py_XSETREF in object.h .
+ PyObject *_py_tmp = m_pyObj;
m_pyObj = other;
+ Py_XDECREF(_py_tmp);
}
private:
PyObject *m_pyObj;
diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp
index b0d453cc5..78f4cbe8b 100644
--- a/sources/shiboken2/libshiboken/basewrapper.cpp
+++ b/sources/shiboken2/libshiboken/basewrapper.cpp
@@ -44,6 +44,7 @@
#include "sbkconverter.h"
#include "sbkenum.h"
#include "sbkstring.h"
+#include "sbkstaticstrings.h"
#include "sbkstaticstrings_p.h"
#include "autodecref.h"
#include "gilstate.h"
@@ -101,6 +102,23 @@ static PyGetSetDef SbkObjectType_Type_getsetlist[] = {
{nullptr} // Sentinel
};
+#if PY_VERSION_HEX < 0x03000000
+
+static PyObject *SbkObjectType_repr(PyObject *type)
+{
+ Shiboken::AutoDecRef mod(PyObject_GetAttr(type, Shiboken::PyMagicName::module()));
+ if (mod.isNull())
+ return nullptr;
+ Shiboken::AutoDecRef name(PyObject_GetAttr(type, Shiboken::PyMagicName::qualname()));
+ if (name.isNull())
+ return nullptr;
+ return PyString_FromFormat("<class '%s.%s'>",
+ PyString_AS_STRING(mod.object()),
+ PyString_AS_STRING(name.object()));
+}
+
+#endif // PY_VERSION_HEX < 0x03000000
+
static PyType_Slot SbkObjectType_Type_slots[] = {
{Py_tp_dealloc, reinterpret_cast<void *>(SbkObjectTypeDealloc)},
{Py_tp_setattro, reinterpret_cast<void *>(PyObject_GenericSetAttr)},
@@ -109,10 +127,13 @@ static PyType_Slot SbkObjectType_Type_slots[] = {
{Py_tp_new, reinterpret_cast<void *>(SbkObjectTypeTpNew)},
{Py_tp_free, reinterpret_cast<void *>(PyObject_GC_Del)},
{Py_tp_getset, reinterpret_cast<void *>(SbkObjectType_Type_getsetlist)},
+#if PY_VERSION_HEX < 0x03000000
+ {Py_tp_repr, reinterpret_cast<void *>(SbkObjectType_repr)},
+#endif
{0, nullptr}
};
static PyType_Spec SbkObjectType_Type_spec = {
- "Shiboken.ObjectType",
+ "1:Shiboken.ObjectType",
0, // basicsize (inserted later)
sizeof(PyMemberDef),
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
@@ -214,7 +235,7 @@ PyTypeObject *SbkObjectType_TypeF(void)
if (!type) {
SbkObjectType_Type_spec.basicsize =
PepHeapType_SIZE + sizeof(SbkObjectTypePrivate);
- type = reinterpret_cast<PyTypeObject *>(PyType_FromSpec(&SbkObjectType_Type_spec));
+ type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&SbkObjectType_Type_spec));
#if PY_VERSION_HEX < 0x03000000
if (patch_tp_new_wrapper(type) < 0)
return nullptr;
@@ -288,7 +309,7 @@ static PyType_Slot SbkObject_Type_slots[] = {
{0, nullptr}
};
static PyType_Spec SbkObject_Type_spec = {
- "Shiboken.Object",
+ "1:Shiboken.Object",
sizeof(SbkObject),
0,
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,
@@ -300,7 +321,7 @@ SbkObjectType *SbkObject_TypeF(void)
{
static PyTypeObject *type = nullptr;
if (!type) {
- type = reinterpret_cast<PyTypeObject *>(PyType_FromSpec(&SbkObject_Type_spec));
+ type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&SbkObject_Type_spec));
Py_TYPE(type) = SbkObjectType_TypeF();
Py_INCREF(Py_TYPE(type));
type->tp_weaklistoffset = offsetof(SbkObject, weakreflist);
@@ -614,8 +635,7 @@ PyObject *SbkQAppTpNew(PyTypeObject *subtype, PyObject *, PyObject *)
return self == nullptr ? nullptr : _setupNew(self, subtype);
}
-PyObject *
-SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *)
+PyObject *SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *)
{
// PYSIDE-595: Give the same error as type_call does when tp_new is NULL.
PyErr_Format(PyExc_TypeError,
@@ -624,6 +644,51 @@ SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *)
return nullptr;
}
+PyObject *SbkType_FromSpec(PyType_Spec *spec)
+{
+ return SbkType_FromSpecWithBases(spec, nullptr);
+}
+
+PyObject *SbkType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
+{
+ // PYSIDE-1286: Generate correct __module__ and __qualname__
+ // The name field can now be extended by an "n:" prefix which is
+ // the number of modules in the name. The default is 1.
+ //
+ // Example:
+ // "2:mainmod.submod.mainclass.subclass"
+ // results in
+ // __module__ : "mainmod.submod"
+ // __qualname__ : "mainclass.subclass"
+ // __name__ : "subclass"
+
+ PyType_Spec new_spec = *spec;
+ const char *colon = strchr(spec->name, ':');
+ assert(colon);
+ int package_level = atoi(spec->name);
+ const char *mod = new_spec.name = colon + 1;
+
+ PyObject *type = PyType_FromSpecWithBases(&new_spec, bases);
+ if (type == nullptr)
+ return nullptr;
+
+ const char *qual = mod;
+ for (int idx = package_level; idx > 0; --idx) {
+ const char *dot = strchr(qual, '.');
+ if (!dot)
+ break;
+ qual = dot + 1;
+ }
+ int mlen = qual - mod - 1;
+ Shiboken::AutoDecRef module(Shiboken::String::fromCString(mod, mlen));
+ Shiboken::AutoDecRef qualname(Shiboken::String::fromCString(qual));
+ if (PyObject_SetAttr(type, Shiboken::PyMagicName::module(), module) < 0)
+ return nullptr;
+ if (PyObject_SetAttr(type, Shiboken::PyMagicName::qualname(), qualname) < 0)
+ return nullptr;
+ return type;
+}
+
} //extern "C"
@@ -745,13 +810,13 @@ void init()
Shiboken::ObjectType::initPrivateData(SbkObject_TypeF());
if (PyType_Ready(SbkEnumType_TypeF()) < 0)
- Py_FatalError("[libshiboken] Failed to initialise Shiboken.SbkEnumType metatype.");
+ Py_FatalError("[libshiboken] Failed to initialize Shiboken.SbkEnumType metatype.");
if (PyType_Ready(SbkObjectType_TypeF()) < 0)
- Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapperType metatype.");
+ Py_FatalError("[libshiboken] Failed to initialize Shiboken.BaseWrapperType metatype.");
if (PyType_Ready(reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())) < 0)
- Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapper type.");
+ Py_FatalError("[libshiboken] Failed to initialize Shiboken.BaseWrapper type.");
VoidPtr::init();
@@ -901,7 +966,7 @@ introduceWrapperType(PyObject *enclosingObject,
{
typeSpec->slots[0].pfunc = reinterpret_cast<void *>(baseType ? baseType : SbkObject_TypeF());
- PyObject *heaptype = PyType_FromSpecWithBases(typeSpec, baseTypes);
+ PyObject *heaptype = SbkType_FromSpecWithBases(typeSpec, baseTypes);
Py_TYPE(heaptype) = SbkObjectType_TypeF();
Py_INCREF(Py_TYPE(heaptype));
auto *type = reinterpret_cast<SbkObjectType *>(heaptype);
diff --git a/sources/shiboken2/libshiboken/basewrapper.h b/sources/shiboken2/libshiboken/basewrapper.h
index 813870dac..4132b5cc5 100644
--- a/sources/shiboken2/libshiboken/basewrapper.h
+++ b/sources/shiboken2/libshiboken/basewrapper.h
@@ -122,6 +122,10 @@ LIBSHIBOKEN_API PyObject *SbkQAppTpNew(PyTypeObject *subtype, PyObject *args, Py
/// PYSIDE-939: Replaced by Sbk_object_dealloc.
LIBSHIBOKEN_API PyObject *SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *);
+/// PYSIDE-1286: Generate correct __module__ and __qualname__
+LIBSHIBOKEN_API PyObject *SbkType_FromSpec(PyType_Spec *);
+LIBSHIBOKEN_API PyObject *SbkType_FromSpecWithBases(PyType_Spec *, PyObject *);
+
} // extern "C"
namespace Shiboken
diff --git a/sources/shiboken2/libshiboken/pep384impl.cpp b/sources/shiboken2/libshiboken/pep384impl.cpp
index c04848eb3..f07cac613 100644
--- a/sources/shiboken2/libshiboken/pep384impl.cpp
+++ b/sources/shiboken2/libshiboken/pep384impl.cpp
@@ -638,6 +638,38 @@ PepType_GetNameStr(PyTypeObject *type)
/*****************************************************************************
*
+ * Newly introduced convenience functions
+ *
+ */
+#if PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API)
+
+PyObject *
+PyImport_GetModule(PyObject *name)
+{
+ PyObject *m;
+ PyObject *modules = PyImport_GetModuleDict();
+ if (modules == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules");
+ return NULL;
+ }
+ Py_INCREF(modules);
+ if (PyDict_CheckExact(modules)) {
+ m = PyDict_GetItemWithError(modules, name); /* borrowed */
+ Py_XINCREF(m);
+ }
+ else {
+ m = PyObject_GetItem(modules, name);
+ if (m == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
+ PyErr_Clear();
+ }
+ }
+ Py_DECREF(modules);
+ return m;
+}
+
+#endif // PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API)
+/*****************************************************************************
+ *
* Extra support for name mangling
*
*/
diff --git a/sources/shiboken2/libshiboken/pep384impl.h b/sources/shiboken2/libshiboken/pep384impl.h
index e735095e8..541b0e775 100644
--- a/sources/shiboken2/libshiboken/pep384impl.h
+++ b/sources/shiboken2/libshiboken/pep384impl.h
@@ -523,6 +523,16 @@ extern LIBSHIBOKEN_API PyTypeObject *PepMethodDescr_TypePtr;
/*****************************************************************************
*
+ * Newly introduced convenience functions
+ *
+ * This is not defined if Py_LIMITED_API is defined.
+ */
+#if PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API)
+LIBSHIBOKEN_API PyObject *PyImport_GetModule(PyObject *name);
+#endif // PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API)
+
+/*****************************************************************************
+ *
* Runtime support for Python 3.8 incompatibilities
*
*/
diff --git a/sources/shiboken2/libshiboken/sbkenum.cpp b/sources/shiboken2/libshiboken/sbkenum.cpp
index 65f63ca81..36f2f48f9 100644
--- a/sources/shiboken2/libshiboken/sbkenum.cpp
+++ b/sources/shiboken2/libshiboken/sbkenum.cpp
@@ -107,16 +107,18 @@ static PyObject *SbkEnum_tp_new(PyTypeObject *type, PyObject *args, PyObject *)
if (!self)
return nullptr;
self->ob_value = itemValue;
- PyObject *item = Shiboken::Enum::getEnumItemFromValue(type, itemValue);
- if (item) {
- self->ob_name = SbkEnumObject_name(item, nullptr);
- Py_XDECREF(item);
- } else {
- self->ob_name = nullptr;
- }
+ Shiboken::AutoDecRef item(Shiboken::Enum::getEnumItemFromValue(type, itemValue));
+ self->ob_name = item.object() ? SbkEnumObject_name(item, nullptr) : nullptr;
return reinterpret_cast<PyObject *>(self);
}
+void enum_object_dealloc(PyObject *ob)
+{
+ auto self = reinterpret_cast<SbkEnumObject *>(ob);
+ Py_XDECREF(self->ob_name);
+ Sbk_object_dealloc(ob);
+}
+
static PyObject *enum_op(enum_func f, PyObject *a, PyObject *b) {
PyObject *valA = a;
PyObject *valB = b;
@@ -260,6 +262,23 @@ static PyGetSetDef SbkEnumGetSetList[] = {
{nullptr, nullptr, nullptr, nullptr, nullptr} // Sentinel
};
+#if PY_VERSION_HEX < 0x03000000
+
+static PyObject *SbkEnumType_repr(PyObject *type)
+{
+ Shiboken::AutoDecRef mod(PyObject_GetAttr(type, Shiboken::PyMagicName::module()));
+ if (mod.isNull())
+ return nullptr;
+ Shiboken::AutoDecRef name(PyObject_GetAttr(type, Shiboken::PyMagicName::qualname()));
+ if (name.isNull())
+ return nullptr;
+ return PyString_FromFormat("<class '%s.%s'>",
+ PyString_AS_STRING(mod.object()),
+ PyString_AS_STRING(name.object()));
+}
+
+#endif // PY_VERSION_HEX < 0x03000000
+
static void SbkEnumTypeDealloc(PyObject *pyObj);
static PyObject *SbkEnumTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds);
@@ -287,10 +306,13 @@ static PyType_Slot SbkEnumType_Type_slots[] = {
{Py_tp_alloc, (void *)PyType_GenericAlloc},
{Py_tp_new, (void *)SbkEnumTypeTpNew},
{Py_tp_free, (void *)PyObject_GC_Del},
+#if PY_VERSION_HEX < 0x03000000
+ {Py_tp_repr, (void *)SbkEnumType_repr},
+#endif
{0, nullptr}
};
static PyType_Spec SbkEnumType_Type_spec = {
- "Shiboken.EnumType",
+ "1:Shiboken.EnumType",
0, // filled in later
sizeof(PyMemberDef),
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES,
@@ -304,7 +326,7 @@ PyTypeObject *SbkEnumType_TypeF(void)
if (!type) {
SbkEnumType_Type_spec.basicsize =
PepHeapType_SIZE + sizeof(SbkEnumTypePrivate);
- type = (PyTypeObject *)PyType_FromSpec(&SbkEnumType_Type_spec);
+ type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&SbkEnumType_Type_spec));
}
return type;
}
@@ -341,6 +363,107 @@ PyObject *SbkEnumTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwd
} // extern "C"
+///////////////////////////////////////////////////////////////
+//
+// PYSIDE-15: Pickling Support for Qt Enum objects
+// This works very well and fixes the issue.
+//
+extern "C" {
+
+static void init_enum(); // forward
+
+static PyObject *enum_unpickler = nullptr;
+
+// Pickling: reduce the Qt Enum object
+static PyObject *enum___reduce__(PyObject *obj)
+{
+ init_enum();
+ return Py_BuildValue("O(Ni)",
+ enum_unpickler,
+ Py_BuildValue("s", Py_TYPE(obj)->tp_name),
+ PyInt_AS_LONG(obj));
+}
+
+} // extern "C"
+
+namespace Shiboken { namespace Enum {
+
+// Unpickling: rebuild the Qt Enum object
+PyObject *unpickleEnum(PyObject *enum_class_name, PyObject *value)
+{
+ Shiboken::AutoDecRef parts(PyObject_CallMethod(enum_class_name,
+ const_cast<char *>("split"), const_cast<char *>("s"), "."));
+ if (parts.isNull())
+ return nullptr;
+ PyObject *top_name = PyList_GetItem(parts, 0); // borrowed ref
+ if (top_name == nullptr)
+ return nullptr;
+ PyObject *module = PyImport_GetModule(top_name);
+ if (module == nullptr) {
+ PyErr_Format(PyExc_ImportError, "could not import module %.200s",
+ Shiboken::String::toCString(top_name));
+ return nullptr;
+ }
+ Shiboken::AutoDecRef cur_thing(module);
+ int len = PyList_Size(parts);
+ for (int idx = 1; idx < len; ++idx) {
+ PyObject *name = PyList_GetItem(parts, idx); // borrowed ref
+ PyObject *thing = PyObject_GetAttr(cur_thing, name);
+ if (thing == nullptr) {
+ PyErr_Format(PyExc_ImportError, "could not import Qt Enum type %.200s",
+ Shiboken::String::toCString(enum_class_name));
+ return nullptr;
+ }
+ cur_thing.reset(thing);
+ }
+ PyObject *klass = cur_thing;
+ return PyObject_CallFunctionObjArgs(klass, value, nullptr);
+}
+
+} // namespace Enum
+} // namespace Shiboken
+
+extern "C" {
+
+// Initialization
+static bool _init_enum()
+{
+ static PyObject *shiboken_name = Py_BuildValue("s", "shiboken2");
+ if (shiboken_name == nullptr)
+ return false;
+ Shiboken::AutoDecRef shibo(PyImport_GetModule(shiboken_name));
+ if (shibo.isNull())
+ return false;
+ Shiboken::AutoDecRef sub(PyObject_GetAttr(shibo, shiboken_name));
+ PyObject *mod = sub.object();
+ if (mod == nullptr) {
+ // We are in the build dir and already in shiboken.
+ PyErr_Clear();
+ mod = shibo.object();
+ }
+ enum_unpickler = PyObject_GetAttrString(mod, "_unpickle_enum");
+ if (enum_unpickler == nullptr)
+ return false;
+ return true;
+}
+
+static void init_enum()
+{
+ if (!(enum_unpickler || _init_enum()))
+ Py_FatalError("could not load enum pickling helper function");
+}
+
+static PyMethodDef SbkEnumObject_Methods[] = {
+ {const_cast<char *>("__reduce__"), reinterpret_cast<PyCFunction>(enum___reduce__),
+ METH_NOARGS, nullptr},
+ {nullptr, nullptr, 0, nullptr} // Sentinel
+};
+
+} // extern "C"
+
+//
+///////////////////////////////////////////////////////////////
+
namespace Shiboken {
class DeclaredEnumTypes
@@ -376,7 +499,7 @@ PyObject *getEnumItemFromValue(PyTypeObject *enumType, long itemValue)
while (PyDict_Next(values, &pos, &key, &value)) {
auto *obj = reinterpret_cast<SbkEnumObject *>(value);
if (obj->ob_value == itemValue) {
- Py_INCREF(obj);
+ Py_INCREF(value);
return value;
}
}
@@ -501,6 +624,7 @@ static PyType_Slot SbkNewType_slots[] = {
{Py_tp_repr, (void *)SbkEnumObject_repr},
{Py_tp_str, (void *)SbkEnumObject_repr},
{Py_tp_getset, (void *)SbkEnumGetSetList},
+ {Py_tp_methods, (void *)SbkEnumObject_Methods},
{Py_tp_new, (void *)SbkEnum_tp_new},
{Py_nb_add, (void *)enum_add},
{Py_nb_subtract, (void *)enum_subtract},
@@ -522,7 +646,7 @@ static PyType_Slot SbkNewType_slots[] = {
{Py_nb_index, (void *)enum_int},
{Py_tp_richcompare, (void *)enum_richcompare},
{Py_tp_hash, (void *)enum_hash},
- {Py_tp_dealloc, (void *)Sbk_object_dealloc},
+ {Py_tp_dealloc, (void *)enum_object_dealloc},
{0, nullptr}
};
static PyType_Spec SbkNewType_spec = {
@@ -594,7 +718,7 @@ newTypeWithName(const char *name,
const char *cppName,
PyTypeObject *numbers_fromFlag)
{
- // Careful: PyType_FromSpec does not allocate the string.
+ // Careful: SbkType_FromSpec does not allocate the string.
PyType_Slot newslots[99] = {}; // enough but not too big for the stack
auto *newspec = new PyType_Spec;
newspec->name = strdup(name);
@@ -611,9 +735,8 @@ newTypeWithName(const char *name,
if (numbers_fromFlag)
copyNumberMethods(numbers_fromFlag, newslots, &idx);
newspec->slots = newslots;
- auto *type = reinterpret_cast<PyTypeObject *>(PyType_FromSpec(newspec));
+ auto *type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(newspec));
Py_TYPE(type) = SbkEnumType_TypeF();
- Py_INCREF(Py_TYPE(type));
auto *enumType = reinterpret_cast<SbkEnumType *>(type);
PepType_SETP(enumType)->cppName = cppName;
@@ -659,7 +782,7 @@ DeclaredEnumTypes::DeclaredEnumTypes() = default;
DeclaredEnumTypes::~DeclaredEnumTypes()
{
/*
- * PYSIDE-595: This was "delete *it;" before introducing 'PyType_FromSpec'.
+ * PYSIDE-595: This was "delete *it;" before introducing 'SbkType_FromSpec'.
* XXX what should I do now?
* Refcounts in tests are 30 or 0 at end.
* When I add the default tp_dealloc, we get negative refcounts!
diff --git a/sources/shiboken2/libshiboken/sbkenum.h b/sources/shiboken2/libshiboken/sbkenum.h
index 759d72636..c294c17d9 100644
--- a/sources/shiboken2/libshiboken/sbkenum.h
+++ b/sources/shiboken2/libshiboken/sbkenum.h
@@ -114,6 +114,8 @@ namespace Enum
LIBSHIBOKEN_API void setTypeConverter(PyTypeObject *enumType, SbkConverter *converter);
/// Returns the converter assigned to the enum \p type.
LIBSHIBOKEN_API SbkConverter *getTypeConverter(PyTypeObject *enumType);
+
+ LIBSHIBOKEN_API PyObject *unpickleEnum(PyObject *, PyObject *);
}
} // namespace Shiboken
diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp
index 3681a093d..c19665176 100644
--- a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp
+++ b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp
@@ -75,6 +75,7 @@ STATIC_STRING_IMPL(ecf, "__ecf__")
STATIC_STRING_IMPL(file, "__file__")
STATIC_STRING_IMPL(module, "__module__")
STATIC_STRING_IMPL(name, "__name__")
+STATIC_STRING_IMPL(qualname, "__qualname__")
// Internal:
STATIC_STRING_IMPL(base, "__base__")
diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.h b/sources/shiboken2/libshiboken/sbkstaticstrings.h
index a951899b6..07d6cc60a 100644
--- a/sources/shiboken2/libshiboken/sbkstaticstrings.h
+++ b/sources/shiboken2/libshiboken/sbkstaticstrings.h
@@ -61,6 +61,7 @@ LIBSHIBOKEN_API PyObject *ecf();
LIBSHIBOKEN_API PyObject *file();
LIBSHIBOKEN_API PyObject *module();
LIBSHIBOKEN_API PyObject *name();
+LIBSHIBOKEN_API PyObject *qualname();
} // namespace PyMagicName
} // namespace Shiboken
diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp
index 5430ab064..ba1fc119e 100644
--- a/sources/shiboken2/libshiboken/signature.cpp
+++ b/sources/shiboken2/libshiboken/signature.cpp
@@ -39,6 +39,7 @@
#include "basewrapper.h"
#include "autodecref.h"
+#include "sbkstring.h"
#include "sbkstaticstrings.h"
#include "sbkstaticstrings_p.h"
@@ -185,7 +186,6 @@ _get_class_of_sm(PyObject *ob_sm)
static PyObject *
_get_class_of_descr(PyObject *ob)
{
- Shiboken::AutoDecRef func_name(PyObject_GetAttr(ob, Shiboken::PyMagicName::name()));
return PyObject_GetAttr(ob, Shiboken::PyMagicName::objclass());
}
@@ -318,6 +318,20 @@ pyside_tp_get___signature__(PyObject *obtype_mod, PyObject *modifier)
static PyObject *
GetSignature_Cached(PyObject *props, PyObject *func_kind, PyObject *modifier);
+// Helper for __qualname__ which might not always exist in Python 2 (type).
+static PyObject *
+_get_qualname(PyObject *ob)
+{
+ // We support __qualname__ for types, only.
+ assert(PyType_Check(ob));
+ PyObject *name = PyObject_GetAttr(ob, Shiboken::PyMagicName::qualname());
+ if (name == nullptr) {
+ PyErr_Clear();
+ name = PyObject_GetAttr(ob, Shiboken::PyMagicName::name());
+ }
+ return name;
+}
+
static PyObject *
GetTypeKey(PyObject *ob)
{
@@ -334,19 +348,20 @@ GetTypeKey(PyObject *ob)
*
* This is the PyCFunction behavior, as opposed to Python functions.
*/
- Shiboken::AutoDecRef class_name(PyObject_GetAttr(ob, Shiboken::PyMagicName::name()));
+ // PYSIDE-1286: We use correct __module__ and __qualname__, now.
Shiboken::AutoDecRef module_name(PyObject_GetAttr(ob, Shiboken::PyMagicName::module()));
-
- if (module_name.isNull())
+ if (module_name.isNull()) {
+ // We have no module_name because this is a module ;-)
PyErr_Clear();
-
- // Note: if we have a module, then __module__ is null, and we get
- // the module name through __name__ .
- if (class_name.isNull())
+ module_name.reset(PyObject_GetAttr(ob, Shiboken::PyMagicName::name()));
+ return Py_BuildValue("O", module_name.object());
+ }
+ Shiboken::AutoDecRef class_name(_get_qualname(ob));
+ if (class_name.isNull()) {
+ Py_FatalError("Signature: missing class name in GetTypeKey");
return nullptr;
- if (module_name.object())
- return Py_BuildValue("(OO)", module_name.object(), class_name.object());
- return Py_BuildValue("O", class_name.object());
+ }
+ return Py_BuildValue("(OO)", module_name.object(), class_name.object());
}
static PyObject *empty_dict = nullptr;
@@ -402,7 +417,6 @@ GetSignature_Wrapper(PyObject *ob, PyObject *modifier)
Shiboken::AutoDecRef func_name(PyObject_GetAttr(ob, Shiboken::PyMagicName::name()));
Shiboken::AutoDecRef objclass(PyObject_GetAttr(ob, Shiboken::PyMagicName::objclass()));
Shiboken::AutoDecRef class_key(GetTypeKey(objclass));
-
if (func_name.isNull() || objclass.isNull() || class_key.isNull())
return nullptr;
PyObject *dict = TypeKey_to_PropsDict(class_key, objclass);
@@ -851,12 +865,15 @@ get_signature(PyObject * /* self */, PyObject *args)
////////////////////////////////////////////////////////////////////////////
// a stack trace for linux-like platforms
#include <stdio.h>
-#include <execinfo.h>
+#if defined(__GLIBC__)
+# include <execinfo.h>
+#endif
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
void handler(int sig) {
+#if defined(__GLIBC__)
void *array[30];
size_t size;
@@ -864,8 +881,11 @@ void handler(int sig) {
size = backtrace(array, 30);
// print out all the frames to stderr
+#endif
fprintf(stderr, "Error: signal %d:\n", sig);
+#if defined(__GLIBC__)
backtrace_symbols_fd(array, size, STDERR_FILENO);
+#endif
exit(1);
}
diff --git a/sources/shiboken2/libshiboken/voidptr.cpp b/sources/shiboken2/libshiboken/voidptr.cpp
index 46f49b67e..6ac3c131d 100644
--- a/sources/shiboken2/libshiboken/voidptr.cpp
+++ b/sources/shiboken2/libshiboken/voidptr.cpp
@@ -340,7 +340,7 @@ static PyType_Slot SbkVoidPtrType_slots[] = {
{0, nullptr}
};
static PyType_Spec SbkVoidPtrType_spec = {
- "shiboken2.libshiboken.VoidPtr",
+ "2:shiboken2.shiboken2.VoidPtr",
sizeof(SbkVoidPtrObject),
0,
Py_TPFLAGS_DEFAULT,
@@ -353,16 +353,15 @@ static PyType_Spec SbkVoidPtrType_spec = {
PyTypeObject *SbkVoidPtrTypeF(void)
{
static PyTypeObject *type = nullptr;
- if (!type)
- type = reinterpret_cast<PyTypeObject *>(PyType_FromSpec(&SbkVoidPtrType_spec));
-
+ if (!type) {
+ type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&SbkVoidPtrType_spec));
#if PY_VERSION_HEX < 0x03000000
- type->tp_as_buffer = &SbkVoidPtrObjectBufferProc;
- type->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
+ type->tp_as_buffer = &SbkVoidPtrObjectBufferProc;
+ type->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
#else
- PepType_AS_BUFFER(type) = &SbkVoidPtrObjectBufferProc;
+ PepType_AS_BUFFER(type) = &SbkVoidPtrObjectBufferProc;
#endif
-
+ }
return type;
}
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/backport_inspect.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/backport_inspect.py
index 1f6d70b31..0f9598c64 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/backport_inspect.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/backport_inspect.py
@@ -109,8 +109,13 @@ CO_NOFREE = 0x0040
###############################################################################
+
+# PYSIDE-1286: We now use the added __qualname__ for classes.
+def _get_class_name(cls):
+ return getattr(cls, "__qualname__", cls.__name__)
+
# This function was changed: 'builtins' and 'qualname' don't exist.
-# We use '__builtin__' and '__name__' instead.
+# We use '__builtin__' and '__(qual)?name__' instead.
def formatannotation(annotation, base_module=None):
if getattr(annotation, '__module__', None) == 'typing':
# The replace must not be done on Python 2.7 because it
@@ -118,8 +123,8 @@ def formatannotation(annotation, base_module=None):
return repr(annotation) ##.replace('typing.', '')
if isinstance(annotation, type):
if annotation.__module__ in ('__builtin__', base_module):
- return annotation.__name__
- return annotation.__module__+'.'+annotation.__name__
+ return _get_class_name(annotation)
+ return annotation.__module__ + '.' + _get_class_name(annotation)
return repr(annotation)
@@ -393,7 +398,7 @@ class Parameter(object):
return formatted
def __repr__(self):
- return '<{} "{}">'.format(self.__class__.__name__, self)
+ return '<{} "{}">'.format(_get_class_name(self.__class__), self)
def __hash__(self):
return hash((self.name, self.kind, self.annotation, self.default))
@@ -536,7 +541,7 @@ class BoundArguments(object):
args = []
for arg, value in self.arguments.items():
args.append('{}={!r}'.format(arg, value))
- return '<{} ({})>'.format(self.__class__.__name__, ', '.join(args))
+ return '<{} ({})>'.format(_get_class_name(self.__class__), ', '.join(args))
class Signature(object):
@@ -842,7 +847,7 @@ class Signature(object):
self._return_annotation = state['_return_annotation']
def __repr__(self):
- return '<{} {}>'.format(self.__class__.__name__, self)
+ return '<{} {}>'.format(_get_class_name(self.__class__), self)
def __str__(self):
result = []
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py
index 67ff67722..4dbed077d 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py
@@ -1,6 +1,6 @@
#############################################################################
##
-## Copyright (C) 2019 The Qt Company Ltd.
+## Copyright (C) 2020 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
@@ -56,6 +56,8 @@ enough to produce a useful ValueError.
This matter will be improved in a later version.
"""
+import sys
+
from shibokensupport.signature import inspect
from shibokensupport.signature import get_signature
from shibokensupport.signature.mapping import update_mapping, namespace
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py
index 0417f132a..7af43bea0 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py
@@ -70,7 +70,7 @@ def finish_import(module):
if func:
func(module)
except Exception as e:
- name = e.__class__.__name__
+ name = e.__class__.__qualname__
print(72 * "*")
print("Error in deprecated.py, ignored:")
print(" {name}: {e}".format(**locals()))
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py
index f11f3cf3d..fa4d5e77c 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py
@@ -1,6 +1,6 @@
#############################################################################
##
-## Copyright (C) 2018 The Qt Company Ltd.
+## Copyright (C) 2020 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
@@ -100,17 +100,19 @@ class ExactEnumerator(object):
return ret
def klass(self, class_name, klass):
+ ret = self.result_type()
+ if "<" in class_name:
+ # This is happening in QtQuick for some reason:
+ ## class QSharedPointer<QQuickItemGrabResult >:
+ # We simply skip over this class.
+ return ret
bases_list = []
for base in klass.__bases__:
name = base.__name__
- if name in ("object", "type"):
- pass
- else:
- modname = base.__module__
- name = modname + "." + base.__name__
+ if name not in ("object", "type"):
+ name = base.__module__ + "." + name
bases_list.append(name)
class_str = "{}({})".format(class_name, ", ".join(bases_list))
- ret = self.result_type()
# class_members = inspect.getmembers(klass)
# gives us also the inherited things.
class_members = sorted(list(klass.__dict__.items()))
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py
index 6564786b9..1efc6fde5 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py
@@ -75,14 +75,18 @@ try:
except NameError:
ModuleNotFoundError = ImportError
+def _qualname(x):
+ return getattr(x, "__qualname__", x.__name__)
+
# patching inspect's formatting to keep the word "typing":
def formatannotation(annotation, base_module=None):
# if getattr(annotation, '__module__', None) == 'typing':
# return repr(annotation).replace('typing.', '')
if isinstance(annotation, type):
+ name = _qualname(annotation)
if annotation.__module__ in ('builtins', base_module):
- return annotation.__qualname__
- return annotation.__module__ + '.' + annotation.__qualname__
+ return name
+ return annotation.__module__ + '.' + name
return repr(annotation)
# Note also that during the tests we have a different encoding that would
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py
index 8d970956b..2053c3e9d 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py
@@ -165,6 +165,11 @@ def try_to_guess(thing, valtype):
return ret
return None
+def get_name(thing):
+ if isinstance(thing, type):
+ return getattr(thing, "__qualname__", thing.__name__)
+ else:
+ return thing.__name__
def _resolve_value(thing, valtype, line):
if thing in ("0", "None") and valtype:
@@ -172,7 +177,7 @@ def _resolve_value(thing, valtype, line):
return None
map = type_map[valtype]
# typing.Any: '_SpecialForm' object has no attribute '__name__'
- name = map.__name__ if hasattr(map, "__name__") else str(map)
+ name = get_name(map) if hasattr(map, "__name__") else str(map)
thing = "zero({})".format(name)
if thing in type_map:
return type_map[thing]
@@ -212,7 +217,8 @@ def to_string(thing):
return thing
if hasattr(thing, "__name__"):
dot = "." in str(thing)
- return thing.__module__ + "." + thing.__name__ if dot else thing.__name__
+ name = get_name(thing)
+ return thing.__module__ + "." + name if dot else name
# Note: This captures things from the typing module:
return str(thing)
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/typing27.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/typing27.py
index 44d78c433..41ed456cc 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/typing27.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/typing27.py
@@ -184,11 +184,8 @@ __all__ = [
def _qualname(x):
- if sys.version_info[:2] >= (3, 3):
- return x.__qualname__
- else:
- # Fall back to just name.
- return x.__name__
+ # PYSIDE-1286: Support __qualname__ in Python 2
+ return getattr(x, "__qualname__", x.__name__)
def _trim_name(nm):
diff --git a/sources/shiboken2/shibokenmodule/typesystem_shiboken.xml b/sources/shiboken2/shibokenmodule/typesystem_shiboken.xml
index bdb0c9338..3eba557fb 100644
--- a/sources/shiboken2/shibokenmodule/typesystem_shiboken.xml
+++ b/sources/shiboken2/shibokenmodule/typesystem_shiboken.xml
@@ -103,6 +103,12 @@
</inject-code>
</add-function>
+ <add-function signature="_unpickle_enum(PyObject*, PyObject*)" return-type="PyObject*">
+ <inject-code>
+ %PYARG_0 = Shiboken::Enum::unpickleEnum(%1, %2);
+ </inject-code>
+ </add-function>
+
<extra-includes>
<include file-name="sbkversion.h" location="local"/>
<include file-name="voidptr.h" location="local"/>