Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6')
-rw-r--r--sources/pyside6/PySide6/QtCore/CMakeLists.txt22
-rw-r--r--sources/pyside6/PySide6/QtCore/glue/core_snippets.cpp99
-rw-r--r--sources/pyside6/PySide6/QtCore/glue/core_snippets_p.h10
-rw-r--r--sources/pyside6/PySide6/QtCore/typesystem_core_common.xml14
-rw-r--r--sources/pyside6/PySide6/QtWidgets/typesystem_widgets_common.xml5
-rw-r--r--sources/pyside6/PySide6/QtXml/typesystem_xml.xml4
-rw-r--r--sources/pyside6/PySide6/glue/qtcore.cpp57
-rw-r--r--sources/pyside6/libpyside/CMakeLists.txt2
-rw-r--r--sources/pyside6/libpyside/pysidemetafunction.cpp8
-rw-r--r--sources/pyside6/libpyside/pysideproperty.cpp25
-rw-r--r--sources/pyside6/libpyside/pysidevariantutils.cpp216
-rw-r--r--sources/pyside6/libpyside/pysidevariantutils.h37
-rw-r--r--sources/pyside6/libpyside/signalmanager.cpp71
-rw-r--r--sources/pyside6/libpyside/signalmanager.h8
-rw-r--r--sources/pyside6/tests/QtCore/deepcopy_test.py6
-rw-r--r--sources/pyside6/tests/QtCore/qobject_property_test.py34
-rw-r--r--sources/pyside6/tests/QtCore/repr_test.py6
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_433.py2
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_919.py9
-rw-r--r--sources/pyside6/tests/QtWidgets/qapp_issue_585.py10
-rw-r--r--sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py8
-rw-r--r--sources/pyside6/tests/QtWidgets/qmenu_test.py18
-rw-r--r--sources/pyside6/tests/QtXml/qdomdocument_test.py23
-rw-r--r--sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py2
24 files changed, 468 insertions, 228 deletions
diff --git a/sources/pyside6/PySide6/QtCore/CMakeLists.txt b/sources/pyside6/PySide6/QtCore/CMakeLists.txt
index d559f9d96..fff6cc8b0 100644
--- a/sources/pyside6/PySide6/QtCore/CMakeLists.txt
+++ b/sources/pyside6/PySide6/QtCore/CMakeLists.txt
@@ -19,9 +19,6 @@ if(ENABLE_WIN)
set(SPECIFIC_OS_FILES
${QtCore_GEN_DIR}/qwineventnotifier_wrapper.cpp
)
-else()
- set(SPECIFIC_OS_FILES
- ${QtCore_GEN_DIR}/qprocess_unixprocessparameters_wrapper.cpp)
endif()
set(QtCore_SRC
@@ -130,8 +127,6 @@ ${QtCore_GEN_DIR}/qpersistentmodelindex_wrapper.cpp
${QtCore_GEN_DIR}/qpluginloader_wrapper.cpp
${QtCore_GEN_DIR}/qpoint_wrapper.cpp
${QtCore_GEN_DIR}/qpointf_wrapper.cpp
-${QtCore_GEN_DIR}/qprocess_wrapper.cpp
-${QtCore_GEN_DIR}/qprocessenvironment_wrapper.cpp
${QtCore_GEN_DIR}/qpropertyanimation_wrapper.cpp
${QtCore_GEN_DIR}/qrandomgenerator64_wrapper.cpp
${QtCore_GEN_DIR}/qrandomgenerator_wrapper.cpp
@@ -236,6 +231,23 @@ else()
list(APPEND QtCore_SRC ${QtCore_GEN_DIR}/qsharedmemory_wrapper.cpp)
endif()
+if("process" IN_LIST QtCore_disabled_features)
+ list(APPEND QtCore_DROPPED_ENTRIES QProcess)
+ message(STATUS "Qt${QT_MAJOR_VERSION}Core: Dropping QProcess")
+else()
+ list(APPEND QtCore_SRC ${QtCore_GEN_DIR}/qprocess_wrapper.cpp)
+ if(NOT ENABLE_WIN)
+ list(APPEND QtCore_SRC ${QtCore_GEN_DIR}/qprocess_unixprocessparameters_wrapper.cpp)
+ endif()
+endif()
+
+if("processenvironment" IN_LIST QtCore_disabled_features)
+ list(APPEND QtCore_DROPPED_ENTRIES QProcessEnvironment)
+ message(STATUS "Qt${QT_MAJOR_VERSION}Core: Dropping QProcessEnvironment")
+else()
+ list(APPEND QtCore_SRC ${QtCore_GEN_DIR}/qprocessenvironment_wrapper.cpp)
+endif()
+
configure_file("${QtCore_SOURCE_DIR}/QtCore_global.post.h.in"
"${QtCore_BINARY_DIR}/QtCore_global.post.h" @ONLY)
diff --git a/sources/pyside6/PySide6/QtCore/glue/core_snippets.cpp b/sources/pyside6/PySide6/QtCore/glue/core_snippets.cpp
index e58d54998..9b2b40e82 100644
--- a/sources/pyside6/PySide6/QtCore/glue/core_snippets.cpp
+++ b/sources/pyside6/PySide6/QtCore/glue/core_snippets.cpp
@@ -19,105 +19,6 @@
#include <QtCore/QObject>
#include <QtCore/QRegularExpression>
#include <QtCore/QStack>
-#include <QtCore/QVariant>
-
-// Helpers for QVariant conversion
-
-QMetaType QVariant_resolveMetaType(PyTypeObject *type)
-{
- if (!PyObject_TypeCheck(type, SbkObjectType_TypeF()))
- return {};
- const char *typeName = Shiboken::ObjectType::getOriginalName(type);
- if (!typeName)
- return {};
- const bool valueType = '*' != typeName[qstrlen(typeName) - 1];
- // Do not convert user type of value
- if (valueType && Shiboken::ObjectType::isUserType(type))
- return {};
- QMetaType metaType = QMetaType::fromName(typeName);
- if (metaType.isValid())
- return metaType;
- // Do not resolve types to value type
- if (valueType)
- return {};
- // Find in base types. First check tp_bases, and only after check tp_base, because
- // tp_base does not always point to the first base class, but rather to the first
- // that has added any python fields or slots to its object layout.
- // See https://mail.python.org/pipermail/python-list/2009-January/520733.html
- if (type->tp_bases) {
- const auto size = PyTuple_Size(type->tp_bases);
- Py_ssize_t i = 0;
- // PYSIDE-1887, PYSIDE-86: Skip QObject base class of QGraphicsObject;
- // it needs to use always QGraphicsItem as a QVariant type for
- // QGraphicsItem::itemChange() to work.
- if (qstrcmp(typeName, "QGraphicsObject*") == 0)
- ++i;
- for ( ; i < size; ++i) {
- auto baseType = reinterpret_cast<PyTypeObject *>(PyTuple_GetItem(type->tp_bases, i));
- const QMetaType derived = QVariant_resolveMetaType(baseType);
- if (derived.isValid())
- return derived;
- }
- } else if (type->tp_base) {
- return QVariant_resolveMetaType(type->tp_base);
- }
- return {};
-}
-
-QVariant QVariant_convertToValueList(PyObject *list)
-{
- if (PySequence_Size(list) < 0) {
- // clear the error if < 0 which means no length at all
- PyErr_Clear();
- return {};
- }
-
- Shiboken::AutoDecRef element(PySequence_GetItem(list, 0));
-
- auto *type = reinterpret_cast<PyTypeObject *>(element.object());
- QMetaType metaType = QVariant_resolveMetaType(type);
- if (!metaType.isValid())
- return {};
-
- const QByteArray listTypeName = QByteArrayLiteral("QList<") + metaType.name() + '>';
- metaType = QMetaType::fromName(listTypeName);
- if (!metaType.isValid())
- return {};
-
- Shiboken::Conversions::SpecificConverter converter(listTypeName);
- if (!converter) {
- qWarning("Type converter for: %s not registered.", listTypeName.constData());
- return {};
- }
-
- QVariant var(metaType);
- converter.toCpp(list, &var);
- return var;
-}
-
-bool QVariant_isStringList(PyObject *list)
-{
- if (!PySequence_Check(list)) {
- // If it is not a list or a derived list class
- // we assume that will not be a String list neither.
- return false;
- }
-
- if (PySequence_Size(list) < 0) {
- // clear the error if < 0 which means no length at all
- PyErr_Clear();
- return false;
- }
-
- Shiboken::AutoDecRef fast(PySequence_Fast(list, "Failed to convert QVariantList"));
- const Py_ssize_t size = PySequence_Size(fast.object());
- for (Py_ssize_t i = 0; i < size; ++i) {
- Shiboken::AutoDecRef item(PySequence_GetItem(fast.object(), i));
- if (PyUnicode_Check(item) == 0)
- return false;
- }
- return true;
-}
// Helpers for qAddPostRoutine
diff --git a/sources/pyside6/PySide6/QtCore/glue/core_snippets_p.h b/sources/pyside6/PySide6/QtCore/glue/core_snippets_p.h
index 11e84b291..4c1867a1a 100644
--- a/sources/pyside6/PySide6/QtCore/glue/core_snippets_p.h
+++ b/sources/pyside6/PySide6/QtCore/glue/core_snippets_p.h
@@ -14,10 +14,8 @@
QT_FORWARD_DECLARE_CLASS(QGenericArgument)
QT_FORWARD_DECLARE_CLASS(QGenericReturnArgument)
-QT_FORWARD_DECLARE_CLASS(QMetaType)
QT_FORWARD_DECLARE_CLASS(QObject)
QT_FORWARD_DECLARE_CLASS(QRegularExpression)
-QT_FORWARD_DECLARE_CLASS(QVariant);
QT_BEGIN_NAMESPACE
namespace QtCoreHelper {
@@ -26,14 +24,6 @@ class QGenericReturnArgumentHolder;
}
QT_END_NAMESPACE
-// Helpers for QVariant conversion
-
-QMetaType QVariant_resolveMetaType(PyTypeObject *type);
-
-QVariant QVariant_convertToValueList(PyObject *list);
-
-bool QVariant_isStringList(PyObject *list);
-
// Helpers for qAddPostRoutine
namespace PySide {
void globalPostRoutineCallback();
diff --git a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
index 207844c56..26c3ecab1 100644
--- a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
+++ b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
@@ -16,6 +16,7 @@
<extra-includes>
<include file-name="pysidemetatype.h" location="global"/>
<include file-name="pysideutils.h" location="global"/> <!-- QString conversion -->
+ <include file-name="pysidevariantutils.h" location="global"/> <!-- QVariant conversion -->
<include file-name="signalmanager.h" location="global"/>
<include file-name="sbkerrors.h" location="global"/>
<!-- QtCoreHelper::QGenericReturnArgumentHolder -->
@@ -320,6 +321,7 @@
<extra-includes>
<include file-name="optional" location="global"/>
<include file-name="pysideqenum.h" location="global"/>
+ <include file-name="pysidevariantutils.h" location="global"/>
</extra-includes>
<conversion-rule>
<native-to-target file="../glue/qtcore.cpp" snippet="return-qvariant"/>
@@ -391,6 +393,9 @@
</object-type>
<primitive-type name="QJsonObject">
+ <extra-includes>
+ <include file-name="pysidevariantutils.h" location="global"/>
+ </extra-includes>
<conversion-rule>
<native-to-target file="../glue/qtcore.cpp" snippet="return-qjsonobject"/>
<target-to-native>
@@ -934,9 +939,12 @@
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qdatetime-2"/>
</add-function>
<!-- PYSIDE-1735: Qt::TimeSpec is no more compatible with int -->
- <add-function signature="QDateTime(int@year@,int@month@,int@day@,int@h@,int@m@,int@s@,int@ms@,Qt::TimeSpec@spec@=Qt::LocalTime)">
+ <add-function signature="QDateTime(int@year@,int@month@,int@day@,int@h@,int@m@,int@s@,int@ms@,Qt::TimeSpec@spec@)">
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qdatetime-3"/>
</add-function>
+ <add-function signature="QDateTime(int@year@,int@month@,int@day@,int@h@,int@m@,int@s@,int@ms@,QTimeZone@spec@=QTimeZone::LocalTime)" since="6.5">
+ <inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qdatetime-4"/>
+ </add-function>
<add-function signature="__repr__" return-type="str">
<inject-code class="target" position="beginning">
<insert-template name="repr_code">
@@ -2661,7 +2669,9 @@
<?if !windows?>
<enum-type name="UnixProcessFlag" flags="UnixProcessFlags" since="6.6"/>
- <value-type name="UnixProcessParameters" since="6.6"/>
+ <value-type name="UnixProcessParameters">
+ <configuration condition="QT_CONFIG(process)"/>
+ </value-type>
<?endif?>
<modify-function signature="waitForStarted(int)" allow-thread="yes"/>
diff --git a/sources/pyside6/PySide6/QtWidgets/typesystem_widgets_common.xml b/sources/pyside6/PySide6/QtWidgets/typesystem_widgets_common.xml
index a15527c03..c6e93cfd7 100644
--- a/sources/pyside6/PySide6/QtWidgets/typesystem_widgets_common.xml
+++ b/sources/pyside6/PySide6/QtWidgets/typesystem_widgets_common.xml
@@ -1489,6 +1489,7 @@
<enum-type name="InputMode"/>
<modify-function signature="getInt(QWidget*,const QString&amp;,const QString&amp;,int,int,int,int,bool*,QFlags&lt;Qt::WindowType&gt;)" allow-thread="yes">
+ <modify-argument index="1" pyi-type="Optional[PySide6.QtWidgets.QWidget]"/>
<modify-argument index="return" pyi-type="Tuple[int, bool]"/>
<modify-argument index="8">
<remove-default-expression/>
@@ -1500,6 +1501,7 @@
</modify-function>
<modify-function signature="getItem(QWidget*,const QString&amp;,const QString&amp;,const QStringList&amp;,int,bool,bool*,QFlags&lt;Qt::WindowType&gt;,QFlags&lt;Qt::InputMethodHint&gt;)" allow-thread="yes">
+ <modify-argument index="1" pyi-type="Optional[PySide6.QtWidgets.QWidget]"/>
<modify-argument index="return" pyi-type="Tuple[str, bool]"/>
<modify-argument index="7">
<remove-default-expression/>
@@ -1511,6 +1513,7 @@
</modify-function>
<modify-function signature="getMultiLineText(QWidget*,const QString&amp;,const QString&amp;,const QString&amp;,bool*,QFlags&lt;Qt::WindowType&gt;,QFlags&lt;Qt::InputMethodHint&gt;)" allow-thread="yes">
+ <modify-argument index="1" pyi-type="Optional[PySide6.QtWidgets.QWidget]"/>
<modify-argument index="return" pyi-type="Tuple[str, bool]"/>
<modify-argument index="5">
<remove-default-expression/>
@@ -1522,6 +1525,7 @@
</modify-function>
<modify-function signature="getText(QWidget*,const QString&amp;,const QString&amp;,QLineEdit::EchoMode,const QString&amp;,bool*,QFlags&lt;Qt::WindowType&gt;,QFlags&lt;Qt::InputMethodHint&gt;)" allow-thread="yes">
+ <modify-argument index="1" pyi-type="Optional[PySide6.QtWidgets.QWidget]"/>
<modify-argument index="return" pyi-type="Tuple[str, bool]"/>
<modify-argument index="6">
<remove-default-expression/>
@@ -1533,6 +1537,7 @@
</modify-function>
<modify-function signature="getDouble(QWidget*,const QString&amp;,const QString&amp;,double,double,double,int,bool*,QFlags&lt;Qt::WindowType&gt;,double)" allow-thread="yes">
+ <modify-argument index="1" pyi-type="Optional[PySide6.QtWidgets.QWidget]"/>
<modify-argument index="return" pyi-type="Tuple[float, bool]"/>
<modify-argument index="8">
<remove-default-expression/>
diff --git a/sources/pyside6/PySide6/QtXml/typesystem_xml.xml b/sources/pyside6/PySide6/QtXml/typesystem_xml.xml
index 089978b6d..93d3c1f56 100644
--- a/sources/pyside6/PySide6/QtXml/typesystem_xml.xml
+++ b/sources/pyside6/PySide6/QtXml/typesystem_xml.xml
@@ -20,7 +20,7 @@
<enum-type name="ParseOption" flags="ParseOptions" since="6.5"/>
<!-- will be replaced in inject code -->
- <value-type name="ParseResult"/>
+ <value-type name="ParseResult" operator-bool="yes"/>
<modify-function signature="setContent(const QByteArray&amp;,bool,QString*,int*,int*)">
<modify-argument index="3">
@@ -130,6 +130,8 @@
</modify-argument>
<inject-code class="target" position="beginning" file="../glue/qtxml.cpp" snippet="qdomdocument-setcontent" />
</modify-function>
+ <declare-function signature="setContent(const QByteArray&amp;@data@, QDomDocument::ParseOptions@options@=QDomDocument::ParseOption::Default)"
+ return-type="QDomDocument::ParseResult" since="6.8" />
</value-type>
<value-type name="QDomDocumentFragment"/>
diff --git a/sources/pyside6/PySide6/glue/qtcore.cpp b/sources/pyside6/PySide6/glue/qtcore.cpp
index 78a25f0a1..cd1462676 100644
--- a/sources/pyside6/PySide6/glue/qtcore.cpp
+++ b/sources/pyside6/PySide6/glue/qtcore.cpp
@@ -225,49 +225,6 @@ return %out;
// @snippet conversion-qmetatype-pytypeobject
// @snippet qvariant-conversion
-static QVariant QVariant_convertToVariantMap(PyObject *map)
-{
- Py_ssize_t pos = 0;
- Shiboken::AutoDecRef keys(PyDict_Keys(map));
- if (!QVariant_isStringList(keys))
- return {};
- PyObject *key{};
- PyObject *value{};
- QMap<QString,QVariant> ret;
- while (PyDict_Next(map, &pos, &key, &value)) {
- QString cppKey = %CONVERTTOCPP[QString](key);
- QVariant cppValue = %CONVERTTOCPP[QVariant](value);
- ret.insert(cppKey, cppValue);
- }
- return QVariant(ret);
-}
-static QVariant QVariant_convertToVariantList(PyObject *list)
-{
- if (QVariant_isStringList(list)) {
- QList<QString > lst = %CONVERTTOCPP[QList<QString>](list);
- return QVariant(QStringList(lst));
- }
- QVariant valueList = QVariant_convertToValueList(list);
- if (valueList.isValid())
- return valueList;
-
- if (PySequence_Size(list) < 0) {
- // clear the error if < 0 which means no length at all
- PyErr_Clear();
- return {};
- }
-
- QList<QVariant> lst;
- Shiboken::AutoDecRef fast(PySequence_Fast(list, "Failed to convert QVariantList"));
- const Py_ssize_t size = PySequence_Size(fast.object());
- for (Py_ssize_t i = 0; i < size; ++i) {
- Shiboken::AutoDecRef pyItem(PySequence_GetItem(fast.object(), i));
- QVariant item = %CONVERTTOCPP[QVariant](pyItem);
- lst.append(item);
- }
- return QVariant(lst);
-}
-
using SpecificConverter = Shiboken::Conversions::SpecificConverter;
static std::optional<SpecificConverter> converterForQtType(const char *typeNameC)
@@ -535,6 +492,12 @@ QTime time(%4, %5, %6, %7);
Shiboken::Warnings::warnDeprecated("QDateTime", "QDateTime(..., Qt::TimeSpec spec)");
// @snippet qdatetime-3
+// @snippet qdatetime-4
+QDate date(%1, %2, %3);
+QTime time(%4, %5, %6, %7);
+%0 = new %TYPE(date, time, QTimeZone(%8));
+// @snippet qdatetime-4
+
// @snippet qdatetime-topython
QDate date = %CPPSELF.date();
QTime time = %CPPSELF.time();
@@ -1538,7 +1501,7 @@ if (Shiboken::Enum::check(%in)) {
metaType = QMetaType::fromName(typeName);
}
if (!metaType.isValid())
- metaType = QVariant_resolveMetaType(Py_TYPE(%in));
+ metaType = PySide::Variant::resolveMetaType(Py_TYPE(%in));
bool ok = false;
if (metaType.isValid()) {
@@ -1560,12 +1523,12 @@ if (!ok)
// @snippet conversion-sbkobject
// @snippet conversion-pydict
-QVariant ret = QVariant_convertToVariantMap(%in);
+QVariant ret = PySide::Variant::convertToVariantMap(%in);
%out = ret.isValid() ? ret : QVariant::fromValue(PySide::PyObjectWrapper(%in));
// @snippet conversion-pydict
// @snippet conversion-pylist
-QVariant ret = QVariant_convertToVariantList(%in);
+QVariant ret = PySide::Variant::convertToVariantList(%in);
%out = ret.isValid() ? ret : QVariant::fromValue(PySide::PyObjectWrapper(%in));
// @snippet conversion-pylist
@@ -1575,7 +1538,7 @@ QVariant ret = QVariant_convertToVariantList(%in);
// @snippet conversion-pyobject
// @snippet conversion-qjsonobject-pydict
-QVariant dict = QVariant_convertToVariantMap(%in);
+QVariant dict = PySide::Variant::convertToVariantMap(%in);
QJsonValue val = QJsonValue::fromVariant(dict);
%out = val.toObject();
// @snippet conversion-qjsonobject-pydict
diff --git a/sources/pyside6/libpyside/CMakeLists.txt b/sources/pyside6/libpyside/CMakeLists.txt
index 539f1f329..15ab47494 100644
--- a/sources/pyside6/libpyside/CMakeLists.txt
+++ b/sources/pyside6/libpyside/CMakeLists.txt
@@ -40,6 +40,7 @@ set(libpyside_HEADERS # installed below
pysideslot_p.h
pysidestaticstrings.h
pysideutils.h
+ pysidevariantutils.h
pysideweakref.h
qobjectconnect.h
signalmanager.h
@@ -59,6 +60,7 @@ set(libpyside_SRC
pysidesignal.cpp
pysideslot.cpp
pysideproperty.cpp
+ pysidevariantutils.cpp
pysideweakref.cpp
pyside.cpp
pyside_numpy.cpp
diff --git a/sources/pyside6/libpyside/pysidemetafunction.cpp b/sources/pyside6/libpyside/pysidemetafunction.cpp
index 48aba3c7b..7a496c4b7 100644
--- a/sources/pyside6/libpyside/pysidemetafunction.cpp
+++ b/sources/pyside6/libpyside/pysidemetafunction.cpp
@@ -4,6 +4,8 @@
#include "pysidemetafunction.h"
#include "pysidemetafunction_p.h"
+#include <signalmanager.h>
+
#include <autodecref.h>
#include <basewrapper.h>
#include <sbkconverter.h>
@@ -12,6 +14,8 @@
#include <QtCore/qmetaobject.h>
+using namespace Qt::StringLiterals;
+
extern "C"
{
@@ -164,6 +168,10 @@ bool call(QObject *self, int methodIndex, PyObject *args, PyObject **retVal)
QString tmp;
converter.toCpp(obj, &tmp);
methValues[i] = tmp;
+ } else if (metaType.id() == PyObjectWrapper::metaTypeId()) {
+ // Manual conversion, see PyObjectWrapper converter registration
+ methValues[i] = QVariant::fromValue(PyObjectWrapper(obj.object()));
+ methArgs[i] = methValues[i].data();
} else {
converter.toCpp(obj, methArgs[i]);
}
diff --git a/sources/pyside6/libpyside/pysideproperty.cpp b/sources/pyside6/libpyside/pysideproperty.cpp
index e8ea2fa03..69d347043 100644
--- a/sources/pyside6/libpyside/pysideproperty.cpp
+++ b/sources/pyside6/libpyside/pysideproperty.cpp
@@ -6,6 +6,7 @@
#include "pysideproperty_p.h"
#include "pysidesignal.h"
#include "pysidesignal_p.h"
+#include "signalmanager.h"
#include <autodecref.h>
#include <pep384ext.h>
@@ -17,6 +18,8 @@
using namespace Shiboken;
+using namespace Qt::StringLiterals;
+
extern "C"
{
@@ -148,16 +151,20 @@ void PySidePropertyPrivate::metaCall(PyObject *source, QMetaObject::Call call, v
switch (call) {
case QMetaObject::ReadProperty: {
AutoDecRef value(getValue(source));
- auto *obValue = value.object();
- if (obValue) {
- Conversions::SpecificConverter converter(typeName);
- if (converter) {
- converter.toCpp(obValue, args[0]);
- } else {
- // PYSIDE-2160: Report an unknown type name to the caller `qtPropertyMetacall`.
- PyErr_SetObject(PyExc_StopIteration, obValue);
- }
+ if (value.isNull())
+ return;
+ if (typeName == "PyObject"_ba) {
+ // Manual conversion, see PyObjectWrapper converter registration
+ auto *pw = reinterpret_cast<PySide::PyObjectWrapper *>(args[0]);
+ pw->reset(value.object());
+ return;
+ }
+ if (Conversions::SpecificConverter converter(typeName); converter) {
+ converter.toCpp(value.object(), args[0]);
+ return;
}
+ // PYSIDE-2160: Report an unknown type name to the caller `qtPropertyMetacall`.
+ PyErr_SetObject(PyExc_StopIteration, value.object());
}
break;
diff --git a/sources/pyside6/libpyside/pysidevariantutils.cpp b/sources/pyside6/libpyside/pysidevariantutils.cpp
new file mode 100644
index 000000000..729557919
--- /dev/null
+++ b/sources/pyside6/libpyside/pysidevariantutils.cpp
@@ -0,0 +1,216 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "pysidevariantutils.h"
+#include "pysideutils.h"
+
+#include <QtCore/qvariantmap.h>
+
+#include <autodecref.h>
+#include <sbkconverter.h>
+#include <basewrapper.h>
+
+using namespace Qt::StringLiterals;
+
+static const char qVariantTypeName[] = "QVariant";
+
+static void warnConverter(const char *name)
+{
+ qWarning("Type converter for: %s not registered.", name);
+}
+
+// Helper converting each item of a non-empty list using the "QVariant" converter
+static std::optional<QVariantList> pyListToVariantListHelper(PyObject *list, Py_ssize_t size)
+{
+ Q_ASSERT(size > 0);
+ QVariantList result;
+ result.reserve(size);
+ Shiboken::Conversions::SpecificConverter converter(qVariantTypeName);
+ if (!converter) {
+ warnConverter(qVariantTypeName);
+ return std::nullopt;
+ }
+ for (Py_ssize_t i = 0; i < size; ++i) {
+ Shiboken::AutoDecRef pyItem(PySequence_GetItem(list, i));
+ QVariant item;
+ converter.toCpp(pyItem.object(), &item);
+ result.append(item);
+ }
+ return result;
+}
+
+// Helper checking for a sequence of Unicode objects
+static bool isStringList(PyObject *list)
+{
+ const Py_ssize_t size = PySequence_Size(list);
+ if (size == 0)
+ return false;
+ for (Py_ssize_t i = 0; i < size; ++i) {
+ Shiboken::AutoDecRef item(PySequence_GetItem(list, i));
+ if (PyUnicode_Check(item) == 0)
+ return false;
+ }
+ return true;
+}
+
+// Helper to convert to a QStringList
+static std::optional<QStringList> listToStringList(PyObject *list)
+{
+ static const char listType[] = "QList<QString>";
+ Shiboken::Conversions::SpecificConverter converter(listType);
+ if (!converter) {
+ warnConverter(listType);
+ return std::nullopt;
+ }
+ QStringList result;
+ converter.toCpp(list, &result);
+ return result;
+}
+
+// Helper to convert a non-empty, homogenous list using the converter of the first item
+static QVariant convertToValueList(PyObject *list)
+{
+ Q_ASSERT(PySequence_Size(list) >= 0);
+
+ Shiboken::AutoDecRef element(PySequence_GetItem(list, 0));
+
+ auto *type = reinterpret_cast<PyTypeObject *>(element.object());
+ QMetaType metaType = PySide::Variant::resolveMetaType(type);
+ if (!metaType.isValid())
+ return {};
+
+ const QByteArray listTypeName = QByteArrayLiteral("QList<") + metaType.name() + '>';
+ metaType = QMetaType::fromName(listTypeName);
+ if (!metaType.isValid())
+ return {};
+
+ Shiboken::Conversions::SpecificConverter converter(listTypeName);
+ if (!converter) {
+ warnConverter(listTypeName.constData());
+ return {};
+ }
+
+ QVariant var(metaType);
+ converter.toCpp(list, &var);
+ return var;
+}
+
+namespace PySide::Variant
+{
+
+QMetaType resolveMetaType(PyTypeObject *type)
+{
+ if (!PyObject_TypeCheck(type, SbkObjectType_TypeF()))
+ return {};
+ const char *typeName = Shiboken::ObjectType::getOriginalName(type);
+ if (!typeName)
+ return {};
+ const bool valueType = '*' != typeName[qstrlen(typeName) - 1];
+ // Do not convert user type of value
+ if (valueType && Shiboken::ObjectType::isUserType(type))
+ return {};
+ QMetaType metaType = QMetaType::fromName(typeName);
+ if (metaType.isValid())
+ return metaType;
+ // Do not resolve types to value type
+ if (valueType)
+ return {};
+ // Find in base types. First check tp_bases, and only after check tp_base, because
+ // tp_base does not always point to the first base class, but rather to the first
+ // that has added any python fields or slots to its object layout.
+ // See https://mail.python.org/pipermail/python-list/2009-January/520733.html
+ if (type->tp_bases) {
+ const auto size = PyTuple_Size(type->tp_bases);
+ Py_ssize_t i = 0;
+ // PYSIDE-1887, PYSIDE-86: Skip QObject base class of QGraphicsObject;
+ // it needs to use always QGraphicsItem as a QVariant type for
+ // QGraphicsItem::itemChange() to work.
+ if (qstrcmp(typeName, "QGraphicsObject*") == 0 && size > 1) {
+ auto *firstBaseType = reinterpret_cast<PyTypeObject *>(PyTuple_GetItem(type->tp_bases, 0));
+ const char *firstBaseTypeName = Shiboken::ObjectType::getOriginalName(firstBaseType);
+ if (firstBaseTypeName != nullptr && qstrcmp(firstBaseTypeName, "QObject*") == 0)
+ ++i;
+ }
+ for ( ; i < size; ++i) {
+ auto baseType = reinterpret_cast<PyTypeObject *>(PyTuple_GetItem(type->tp_bases, i));
+ const QMetaType derived = resolveMetaType(baseType);
+ if (derived.isValid())
+ return derived;
+ }
+ return {};
+ }
+ if (type->tp_base != nullptr)
+ return resolveMetaType(type->tp_base);
+ return {};
+}
+
+std::optional<QVariantList> pyListToVariantList(PyObject *list)
+{
+ if (list == nullptr || PySequence_Check(list) == 0)
+ return std::nullopt;
+ const auto size = PySequence_Size(list);
+ if (size < 0) { // Some infinite (I/O read) thing? - bail out
+ PyErr_Clear();
+ return std::nullopt;
+ }
+ if (size == 0)
+ return QVariantList{};
+ return pyListToVariantListHelper(list, size);
+}
+
+QVariant convertToVariantList(PyObject *list)
+{
+ const auto size = PySequence_Size(list);
+ if (size < 0) { // Some infinite (I/O read) thing? - bail out
+ PyErr_Clear();
+ return {};
+ }
+ if (size == 0)
+ return QVariantList{};
+
+ if (isStringList(list)) {
+ auto stringListO = listToStringList(list);
+ if (stringListO.has_value())
+ return {stringListO.value()};
+ }
+
+ if (QVariant valueList = convertToValueList(list); valueList.isValid())
+ return valueList;
+
+ if (auto vlO = pyListToVariantListHelper(list, size); vlO.has_value())
+ return vlO.value();
+
+ return {};
+}
+
+QVariant convertToVariantMap(PyObject *map)
+{
+ if (map == nullptr || PyDict_Check(map) == 0)
+ return {};
+
+ QVariantMap result;
+ if (PyDict_Size(map) == 0)
+ return result;
+
+ Py_ssize_t pos = 0;
+ Shiboken::AutoDecRef keys(PyDict_Keys(map));
+ if (!isStringList(keys))
+ return {};
+
+ Shiboken::Conversions::SpecificConverter converter(qVariantTypeName);
+ if (!converter) {
+ warnConverter(qVariantTypeName);
+ return {};
+ }
+
+ PyObject *key{};
+ PyObject *value{};
+ while (PyDict_Next(map, &pos, &key, &value)) {
+ QVariant cppValue;
+ converter.toCpp(value, &cppValue);
+ result.insert(PySide::pyUnicodeToQString(key), cppValue);
+ }
+ return result;
+}
+
+} // namespace PySide::Variant
diff --git a/sources/pyside6/libpyside/pysidevariantutils.h b/sources/pyside6/libpyside/pysidevariantutils.h
new file mode 100644
index 000000000..b53f7ce82
--- /dev/null
+++ b/sources/pyside6/libpyside/pysidevariantutils.h
@@ -0,0 +1,37 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef PYSIDEVARIANTUTILS_H
+#define PYSIDEVARIANTUTILS_H
+
+#include <sbkpython.h>
+
+#include <pysidemacros.h>
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qvariantlist.h>
+
+#include <optional>
+
+namespace PySide::Variant
+{
+
+/// Return a QMetaType for a PyTypeObject for purposes of
+/// converting to a QVariant.
+PYSIDE_API QMetaType resolveMetaType(PyTypeObject *type);
+
+/// Convert a heterogenous Python list to a QVariantList by converting each
+/// item using the QVariant converter.
+PYSIDE_API std::optional<QVariantList> pyListToVariantList(PyObject *list);
+
+/// Converts a list to a QVariant following the PySide semantics:
+/// - A list of strings is returned as QVariant<QStringList>
+/// - A list of convertible values is returned as QVariant<QList<Value>>
+/// - Remaining types are returned as QVariant(QVariantList)
+PYSIDE_API QVariant convertToVariantList(PyObject *list);
+
+/// Converts a map to a QVariantMap (string keys and QVariant values)
+PYSIDE_API QVariant convertToVariantMap(PyObject *map);
+} // namespace PySide::Variant
+
+#endif // PYSIDEVARIANTUTILS_H
diff --git a/sources/pyside6/libpyside/signalmanager.cpp b/sources/pyside6/libpyside/signalmanager.cpp
index 933edd318..305d2f5c3 100644
--- a/sources/pyside6/libpyside/signalmanager.cpp
+++ b/sources/pyside6/libpyside/signalmanager.cpp
@@ -24,9 +24,12 @@
#include <QtCore/qcoreevent.h>
#include <QtCore/qdebug.h>
#include <QtCore/qhash.h>
+#include <QtCore/qmetatype.h>
#include <QtCore/qscopedpointer.h>
+#include <climits>
#include <memory>
+#include <utility>
using namespace Qt::StringLiterals;
@@ -36,6 +39,8 @@ using namespace Qt::StringLiterals;
static PyObject *metaObjectAttr = nullptr;
+static int pyObjectWrapperMetaTypeId = QMetaType::UnknownType;
+
static void destroyMetaObject(PyObject *obj)
{
void *ptr = PyCapsule_GetPointer(obj, nullptr);
@@ -125,6 +130,17 @@ PyObjectWrapper::PyObjectWrapper(const PyObjectWrapper &other)
Py_XINCREF(m_me);
}
+PyObjectWrapper::PyObjectWrapper(PyObjectWrapper &&other) noexcept
+ : m_me{std::exchange(other.m_me, nullptr)}
+{
+}
+
+PyObjectWrapper &PyObjectWrapper::operator=(PyObjectWrapper &&other) noexcept
+{
+ m_me = std::exchange(other.m_me, nullptr);
+ return *this;
+}
+
PyObjectWrapper::~PyObjectWrapper()
{
// Check that Python is still initialized as sometimes this is called by a static destructor
@@ -156,6 +172,10 @@ PyObjectWrapper::operator PyObject *() const
return m_me;
}
+int PyObjectWrapper::metaTypeId()
+{
+ return pyObjectWrapperMetaTypeId;
+}
int PyObjectWrapper::toInt() const
{
@@ -221,7 +241,29 @@ QDataStream &operator>>(QDataStream &in, PyObjectWrapper &myObj)
return in;
}
-};
+PYSIDE_API QDebug operator<<(QDebug debug, const PyObjectWrapper &myObj)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+ // Do not repeat the type name as it is typically called from the QVariant debug
+ // operator, which outputs the type.
+ debug << '<';
+ if (PyObject *ob = myObj) {
+ const auto refs = Py_REFCNT(ob);
+ debug << Py_TYPE(ob)->tp_name << " at " << ob;
+ if (refs == UINT_MAX) // _Py_IMMORTAL_REFCNT
+ debug << ", immortal";
+ else
+ debug << ", refs=" << refs;
+ } else {
+ debug << '0';
+ }
+ debug << '>';
+ return debug;
+}
+
+} // namespace PySide
using namespace PySide;
@@ -238,19 +280,11 @@ struct SignalManagerPrivate
SignalManager::QmlMetaCallErrorHandler
SignalManagerPrivate::m_qmlMetaCallErrorHandler = nullptr;
-static void PyObject_PythonToCpp_PyObject_PTR(PyObject *pyIn, void *cppOut)
-{
- *reinterpret_cast<PyObject **>(cppOut) = pyIn;
-}
-static PythonToCppFunc is_PyObject_PythonToCpp_PyObject_PTR_Convertible(PyObject * /* pyIn */)
-{
- return PyObject_PythonToCpp_PyObject_PTR;
-}
-static PyObject *PyObject_PTR_CppToPython_PyObject(const void *cppIn)
+static PyObject *CopyCppToPythonPyObject(const void *cppIn)
{
- auto *pyOut = reinterpret_cast<PyObject *>(const_cast<void *>(cppIn));
- if (pyOut)
- Py_INCREF(pyOut);
+ const auto *wrapper = reinterpret_cast<const PyObjectWrapper *>(cppIn);
+ PyObject *pyOut = *wrapper;
+ Py_XINCREF(pyOut);
return pyOut;
}
@@ -260,13 +294,16 @@ void SignalManager::init()
using namespace Shiboken;
// Register PyObject type to use in queued signal and slot connections
- qRegisterMetaType<PyObjectWrapper>("PyObject");
+ pyObjectWrapperMetaTypeId = qRegisterMetaType<PyObjectWrapper>("PyObject");
// Register QVariant(enum) conversion to QVariant(int)
QMetaType::registerConverter<PyObjectWrapper, int>(&PyObjectWrapper::toInt);
- SbkConverter *converter = Shiboken::Conversions::createConverter(&PyBaseObject_Type, nullptr);
- Shiboken::Conversions::setCppPointerToPythonFunction(converter, PyObject_PTR_CppToPython_PyObject);
- Shiboken::Conversions::setPythonToCppPointerFunctions(converter, PyObject_PythonToCpp_PyObject_PTR, is_PyObject_PythonToCpp_PyObject_PTR_Convertible);
+ // Register a shiboken converter for PyObjectWrapper->Python (value conversion).
+ // Python->PyObjectWrapper is not registered since the converters do not work for
+ // non-SbkObject types (falling back to plain pointer pass through).
+ // This conversion needs to be done manually via QVariant.
+ SbkConverter *converter = Shiboken::Conversions::createConverter(&PyBaseObject_Type,
+ CopyCppToPythonPyObject);
Shiboken::Conversions::registerConverterName(converter, "PyObject");
Shiboken::Conversions::registerConverterName(converter, "object");
Shiboken::Conversions::registerConverterName(converter, "PyObjectWrapper");
diff --git a/sources/pyside6/libpyside/signalmanager.h b/sources/pyside6/libpyside/signalmanager.h
index d5c007dbe..9fe56efc2 100644
--- a/sources/pyside6/libpyside/signalmanager.h
+++ b/sources/pyside6/libpyside/signalmanager.h
@@ -14,6 +14,7 @@
#include <optional>
QT_FORWARD_DECLARE_CLASS(QDataStream)
+QT_FORWARD_DECLARE_CLASS(QDebug)
namespace PySide
{
@@ -22,13 +23,13 @@ namespace PySide
class PYSIDE_API PyObjectWrapper
{
public:
- PyObjectWrapper(PyObjectWrapper&&) = delete;
- PyObjectWrapper& operator=(PyObjectWrapper &&) = delete;
PyObjectWrapper();
explicit PyObjectWrapper(PyObject* me);
PyObjectWrapper(const PyObjectWrapper &other);
PyObjectWrapper& operator=(const PyObjectWrapper &other);
+ PyObjectWrapper(PyObjectWrapper&&) noexcept;
+ PyObjectWrapper &operator=(PyObjectWrapper &&) noexcept;
void reset(PyObject *o);
@@ -43,12 +44,15 @@ public:
// The proper fix would be to associate PyObjectWrapper to the corresponding C++ Enum.
int toInt() const;
+ static int metaTypeId();
+
private:
PyObject* m_me;
};
PYSIDE_API QDataStream &operator<<(QDataStream& out, const PyObjectWrapper& myObj);
PYSIDE_API QDataStream &operator>>(QDataStream& in, PyObjectWrapper& myObj);
+PYSIDE_API QDebug operator<<(QDebug debug, const PyObjectWrapper &myObj);
class PYSIDE_API SignalManager
{
diff --git a/sources/pyside6/tests/QtCore/deepcopy_test.py b/sources/pyside6/tests/QtCore/deepcopy_test.py
index 8b211a979..64b001e6d 100644
--- a/sources/pyside6/tests/QtCore/deepcopy_test.py
+++ b/sources/pyside6/tests/QtCore/deepcopy_test.py
@@ -12,8 +12,8 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from init_paths import init_test_paths
init_test_paths(False)
-from PySide6.QtCore import QByteArray, QDate, QDateTime, QTime, QLine, QLineF
-from PySide6.QtCore import Qt, QSize, QSizeF, QRect, QRectF, QDir, QPoint, QPointF
+from PySide6.QtCore import QByteArray, QDate, QDateTime, QTime, QLine, QLineF, QTimeZone
+from PySide6.QtCore import QSize, QSizeF, QRect, QRectF, QDir, QPoint, QPointF
try:
from PySide6.QtCore import QUuid
HAVE_Q = True
@@ -45,7 +45,7 @@ class QTimeDeepCopy(DeepCopyHelper, unittest.TestCase):
class QDateTimeDeepCopy(DeepCopyHelper, unittest.TestCase):
def setUp(self):
- self.original = QDateTime(2010, 5, 18, 10, 24, 45, 223, Qt.TimeSpec.LocalTime)
+ self.original = QDateTime(2010, 5, 18, 10, 24, 45, 223, QTimeZone(QTimeZone.LocalTime))
class QSizeDeepCopy(DeepCopyHelper, unittest.TestCase):
diff --git a/sources/pyside6/tests/QtCore/qobject_property_test.py b/sources/pyside6/tests/QtCore/qobject_property_test.py
index 37936205e..80387ec77 100644
--- a/sources/pyside6/tests/QtCore/qobject_property_test.py
+++ b/sources/pyside6/tests/QtCore/qobject_property_test.py
@@ -32,6 +32,26 @@ class MyObjectWithNotifyProperty(QObject):
myProperty = Property(int, readP, fset=writeP, notify=notifyP)
+class OtherClass:
+ """Helper for QObjectWithOtherClassPropertyTest."""
+ pass
+
+
+class MyObjectWithOtherClassProperty(QObject):
+ """Helper for QObjectWithOtherClassPropertyTest."""
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._otherclass = None
+
+ def _get_otherclass(self):
+ return self._otherclass
+
+ def _set_otherclass(self, o):
+ self._otherclass = o
+
+ otherclass = Property(OtherClass, fget=_get_otherclass, fset=_set_otherclass)
+
+
class PropertyWithNotify(unittest.TestCase):
def called(self):
self.called_ = True
@@ -50,5 +70,19 @@ class PropertyWithNotify(unittest.TestCase):
self.assertEqual(o.property("myProperty"), 10)
+class QObjectWithOtherClassPropertyTest(unittest.TestCase):
+ """PYSIDE-2193: For properties of custom classes not wrapped by shiboken,
+ QVariant<PyObjectWrapper> is used, which had refcount issues causing crashes.
+ Exercise the QVariant conversion by setting and retrieving via the
+ QVariant-based property()/setProperty() API."""
+ def testNotify(self):
+ obj = MyObjectWithOtherClassProperty()
+ obj.setProperty("otherclass", OtherClass())
+ for i in range(10):
+ pv = obj.property("otherclass")
+ print(pv) # Exercise repr
+ self.assertTrue(type(pv) is OtherClass)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/pyside6/tests/QtCore/repr_test.py b/sources/pyside6/tests/QtCore/repr_test.py
index 084b69f87..52a426d31 100644
--- a/sources/pyside6/tests/QtCore/repr_test.py
+++ b/sources/pyside6/tests/QtCore/repr_test.py
@@ -13,8 +13,8 @@ init_test_paths(False)
# for 'self.original'
import PySide6 # noqa
-from PySide6.QtCore import QByteArray, QDate, QDateTime, QTime, QLine, QLineF
-from PySide6.QtCore import Qt, QSize, QSizeF, QRect, QRectF, QPoint, QPointF
+from PySide6.QtCore import QByteArray, QDate, QDateTime, QTime, QLine, QLineF, QTimeZone
+from PySide6.QtCore import QSize, QSizeF, QRect, QRectF, QPoint, QPointF
try:
from PySide6.QtCore import QUuid
HAVE_Q = True
@@ -46,7 +46,7 @@ class QTimeReprCopy(ReprCopyHelper, unittest.TestCase):
class QDateTimeReprCopy(ReprCopyHelper, unittest.TestCase):
def setUp(self):
- self.original = QDateTime(2010, 5, 18, 10, 24, 45, 223, Qt.TimeSpec.LocalTime)
+ self.original = QDateTime(2010, 5, 18, 10, 24, 45, 223, QTimeZone(QTimeZone.LocalTime))
class QSizeReprCopy(ReprCopyHelper, unittest.TestCase):
diff --git a/sources/pyside6/tests/QtWidgets/bug_433.py b/sources/pyside6/tests/QtWidgets/bug_433.py
index 5adcacccc..6d5c4333a 100644
--- a/sources/pyside6/tests/QtWidgets/bug_433.py
+++ b/sources/pyside6/tests/QtWidgets/bug_433.py
@@ -26,4 +26,4 @@ a = QApplication(sys.argv)
t = Test()
t.show()
QTimer.singleShot(0, t.close)
-sys.exit(a.exec_())
+sys.exit(a.exec())
diff --git a/sources/pyside6/tests/QtWidgets/bug_919.py b/sources/pyside6/tests/QtWidgets/bug_919.py
index 6f2fc128d..a95d3aa37 100644
--- a/sources/pyside6/tests/QtWidgets/bug_919.py
+++ b/sources/pyside6/tests/QtWidgets/bug_919.py
@@ -26,10 +26,11 @@ class MyWidget(QPushButton):
self.paintReceived.emit()
def paintEvent(self, e):
- p = QPainter(self)
- style = QApplication.style()
- option = QStyleOptionButton()
- style.drawControl(QStyle.ControlElement.CE_PushButton, option, p)
+ with QPainter(self) as p:
+ style = QApplication.style()
+ option = QStyleOptionButton()
+ self.initStyleOption(option)
+ style.drawControl(QStyle.ControlElement.CE_PushButton, option, p)
self._painted = True
QTimer.singleShot(0, self._emitPainted)
diff --git a/sources/pyside6/tests/QtWidgets/qapp_issue_585.py b/sources/pyside6/tests/QtWidgets/qapp_issue_585.py
index ec8a47569..1300ea4aa 100644
--- a/sources/pyside6/tests/QtWidgets/qapp_issue_585.py
+++ b/sources/pyside6/tests/QtWidgets/qapp_issue_585.py
@@ -40,15 +40,15 @@ import sys
from pathlib import Path
sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
-from init_paths import init_test_paths
+from init_paths import init_test_paths # noqa: E402
init_test_paths()
-from PySide6.QtCore import QTimer
-from PySide6.QtWidgets import QApplication
+from PySide6.QtCore import QTimer # noqa: E402
+from PySide6.QtWidgets import QApplication # noqa: E402
app_instance = QApplication([])
# If the following line is commented, application doesn't crash on exit anymore.
app_instance2 = app_instance
-QTimer.singleShot(0, qApp.quit)
-app_instance.exec_()
+QTimer.singleShot(0, qApp.quit) # noqa: F821
+app_instance.exec()
diff --git a/sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py b/sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py
index 91b405aaf..7ae29d1f7 100644
--- a/sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py
+++ b/sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py
@@ -53,8 +53,16 @@ class QGraphicsObjectReimpl(UsesQApplication):
# See also PYSIDE-1887, PYSIDE-3069
gobjA = GObjA()
gobjA.setParentItem(w)
+ print(gobjA.parentItem())
self.assertIs(type(w), type(gobjA.parentItem()))
+ # PYSIDE-3115: QVariant conversion of the parent
+ # (Python class inheriting QGraphicsObject).
+ parentA = GObjA()
+ gobjA = GObjA()
+ gobjA.setParentItem(parentA)
+ self.assertIs(type(parentA), type(gobjA.parentItem()))
+
gobjB = GObjB()
gobjB.setParentItem(w)
self.assertIs(type(w), type(gobjB.parentItem()))
diff --git a/sources/pyside6/tests/QtWidgets/qmenu_test.py b/sources/pyside6/tests/QtWidgets/qmenu_test.py
index 7d1d262e4..8bd5d1624 100644
--- a/sources/pyside6/tests/QtWidgets/qmenu_test.py
+++ b/sources/pyside6/tests/QtWidgets/qmenu_test.py
@@ -33,16 +33,16 @@ class QMenuAddAction(UsesQApplication):
def testAddActionWithoutKeySequenceCallable(self):
# bug #280
- action = self.menu.addAction(self.app.tr('aaa'), lambda: 1)
+ action = self.menu.addAction(self.app.tr('aaa'), lambda: 1) # noqa: F841
def testAddActionKeySequenceCallable(self):
# bug #228
- action = self.menu.addAction(self.app.tr('aaa'), lambda: 1,
+ action = self.menu.addAction(self.app.tr('aaa'), lambda: 1, # noqa: F841
QKeySequence(self.app.tr('Ctrl+O')))
def testAddActionKeySequenceSlot(self):
- action = self.menu.addAction('Quit', self.app, SLOT('quit()'),
- QKeySequence('Ctrl+O'))
+ action = self.menu.addAction('Quit', QKeySequence('Ctrl+O'), # noqa: F841
+ self.app, SLOT('quit()'))
class QMenuAddActionWithIcon(UsesQApplication):
@@ -61,16 +61,16 @@ class QMenuAddActionWithIcon(UsesQApplication):
def testAddActionWithoutKeySequenceCallable(self):
# bug #280
- action = self.menu.addAction(self.icon, self.app.tr('aaa'), lambda: 1)
+ action = self.menu.addAction(self.icon, self.app.tr('aaa'), lambda: 1) # noqa: F841
def testAddActionKeySequenceCallable(self):
# bug #228
- action = self.menu.addAction(self.icon, self.app.tr('aaa'), lambda: 1,
- QKeySequence(self.app.tr('Ctrl+O')))
+ action = self.menu.addAction(self.icon, self.app.tr('aaa'), lambda: 1, # noqa: F841
+ QKeySequence(self.app.tr('Ctrl+O'))) # noqa: F841
def testAddActionKeySequenceSlot(self):
- action = self.menu.addAction(self.icon, 'Quit', self.app, SLOT('quit()'),
- QKeySequence('Ctrl+O'))
+ action = self.menu.addAction(self.icon, 'Quit', QKeySequence('Ctrl+O'), # noqa: F841
+ self.app, SLOT('quit()')) # noqa: F841
if __name__ == '__main__':
diff --git a/sources/pyside6/tests/QtXml/qdomdocument_test.py b/sources/pyside6/tests/QtXml/qdomdocument_test.py
index 8fe4f6e17..b321b1bdf 100644
--- a/sources/pyside6/tests/QtXml/qdomdocument_test.py
+++ b/sources/pyside6/tests/QtXml/qdomdocument_test.py
@@ -44,18 +44,20 @@ class QDomDocumentTest(unittest.TestCase):
def testQDomDocumentSetContentWithBadXmlData(self):
'''Sets invalid xml as the QDomDocument contents.'''
- ok, errorStr, errorLine, errorColumn = self.dom.setContent(self.badXmlData, True)
- self.assertFalse(ok)
- self.assertEqual(errorStr, 'Opening and ending tag mismatch.')
- self.assertEqual(errorLine, 4)
+ parseResult = self.dom.setContent(self.badXmlData,
+ QDomDocument.ParseOption.UseNamespaceProcessing)
+ self.assertFalse(parseResult)
+ self.assertEqual(parseResult.errorMessage, 'Opening and ending tag mismatch.')
+ self.assertEqual(parseResult.errorLine, 4)
def testQDomDocumentSetContentWithGoodXmlData(self):
'''Sets valid xml as the QDomDocument contents.'''
- ok, errorStr, errorLine, errorColumn = self.dom.setContent(self.goodXmlData, True)
- self.assertTrue(ok)
- self.assertEqual(errorStr, '')
- self.assertEqual(errorLine, 0)
- self.assertEqual(errorColumn, 0)
+ parseResult = self.dom.setContent(self.goodXmlData,
+ QDomDocument.ParseOption.UseNamespaceProcessing)
+ self.assertTrue(parseResult)
+ self.assertEqual(parseResult.errorMessage, '')
+ self.assertEqual(parseResult.errorLine, 0)
+ self.assertEqual(parseResult.errorColumn, 0)
def testQDomDocumentData(self):
'''Checks the QDomDocument elements for the valid xml contents.'''
@@ -66,7 +68,8 @@ class QDomDocumentTest(unittest.TestCase):
self.assertTrue(element.hasAttribute(attribute))
self.assertEqual(element.attribute(attribute), value)
- ok, errorStr, errorLine, errorColumn = self.dom.setContent(self.goodXmlData, True)
+ parseResult = self.dom.setContent(self.goodXmlData, # noqa F:841
+ QDomDocument.ParseOption.UseNamespaceProcessing)
root = self.dom.documentElement()
self.assertEqual(root.tagName(), 'typesystem')
checkAttribute(root, 'package', 'PySide6.QtXml')
diff --git a/sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py b/sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py
index 120c54af3..14330726a 100644
--- a/sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py
+++ b/sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py
@@ -36,7 +36,7 @@ class DeployTestBase(unittest.TestCase):
android_requirements_file = pyside_tools / "requirements-android.txt"
with open(android_requirements_file, 'r', encoding='UTF-8') as file:
while line := file.readline():
- dependent_package = line.rstrip()
+ dependent_package = line.rstrip().split('==')[0]
if not bool(importlib.util.find_spec(dependent_package)):
command = [sys.executable, "-m", "pip", "install", dependent_package]
subprocess.run(command)