aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2023-10-26 23:32:10 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-11-14 16:23:33 +0000
commita2819f087892a1b82677ba1dc22dedee2d537efc (patch)
tree54f0055153f920ea1c991929fae8c8886c619f27
parent2b560b5a096993898da22a09ef143c9e24dbcb4c (diff)
Shiboken: Fix subtle bug caused by PyPy support and "bug_825"
When implementing PyPy support, all Shiboken types lost their hidden extra fields, because they were replaced by shadow dicts. This creates a problem with multiple inheritance. In Python < 3.12, the decision which base type will create the instance is driven simply by the size of the type. In class MetaC(MetaA, MetaB): pass when MetaA is derived from type and MetaB is derived from SbkObjectType, MetaA is not the type that should win. Fixed by simply adding 1 to the default size of PyType_Type. Caused by bug_825 corrected version. The old test is retained as bug_825_old.py . NOTE: This touches a Python 3.8 bug that was fixed in 3.9.12 and 3.10.4 - unfortunately CI Python is older in all cases. Task-number: PYSIDE-2230 Change-Id: I6e82cafb83c8351bbbeafcc80e11d5e45568f73d Pick-to: 6.5 6.2 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> (cherry picked from commit 9557565b48b2a72b7697443930234f9f92c17781) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--build_history/blacklist.txt5
-rw-r--r--sources/pyside6/tests/QtQml/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtQml/bug_825.py14
-rw-r--r--sources/pyside6/tests/QtQml/bug_825_old.py80
-rw-r--r--sources/shiboken6/libshiboken/basewrapper.cpp13
5 files changed, 104 insertions, 9 deletions
diff --git a/build_history/blacklist.txt b/build_history/blacklist.txt
index cb9b1c500..60cc3f955 100644
--- a/build_history/blacklist.txt
+++ b/build_history/blacklist.txt
@@ -43,7 +43,10 @@
darwin ci
[QtAsyncio::qasyncio_test_chain]
win32
-
+[QtQml::bug_825]
+ py3.8 # bug in typeobject::type_mro_modified, fix in 3.9
+ py3.9 # fixed in 3.9.12
+ py3.10 # fixed in 3.10.4
# PYSIDE-535: These errors are still present. Please try to remove one :)
[sample::mixed_mi]
pypy
diff --git a/sources/pyside6/tests/QtQml/CMakeLists.txt b/sources/pyside6/tests/QtQml/CMakeLists.txt
index c24beb35a..720f0ef99 100644
--- a/sources/pyside6/tests/QtQml/CMakeLists.txt
+++ b/sources/pyside6/tests/QtQml/CMakeLists.txt
@@ -6,6 +6,7 @@ PYSIDE_TEST(bug_456.py)
PYSIDE_TEST(bug_557.py)
PYSIDE_TEST(bug_726.py)
PYSIDE_TEST(bug_814.py)
+PYSIDE_TEST(bug_825_old.py)
PYSIDE_TEST(bug_825.py)
PYSIDE_TEST(bug_847.py)
PYSIDE_TEST(bug_915.py)
diff --git a/sources/pyside6/tests/QtQml/bug_825.py b/sources/pyside6/tests/QtQml/bug_825.py
index 9771d0634..1d9b82d16 100644
--- a/sources/pyside6/tests/QtQml/bug_825.py
+++ b/sources/pyside6/tests/QtQml/bug_825.py
@@ -1,6 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+"""
+This is the corrected version for Python 3.
+Unfortunately, this touches a Python 3.8 error that was fixed late.
+"""
+
import os
import sys
import unittest
@@ -25,9 +30,8 @@ class MetaA(type):
pass
-class A(object):
- __metaclass__ = MetaA
-
+class A(object, metaclass=MetaA):
+ pass
MetaB = type(QQuickPaintedItem)
B = QQuickPaintedItem
@@ -37,8 +41,8 @@ class MetaC(MetaA, MetaB):
pass
-class C(A, B):
- __metaclass__ = MetaC
+class C(A, B, metaclass=MetaC):
+ pass
class Bug825 (C):
diff --git a/sources/pyside6/tests/QtQml/bug_825_old.py b/sources/pyside6/tests/QtQml/bug_825_old.py
new file mode 100644
index 000000000..c44fa75f4
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_825_old.py
@@ -0,0 +1,80 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+"""
+This is the now incorrect old version from Python 2.
+It happens to work in another way and will be retained.
+"""
+
+import os
+import sys
+import unittest
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+from init_paths import init_test_paths
+init_test_paths(False)
+
+from helper.helper import quickview_errorstring
+
+from PySide6.QtCore import Qt, QUrl, QTimer
+from PySide6.QtGui import QGuiApplication, QPen
+from PySide6.QtWidgets import QGraphicsItem
+from PySide6.QtQml import qmlRegisterType
+from PySide6.QtQuick import QQuickView, QQuickItem, QQuickPaintedItem
+
+paintCalled = False
+
+
+class MetaA(type):
+ pass
+
+
+class A(object):
+ __metaclass__ = MetaA
+
+
+MetaB = type(QQuickPaintedItem)
+B = QQuickPaintedItem
+
+
+class MetaC(MetaA, MetaB):
+ pass
+
+
+class C(A, B):
+ __metaclass__ = MetaC
+
+
+class Bug825 (C):
+ def __init__(self, parent=None):
+ QQuickPaintedItem.__init__(self, parent)
+
+ def paint(self, painter):
+ global paintCalled
+ pen = QPen(Qt.black, 2)
+ painter.setPen(pen)
+ painter.drawPie(self.boundingRect(), 0, 128)
+ paintCalled = True
+
+
+class TestBug825 (unittest.TestCase):
+ def testIt(self):
+ global paintCalled
+ app = QGuiApplication([])
+ qmlRegisterType(Bug825, 'bugs', 1, 0, 'Bug825')
+ self.assertRaises(TypeError, qmlRegisterType, A, 'bugs', 1, 0, 'A')
+
+ view = QQuickView()
+ file = Path(__file__).resolve().parent / 'bug_825.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+ view.show()
+ QTimer.singleShot(250, view.close)
+ app.exec()
+ self.assertTrue(paintCalled)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/shiboken6/libshiboken/basewrapper.cpp b/sources/shiboken6/libshiboken/basewrapper.cpp
index d33f06431..828c54a89 100644
--- a/sources/shiboken6/libshiboken/basewrapper.cpp
+++ b/sources/shiboken6/libshiboken/basewrapper.cpp
@@ -139,11 +139,18 @@ static PyTypeObject *createObjectTypeType()
};
// PYSIDE-535: The tp_itemsize field is inherited and does not need to be set.
- // In PyPy, it _must_ not be set, because it would have the meaning that a
- // `__len__` field must be defined. Not doing so creates a hard-to-find crash.
+ // In PyPy, it _must_ not be set, because it would have the meanin
+ // that a `__len__` field must be defined. Not doing so creates
+ // a hard-to-find crash.
+ //
+ // PYSIDE-2230: In Python < 3.12, the decision which base class should create
+ // the instance is arbitrarily drawn by the size of the type.
+ // Ignoring this creates a bug in the new version of bug_825 that
+ // selects the wrong metatype.
+ //
PyType_Spec SbkObjectType_Type_spec = {
"1:Shiboken.ObjectType",
- 0,
+ static_cast<int>(PyType_Type.tp_basicsize) + 1, // see above
0, // sizeof(PyMemberDef), not for PyPy without a __len__ defined
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
SbkObjectType_Type_slots,