aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2023-02-14 14:46:22 +0100
committerChristian Tismer <tismer@stackless.com>2023-10-09 08:54:27 +0200
commit441ffbd4fc622e67acd81e9c1c6d3a0b0fbcacf0 (patch)
tree83226e3bccf205f6a941c53ce3698c88f99b7935 /sources/pyside6
parent92a4a2a0ed7a8a391406030d1db813de7dd31429 (diff)
Support running PySide on Python 3.12
Builtin types no longer have tp_dict set. We need to use PyType_GetDict, instead. This works without Limited API at the moment. With some great cheating, this works with Limited API, too. We emulate PyType_GetDict by tp_dict if that is not 0. Otherwise we create an empty dict. Some small changes to Exception handling and longer warm-up in leaking tests were found, too. Pick-to: 6.6 6.5 6.2 Task-number: PYSIDE-2230 Change-Id: I8a56de6208ec00979255b39b5784dfc9b4b92def Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'sources/pyside6')
-rw-r--r--sources/pyside6/libpyside/feature_select.cpp10
-rw-r--r--sources/pyside6/libpyside/pysideproperty.cpp4
-rw-r--r--sources/pyside6/libpyside/pysidesignal.cpp7
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_662.py3
-rw-r--r--sources/pyside6/tests/pysidetest/enum_test.py19
-rw-r--r--sources/pyside6/tests/signals/bug_79.py5
6 files changed, 37 insertions, 11 deletions
diff --git a/sources/pyside6/libpyside/feature_select.cpp b/sources/pyside6/libpyside/feature_select.cpp
index 9b778f4e5..ec15e6d0a 100644
--- a/sources/pyside6/libpyside/feature_select.cpp
+++ b/sources/pyside6/libpyside/feature_select.cpp
@@ -266,7 +266,8 @@ static inline void SelectFeatureSetSubtype(PyTypeObject *type, int select_id)
* This is the selector for one sublass. We need to call this for
* every subclass until no more subclasses or reaching the wanted id.
*/
- if (Py_TYPE(type->tp_dict) == Py_TYPE(PyType_Type.tp_dict)) {
+ static const auto *pyTypeType_tp_dict = PepType_GetDict(&PyType_Type);
+ if (Py_TYPE(type->tp_dict) == Py_TYPE(pyTypeType_tp_dict)) {
// On first touch, we initialize the dynamic naming.
// The dict type will be replaced after the first call.
if (!replaceClassDict(type)) {
@@ -320,7 +321,8 @@ static inline void SelectFeatureSet(PyTypeObject *type)
* Generated functions call this directly.
* Shiboken will assign it via a public hook of `basewrapper.cpp`.
*/
- if (Py_TYPE(type->tp_dict) == Py_TYPE(PyType_Type.tp_dict)) {
+ static const auto *pyTypeType_tp_dict = PepType_GetDict(&PyType_Type);
+ if (Py_TYPE(type->tp_dict) == Py_TYPE(pyTypeType_tp_dict)) {
// We initialize the dynamic features by using our own dict type.
if (!replaceClassDict(type)) {
Py_FatalError("failed to replace class dict!");
@@ -744,11 +746,11 @@ static bool patch_property_impl()
// Turn `__doc__` into a computed attribute without changing writability.
auto gsp = property_getset;
auto *type = &PyProperty_Type;
- auto *dict = type->tp_dict;
+ AutoDecRef dict(PepType_GetDict(type));
AutoDecRef descr(PyDescr_NewGetSet(type, gsp));
if (descr.isNull())
return false;
- if (PyDict_SetItemString(dict, gsp->name, descr) < 0)
+ if (PyDict_SetItemString(dict.object(), gsp->name, descr) < 0)
return false;
return true;
}
diff --git a/sources/pyside6/libpyside/pysideproperty.cpp b/sources/pyside6/libpyside/pysideproperty.cpp
index 2658b5f03..d68185667 100644
--- a/sources/pyside6/libpyside/pysideproperty.cpp
+++ b/sources/pyside6/libpyside/pysideproperty.cpp
@@ -443,8 +443,8 @@ static int qpropertyClear(PyObject *self)
static PyObject *getFromType(PyTypeObject *type, PyObject *name)
{
- PyObject *attr = nullptr;
- attr = PyDict_GetItem(type->tp_dict, name);
+ AutoDecRef tpDict(PepType_GetDict(type));
+ auto *attr = PyDict_GetItem(tpDict.object(), name);
if (!attr) {
PyObject *bases = type->tp_bases;
const Py_ssize_t size = PyTuple_GET_SIZE(bases);
diff --git a/sources/pyside6/libpyside/pysidesignal.cpp b/sources/pyside6/libpyside/pysidesignal.cpp
index 7fb07fc38..64eb62b76 100644
--- a/sources/pyside6/libpyside/pysidesignal.cpp
+++ b/sources/pyside6/libpyside/pysidesignal.cpp
@@ -784,7 +784,8 @@ static PyObject *_getHomonymousMethod(PySideSignalInstance *inst)
for (Py_ssize_t idx = 0; idx < n; idx++) {
auto *sub_type = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, idx));
- auto *hom = PyDict_GetItem(sub_type->tp_dict, name);
+ AutoDecRef tpDict(PepType_GetDict(sub_type));
+ auto *hom = PyDict_GetItem(tpDict, name);
PyObject *realFunc{};
if (hom && PyCallable_Check(hom) && (realFunc = _getRealCallable(hom)))
return realFunc;
@@ -891,8 +892,8 @@ void updateSourceObject(PyObject *source)
Py_ssize_t pos = 0;
PyObject *key, *value;
auto *type = reinterpret_cast<PyTypeObject *>(mroItem.object());
-
- while (PyDict_Next(type->tp_dict, &pos, &key, &value)) {
+ AutoDecRef tpDict(PepType_GetDict(type));
+ while (PyDict_Next(tpDict, &pos, &key, &value)) {
if (PyObject_TypeCheck(value, PySideSignal_TypeF())) {
// PYSIDE-1751: We only insert an instance into the instance dict, if a signal
// of the same name is in the mro. This is the equivalent action
diff --git a/sources/pyside6/tests/QtWidgets/bug_662.py b/sources/pyside6/tests/QtWidgets/bug_662.py
index 9b6f1ed39..e3a3130d0 100644
--- a/sources/pyside6/tests/QtWidgets/bug_662.py
+++ b/sources/pyside6/tests/QtWidgets/bug_662.py
@@ -17,7 +17,8 @@ import sys
class testQTextBlock(unittest.TestCase):
- def tesIterator(self):
+
+ def testIterator(self):
edit = QTextEdit()
cursor = edit.textCursor()
fmt = QTextCharFormat()
diff --git a/sources/pyside6/tests/pysidetest/enum_test.py b/sources/pyside6/tests/pysidetest/enum_test.py
index 0036eb764..189ef60c1 100644
--- a/sources/pyside6/tests/pysidetest/enum_test.py
+++ b/sources/pyside6/tests/pysidetest/enum_test.py
@@ -71,6 +71,7 @@ class InvestigateOpcodesTest(unittest.TestCase):
_sin = sys.implementation.name
@unittest.skipIf(hasattr(sys.flags, "nogil"), f"{_sin} has different opcodes")
def testByteCode(self):
+ import dis
# opname, opcode, arg
result_1 = [('LOAD_GLOBAL', 116, 0),
('LOAD_ATTR', 106, 1),
@@ -94,7 +95,7 @@ class InvestigateOpcodesTest(unittest.TestCase):
('LOAD_CONST', 100, 0),
('RETURN_VALUE', 83, None)]
- if sys.version_info[:2] >= (3, 11):
+ if sys.version_info[:2] == (3, 11):
# Note: Python 3.11 is a bit more complex because it can optimize itself.
# Opcodes are a bit different, and a hidden second code object is used.
# We investigate this a bit, because we want to be warned when things change.
@@ -158,6 +159,22 @@ class InvestigateOpcodesTest(unittest.TestCase):
self.assertEqual(self.read_code(self.probe_function2, adaptive=True), result_3)
self.assertEqual(self.get_sizes(self.probe_function2, adaptive=True), sizes_3)
+ if sys.version_info[:2] >= (3, 12):
+
+ result_1 = [('RESUME', 151, 0),
+ ('LOAD_GLOBAL', 116, 0),
+ ('LOAD_ATTR', 106, 2),
+ ('STORE_FAST', 125, 1),
+ ('RETURN_CONST', 121, 0)]
+
+ result_2 = [('RESUME', 151, 0),
+ ('LOAD_GLOBAL', 116, 1),
+ ('LOAD_ATTR', 106, 2),
+ ('CALL', 171, 0),
+ ('STORE_FAST', 125, 1),
+ ('RETURN_CONST', 121, 0)]
+
+
self.assertEqual(self.read_code(self.probe_function1), result_1)
self.assertEqual(self.read_code(self.probe_function2), result_2)
diff --git a/sources/pyside6/tests/signals/bug_79.py b/sources/pyside6/tests/signals/bug_79.py
index 54bd1f076..0e12301f2 100644
--- a/sources/pyside6/tests/signals/bug_79.py
+++ b/sources/pyside6/tests/signals/bug_79.py
@@ -38,6 +38,11 @@ class ConnectTest(unittest.TestCase):
gc.collect()
# if this is no debug build, then we check at least that
# we do not crash any longer.
+ for idx in range(200):
+ # PYSIDE-2230: Warm-up is necessary before measuring, because
+ # the code changes the constant parts after some time.
+ o.selectionModel().destroyed.connect(self.callback)
+ o.selectionModel().destroyed.disconnect(self.callback)
if not skiptest:
total = gettotalrefcount()
for idx in range(1000):