diff options
author | Christian Tismer <tismer@stackless.com> | 2023-10-26 23:32:10 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-11-20 21:39:10 +0000 |
commit | 366925c6bc08b130954ccfa1123a883253fe49fc (patch) | |
tree | 68380e3819ce431cdac40f21bbdfccbc0a680854 | |
parent | d650a09764defb1cf206827485e0be24b34c6075 (diff) |
Shiboken: Fix an oversight when removing ob_type
SbkObjectType's meta type was changed due to a wrong fix.
This has strange side effects when applying PEP 697
because a wrong action is taken.
The meta class for class property was also rewritten
to have its own meta class for PEP 697 compatibility.
Amends: 73adefe22ffbfabe0ef213e9c2fe2c56efdd7488
Change-Id: I2d5c0a58e274c0a60496e29cbd714b9e69bfffbd
Pick-to: 6.5 6.2
Task-number: PYSIDE-2230
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
(cherry picked from commit 5935b0f45503eabbd24c7379701b48bb2874a8ac)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | sources/pyside6/libpyside/class_property.cpp | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/sources/pyside6/libpyside/class_property.cpp b/sources/pyside6/libpyside/class_property.cpp index 140956035..99104445c 100644 --- a/sources/pyside6/libpyside/class_property.cpp +++ b/sources/pyside6/libpyside/class_property.cpp @@ -33,6 +33,46 @@ static int PyClassProperty_descr_set(PyObject *self, PyObject *obj, PyObject *va return PyProperty_Type.tp_descr_set(self, cls, value); } +// PYSIDE-2230: Why is this metaclass necessary? +// +// The problem is that the property object already exists as a Python +// object. We derive a subclass for class properties, without +// repeating everything but just by adding something to support +// the class-ness. +// +// But this Python property has as metaclass `type` which is incompatible +// now with SbkObjectType, which generates physically larger types that +// are incompatible with properties by using PEP 697. +// Adding a compatible metaclass that is unrelated to `SbkObjectType` +// is the correct solution. Re-using `SbkObjectType` was actually an abuse, +// since Python properties are in no way PySide objects. + +static PyTypeObject *createClassPropertyTypeType() +{ + PyType_Slot PyClassPropertyType_Type_slots[] = { + {Py_tp_base, static_cast<void *>(&PyType_Type)}, + {Py_tp_alloc, reinterpret_cast<void *>(PyType_GenericAlloc)}, + {Py_tp_free, reinterpret_cast<void *>(PyObject_GC_Del)}, + {0, nullptr} + }; + + PyType_Spec PyClassPropertyType_Type_spec = { + "1:Shiboken.ClassPropertyType", + 0, + 0, // sizeof(PyMemberDef), not for PyPy without a __len__ defined + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_TYPE_SUBCLASS, + PyClassPropertyType_Type_slots, + }; + + return SbkType_FromSpec(&PyClassPropertyType_Type_spec); +} + +PyTypeObject *PyClassPropertyType_TypeF() +{ + static auto *type = createClassPropertyTypeType(); + return type; +} + // The property `__doc__` default does not work for class properties // because PyProperty_Type.tp_init thinks this is a subclass which needs PyObject_SetAttr. // We call `__init__` while pretending to be a PyProperty_Type instance. @@ -48,7 +88,7 @@ static int PyClassProperty_tp_init(PyObject *self, PyObject *args, PyObject *kwa static PyTypeObject *createPyClassPropertyType() { PyType_Slot PyClassProperty_slots[] = { - {Py_tp_getset, nullptr}, // will be set below + {Py_tp_getset, reinterpret_cast<void *>(PyProperty_Type.tp_getset)}, // will be set below {Py_tp_base, reinterpret_cast<void *>(&PyProperty_Type)}, {Py_tp_descr_get, reinterpret_cast<void *>(PyClassProperty_descr_get)}, {Py_tp_descr_set, reinterpret_cast<void *>(PyClassProperty_descr_set)}, @@ -64,10 +104,9 @@ static PyTypeObject *createPyClassPropertyType() PyClassProperty_slots, }; - PyClassProperty_slots[0].pfunc = PyProperty_Type.tp_getset; if (_PepRuntimeVersion() >= 0x030A00) PyClassProperty_spec.basicsize = sizeof(propertyobject310); - return SbkType_FromSpec(&PyClassProperty_spec); + return SbkType_FromSpecWithMeta(&PyClassProperty_spec, PyClassPropertyType_TypeF()); } PyTypeObject *PyClassProperty_TypeF() @@ -126,7 +165,6 @@ void init(PyObject *module) { PyTypeObject *type = SbkObjectType_TypeF(); type->tp_setattro = SbkObjectType_meta_setattro; - reinterpret_cast<PyObject *>(type)->ob_type = type; if (InitSignatureStrings(PyClassProperty_TypeF(), PyClassProperty_SignatureStrings) < 0) return; |