diff options
author | Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io> | 2018-04-25 17:49:25 +0200 |
---|---|---|
committer | Christian Tismer <tismer@stackless.com> | 2018-06-21 14:42:51 +0000 |
commit | aa75437f9119d997dd290471ac3e2cc88ca88bf1 (patch) | |
tree | 25bd1488cde8b60c14190d40dd03725f11f8d537 /sources/pyside2/PySide2 | |
parent | 27a3402507364e15c37fcabfa025c2fed36146f0 (diff) |
Fix QVariant conversions when using PySequences
Currently we transform QVariant arguments to internal
types, starting from the Python ones, to others
related to shiboken.
After checking if the current object is a PyDict
we proceed to check if it's a PySequence.
PySequence is the complementary 'sequence-like' type of PyDict,
and allows finite and infinite sequences,
like lists or generators.
The problem is that when one implements a class
which includes the __getitem__ method, Python already
thinks that it correspond to a PySequence, then
we try to get the elements to transform into
a QList<QVariant> but it fails at the first attempt.
The solution was to not assume that all PySequences
have finite length (or a length), and also to have
a fallback case similarly to the PyDict treatment,
wrapping the PyObject as a QVariant.
Task-number: PYSIDE-641
Change-Id: I3b755f47ed076147024de38e5e0a86932d981f88
Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'sources/pyside2/PySide2')
-rw-r--r-- | sources/pyside2/PySide2/QtCore/typesystem_core_common.xml | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml index 47d43f2eb..488ee068b 100644 --- a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml +++ b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml @@ -430,7 +430,8 @@ %out = ret.isValid() ? ret : QVariant::fromValue<PySide::PyObjectWrapper>(%in); </add-conversion> <add-conversion type="PySequence"> - %out = QVariant_convertToVariantList(%in); + QVariant ret = QVariant_convertToVariantList(%in); + %out = ret.isValid() ? ret : QVariant::fromValue<PySide::PyObjectWrapper>(%in); </add-conversion> <add-conversion type="PyObject"> // Is a shiboken type not known by Qt @@ -480,8 +481,12 @@ } static QVariant QVariant_convertToValueList(PyObject *list) { - if (PySequence_Size(list) < 1) - return QVariant(); + if (PySequence_Size(list) < 0) { + // clear the error if < 0 which means no length at all + PyErr_Clear(); + return QVariant(); + } + Shiboken::AutoDecRef element(PySequence_GetItem(list, 0)); int typeId; const char *typeName = QVariant_resolveMetaType(element.cast<PyTypeObject*>(), &typeId); @@ -505,14 +510,26 @@ static bool QVariant_isStringList(PyObject *list) { bool allString = true; - Shiboken::AutoDecRef fast(PySequence_Fast(list, "Failed to convert QVariantList")); - Py_ssize_t size = PySequence_Fast_GET_SIZE(fast.object()); - for (int i = 0; i < size; ++i) { - PyObject *item = PySequence_Fast_GET_ITEM(fast.object(), i); - if (!%CHECKTYPE[QString](item)) { - allString = false; - break; + + if (PySequence_Check(list)) { + 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")); + Py_ssize_t size = PySequence_Fast_GET_SIZE(fast.object()); + for (int i = 0; i < size; ++i) { + PyObject *item = PySequence_Fast_GET_ITEM(fast.object(), i); + if (!%CHECKTYPE[QString](item)) { + allString = false; + break; + } + } + } else { + // If it is not a list or a derived list class + // we assume that will not be a String list neither. + allString = false; } return allString; } @@ -541,6 +558,13 @@ 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 QVariant(); + } + QList<QVariant> lst; Shiboken::AutoDecRef fast(PySequence_Fast(list, "Failed to convert QVariantList")); Py_ssize_t size = PySequence_Fast_GET_SIZE(fast.object()); |