diff options
| author | Christian Tismer <tismer@stackless.com> | 2023-02-14 14:46:22 +0100 |
|---|---|---|
| committer | Christian Tismer <tismer@stackless.com> | 2023-10-09 08:54:27 +0200 |
| commit | 441ffbd4fc622e67acd81e9c1c6d3a0b0fbcacf0 (patch) | |
| tree | 83226e3bccf205f6a941c53ce3698c88f99b7935 /sources/pyside6 | |
| parent | 92a4a2a0ed7a8a391406030d1db813de7dd31429 (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.cpp | 10 | ||||
| -rw-r--r-- | sources/pyside6/libpyside/pysideproperty.cpp | 4 | ||||
| -rw-r--r-- | sources/pyside6/libpyside/pysidesignal.cpp | 7 | ||||
| -rw-r--r-- | sources/pyside6/tests/QtWidgets/bug_662.py | 3 | ||||
| -rw-r--r-- | sources/pyside6/tests/pysidetest/enum_test.py | 19 | ||||
| -rw-r--r-- | sources/pyside6/tests/signals/bug_79.py | 5 |
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): |
