diff options
author | Christian Tismer <tismer@stackless.com> | 2023-02-14 14:46:22 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-02-23 11:00:16 +0000 |
commit | d750c0d7a97e4d59129e8d1e44b88a21811c8b28 (patch) | |
tree | 05ad3e60bcf4afc9a043e9d40497ac805a45718b | |
parent | b04be8aa620b20a2867a5d85150f4255a72d4bf0 (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.cpp | 33 |
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; |