diff options
-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 |