aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside2
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside2')
-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
19 files changed, 364 insertions, 52 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 (