aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2023-02-14 14:46:22 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-02-23 11:00:16 +0000
commitd750c0d7a97e4d59129e8d1e44b88a21811c8b28 (patch)
tree05ad3e60bcf4afc9a043e9d40497ac805a45718b
parentb04be8aa620b20a2867a5d85150f4255a72d4bf0 (diff)
Python 3.12: Fix the type generation intermediately
The type generation that we use all over the place does not work any longer because Python 3.12.0a5 no longer allows meta classes with a tp_new function. The developers are aware of the omission and agree that a fix must be found. After prior experience, this can take very long time. To immediately continue, we implement a temporary patch that works. Task-number: PYSIDE-2230 Change-Id: I8bf237411ca0e32e31ef4d3741a2def05f3e39f6 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> (cherry picked from commit ff40e74847cae1e746fc857597209294ca2c2568) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--sources/shiboken6/libshiboken/sbktypefactory.cpp33
1 files changed, 32 insertions, 1 deletions
diff --git a/sources/shiboken6/libshiboken/sbktypefactory.cpp b/sources/shiboken6/libshiboken/sbktypefactory.cpp
index 0da1a8e23..88878f5eb 100644
--- a/sources/shiboken6/libshiboken/sbktypefactory.cpp
+++ b/sources/shiboken6/libshiboken/sbktypefactory.cpp
@@ -37,6 +37,37 @@ static PyObject *_PyType_FromSpecWithBases(PyType_Spec *, PyObject *);
#endif // PYPY_VERSION
+// PYSIDE-2230: Temporary fix for Python 3.12.
+// A tp_new is no longer allowed in a meta class.
+// Hopefully, the Python devs will supply the missing support.
+// Note: Python 3.12 is the first version that grabs the metaclass from base classes.
+static PyObject *_PyType_FromSpecWithBasesHack(PyType_Spec *spec, PyObject *bases)
+{
+ PyTypeObject *keepMeta{};
+ newfunc keepNew{};
+
+ if (bases) {
+ Py_ssize_t n = PyTuple_GET_SIZE(bases);
+ for (auto idx = 0; idx < n; ++idx) {
+ PyTypeObject *base = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(bases, idx));
+ PyTypeObject *meta = Py_TYPE(base);
+ if (meta->tp_new != PyType_Type.tp_new) {
+ // make sure there is no second meta class
+ assert(keepMeta == nullptr);
+ keepMeta = meta;
+ keepNew = meta->tp_new;
+ meta->tp_new = PyType_Type.tp_new;
+ }
+ }
+ }
+
+ auto *ret = _PyType_FromSpecWithBases(spec, bases);
+
+ if (keepMeta)
+ keepMeta->tp_new = keepNew;
+ return ret;
+}
+
PyTypeObject *SbkType_FromSpec_BMDWB(PyType_Spec *spec,
PyObject *bases,
PyTypeObject *meta,
@@ -61,7 +92,7 @@ PyTypeObject *SbkType_FromSpec_BMDWB(PyType_Spec *spec,
int package_level = atoi(spec->name);
const char *mod = new_spec.name = colon + 1;
- PyObject *obType = _PyType_FromSpecWithBases(&new_spec, bases);
+ PyObject *obType = _PyType_FromSpecWithBasesHack(&new_spec, bases);
if (obType == nullptr)
return nullptr;