aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2023-10-18 15:45:05 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-10-25 03:56:51 +0000
commitba73b2f7958b317254a570dda31c364fac35e4b1 (patch)
treea32f6983b22b5a213cab0da03f9f9cc2b0738e02
parent5f5d7e0fc6aff4a3911686783e22125803cb33dc (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.cpp8
-rw-r--r--sources/shiboken6/libshiboken/sbktypefactory.cpp28
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py2
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