diff options
author | Christian Tismer <tismer@stackless.com> | 2023-10-18 15:45:05 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-10-25 03:56:51 +0000 |
commit | ba73b2f7958b317254a570dda31c364fac35e4b1 (patch) | |
tree | a32f6983b22b5a213cab0da03f9f9cc2b0738e02 | |
parent | 5f5d7e0fc6aff4a3911686783e22125803cb33dc (diff) |
Support running PySide on Python 3.12, extension bug
When SbkTypeFactory._PyType_FromSpecWithBasesHack was
written, the intent was to support everything for
Python 3.12, although the new function PyType_FromMetaclass
cannot be used with the Limited API.
The supplied patch did not fix a problem that arises when
a type is created without a base class that has the preferred
metaclass. In PySide, this happens exactly in the case of
SbkObject_type creation.
The subtle bug was that metaclass SbkObjectType_Type was
reported, but it really was still the old &PyType_Type.
The patch fixes that by temporarily changing the type of object.
Python 3.12 is the first version that requires that.
Change-Id: I4d9d05ed93aa0e1fb297a0b931821ab9cae28ee9
Pick-to: 6.2
Task-number: PYSIDE-2230
Reviewed-by: Adrian Herrmann <adrian.herrmann@qt.io>
(cherry picked from commit 897eaa60525099f2c3667148955732db7fed7271)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit e07ef1ded30f545cc100df17825bd88ff8f0d90f)
-rw-r--r-- | sources/shiboken6/libshiboken/basewrapper.cpp | 8 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/sbktypefactory.cpp | 28 | ||||
-rw-r--r-- | sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py | 2 |
3 files changed, 32 insertions, 6 deletions
diff --git a/sources/shiboken6/libshiboken/basewrapper.cpp b/sources/shiboken6/libshiboken/basewrapper.cpp index 65a51454c..44b990064 100644 --- a/sources/shiboken6/libshiboken/basewrapper.cpp +++ b/sources/shiboken6/libshiboken/basewrapper.cpp @@ -233,8 +233,14 @@ static const char *SbkObject_SignatureStrings[] = { PyTypeObject *SbkObject_TypeF(void) { + // PYSIDE-2230: When creating this type, we cannot easily handle the metaclass. + // In versions < Python 3.12, the metaclass can only be set + // indirectly by a base which has that metaclass. + // But before 3.12 is the minimum version, we cannot use the new + // function, although we would need this for 3.12 :-D + // We do a special patching here that is triggered through Py_None. static auto *type = SbkType_FromSpec_BMDWB(&SbkObject_Type_spec, - nullptr, // bases + Py_None, // bases, special flag! SbkObjectType_TypeF(), offsetof(SbkObject, ob_dict), offsetof(SbkObject, weakreflist), diff --git a/sources/shiboken6/libshiboken/sbktypefactory.cpp b/sources/shiboken6/libshiboken/sbktypefactory.cpp index 88878f5eb..ab7ce5900 100644 --- a/sources/shiboken6/libshiboken/sbktypefactory.cpp +++ b/sources/shiboken6/libshiboken/sbktypefactory.cpp @@ -7,6 +7,8 @@ extern "C" { +using Shiboken::AutoDecRef; + PyTypeObject *SbkType_FromSpec(PyType_Spec *spec) { return SbkType_FromSpec_BMDWB(spec, nullptr, nullptr, 0, 0, nullptr); @@ -41,12 +43,25 @@ static PyObject *_PyType_FromSpecWithBases(PyType_Spec *, PyObject *); // 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) +static PyObject *_PyType_FromSpecWithBasesHack(PyType_Spec *spec, + PyObject *bases, + PyTypeObject *meta) { PyTypeObject *keepMeta{}; newfunc keepNew{}; + AutoDecRef basesPatch{}; if (bases) { + if (bases == Py_None) { + // PYSIDE-2230: This is the SbkObject entry which has no base to provide + // the metaclass. We patch it in by modifying `object`s class. + assert(meta); + auto *base = reinterpret_cast<PyObject *>(&PyBaseObject_Type); + base->ob_type = meta; + basesPatch.reset(Py_BuildValue("(O)", &PyBaseObject_Type)); + bases = basesPatch.object(); + } + 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)); @@ -65,6 +80,11 @@ static PyObject *_PyType_FromSpecWithBasesHack(PyType_Spec *spec, PyObject *base if (keepMeta) keepMeta->tp_new = keepNew; + if (basesPatch.object()) { + // undo the metaclass patch. + auto *base = PyTuple_GET_ITEM(basesPatch.object(), 0); + base->ob_type = &PyType_Type; + } return ret; } @@ -92,7 +112,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_FromSpecWithBasesHack(&new_spec, bases); + PyObject *obType = _PyType_FromSpecWithBasesHack(&new_spec, bases, meta); if (obType == nullptr) return nullptr; @@ -104,8 +124,8 @@ PyTypeObject *SbkType_FromSpec_BMDWB(PyType_Spec *spec, qual = dot + 1; } int mlen = qual - mod - 1; - Shiboken::AutoDecRef module(Shiboken::String::fromCString(mod, mlen)); - Shiboken::AutoDecRef qualname(Shiboken::String::fromCString(qual)); + AutoDecRef module(Shiboken::String::fromCString(mod, mlen)); + AutoDecRef qualname(Shiboken::String::fromCString(qual)); auto *type = reinterpret_cast<PyTypeObject *>(obType); diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py index 6f925141a..d403c7582 100644 --- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py +++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py @@ -15,7 +15,7 @@ The normal usage is like Alternatively, there is the `set_selection` function which uses select_id's and takes an optional `mod_name` parameter. -The select id `-1` has the spectial meaning "ignore this module". +The select id `-1` has the special meaning "ignore this module". """ import inspect |