aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/libpyside/class_property.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6/libpyside/class_property.cpp')
-rw-r--r--sources/pyside6/libpyside/class_property.cpp107
1 files changed, 73 insertions, 34 deletions
diff --git a/sources/pyside6/libpyside/class_property.cpp b/sources/pyside6/libpyside/class_property.cpp
index c255ef1e9..2bed97ef5 100644
--- a/sources/pyside6/libpyside/class_property.cpp
+++ b/sources/pyside6/libpyside/class_property.cpp
@@ -5,6 +5,7 @@
#include "pysidestaticstrings.h"
#include "feature_select.h"
+#include <pep384ext.h>
#include <shiboken.h>
#include <sbkstaticstrings.h>
@@ -23,14 +24,54 @@ extern "C" {
// `class_property.__get__()`: Always pass the class instead of the instance.
static PyObject *PyClassProperty_descr_get(PyObject *self, PyObject * /*ob*/, PyObject *cls)
{
- return PyProperty_Type.tp_descr_get(self, cls, cls);
+ return PepExt_Type_GetDescrGetSlot(&PyProperty_Type)(self, cls, cls);
}
// `class_property.__set__()`: Just like the above `__get__()`.
static int PyClassProperty_descr_set(PyObject *self, PyObject *obj, PyObject *value)
{
PyObject *cls = PyType_Check(obj) ? obj : reinterpret_cast<PyObject *>(Py_TYPE(obj));
- return PyProperty_Type.tp_descr_set(self, cls, value);
+ return PepExt_Type_GetDescrSetSlot(&PyProperty_Type)(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
@@ -40,36 +81,38 @@ static int PyClassProperty_tp_init(PyObject *self, PyObject *args, PyObject *kwa
{
auto hold = Py_TYPE(self);
self->ob_type = &PyProperty_Type;
- auto ret = PyProperty_Type.tp_init(self, args, kwargs);
+ auto ret = PepExt_Type_GetInitSlot(&PyProperty_Type)(self, args, kwargs);
self->ob_type = hold;
return ret;
}
-static PyType_Slot PyClassProperty_slots[] = {
- {Py_tp_getset, nullptr}, // 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)},
- {Py_tp_init, reinterpret_cast<void *>(PyClassProperty_tp_init)},
- {0, 0}
-};
-
-static PyType_Spec PyClassProperty_spec = {
- "2:PySide6.QtCore.PyClassProperty",
- sizeof(propertyobject),
- 0,
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
- PyClassProperty_slots,
-};
+static PyTypeObject *createPyClassPropertyType()
+{
+ PyType_Slot PyClassProperty_slots[] = {
+ {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)},
+ {Py_tp_init, reinterpret_cast<void *>(PyClassProperty_tp_init)},
+ {0, nullptr}
+ };
+
+ PyType_Spec PyClassProperty_spec = {
+ "2:PySide6.QtCore.PyClassProperty",
+ sizeof(propertyobject),
+ 0,
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+ PyClassProperty_slots,
+ };
+
+ if (_PepRuntimeVersion() >= 0x030A00)
+ PyClassProperty_spec.basicsize = sizeof(propertyobject310);
+ return SbkType_FromSpecWithMeta(&PyClassProperty_spec, PyClassPropertyType_TypeF());
+}
PyTypeObject *PyClassProperty_TypeF()
{
- static PyTypeObject *type = nullptr;
- if (type == nullptr) {
- // Provide the same `tp_getset`, which is not inherited.
- PyClassProperty_slots[0].pfunc = PyProperty_Type.tp_getset;
- type = SbkType_FromSpec(&PyClassProperty_spec);
- }
+ static auto *type = createPyClassPropertyType();
return type;
}
@@ -96,11 +139,9 @@ static int SbkObjectType_meta_setattro(PyObject *obj, PyObject *name, PyObject *
&& !PyObject_IsInstance(value, class_prop);
if (call_descr_set) {
// Call `class_property.__set__()` instead of replacing the `class_property`.
- return Py_TYPE(descr)->tp_descr_set(descr, obj, value);
- } else {
- // Replace existing attribute.
- return PyType_Type.tp_setattro(obj, name, value);
- }
+ return PepExt_Type_GetDescrSetSlot(Py_TYPE(descr))(descr, obj, value);
+ } // Replace existing attribute.
+ return PepExt_Type_GetSetAttroSlot(&PyType_Type)(obj, name, value);
}
} // extern "C"
@@ -108,7 +149,7 @@ static int SbkObjectType_meta_setattro(PyObject *obj, PyObject *name, PyObject *
/*
* These functions are added to the SbkObjectType_TypeF() dynamically.
*/
-namespace PySide { namespace ClassProperty {
+namespace PySide::ClassProperty {
static const char *PyClassProperty_SignatureStrings[] = {
"PySide6.QtCore.PyClassProperty(cls,"
@@ -125,7 +166,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;
@@ -135,5 +175,4 @@ void init(PyObject *module)
PyModule_AddObject(module, "PyClassProperty", classproptype);
}
-} // namespace ClassProperty
-} // namespace PySide
+} // namespace PySide::ClassProperty