@@ -33,6 +33,46 @@ static int PyClassProperty_descr_set(PyObject *self, PyObject *obj, PyObject *va
33
33
return PyProperty_Type.tp_descr_set (self, cls, value);
34
34
}
35
35
36
+ // PYSIDE-2230: Why is this metaclass necessary?
37
+ //
38
+ // The problem is that the property object already exists as a Python
39
+ // object. We derive a subclass for class properties, without
40
+ // repeating everything but just by adding something to support
41
+ // the class-ness.
42
+ //
43
+ // But this Python property has as metaclass `type` which is incompatible
44
+ // now with SbkObjectType, which generates physically larger types that
45
+ // are incompatible with properties by using PEP 697.
46
+ // Adding a compatible metaclass that is unrelated to `SbkObjectType`
47
+ // is the correct solution. Re-using `SbkObjectType` was actually an abuse,
48
+ // since Python properties are in no way PySide objects.
49
+
50
+ static PyTypeObject *createClassPropertyTypeType ()
51
+ {
52
+ PyType_Slot PyClassPropertyType_Type_slots[] = {
53
+ {Py_tp_base, static_cast <void *>(&PyType_Type)},
54
+ {Py_tp_alloc, reinterpret_cast <void *>(PyType_GenericAlloc)},
55
+ {Py_tp_free, reinterpret_cast <void *>(PyObject_GC_Del)},
56
+ {0 , nullptr }
57
+ };
58
+
59
+ PyType_Spec PyClassPropertyType_Type_spec = {
60
+ " 1:Shiboken.ClassPropertyType" ,
61
+ 0 ,
62
+ 0 , // sizeof(PyMemberDef), not for PyPy without a __len__ defined
63
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_TYPE_SUBCLASS,
64
+ PyClassPropertyType_Type_slots,
65
+ };
66
+
67
+ return SbkType_FromSpec (&PyClassPropertyType_Type_spec);
68
+ }
69
+
70
+ PyTypeObject *PyClassPropertyType_TypeF ()
71
+ {
72
+ static auto *type = createClassPropertyTypeType ();
73
+ return type;
74
+ }
75
+
36
76
// The property `__doc__` default does not work for class properties
37
77
// because PyProperty_Type.tp_init thinks this is a subclass which needs PyObject_SetAttr.
38
78
// 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
48
88
static PyTypeObject *createPyClassPropertyType ()
49
89
{
50
90
PyType_Slot PyClassProperty_slots[] = {
51
- {Py_tp_getset, nullptr }, // will be set below
91
+ {Py_tp_getset, reinterpret_cast < void *>(PyProperty_Type. tp_getset ) }, // will be set below
52
92
{Py_tp_base, reinterpret_cast <void *>(&PyProperty_Type)},
53
93
{Py_tp_descr_get, reinterpret_cast <void *>(PyClassProperty_descr_get)},
54
94
{Py_tp_descr_set, reinterpret_cast <void *>(PyClassProperty_descr_set)},
@@ -64,10 +104,9 @@ static PyTypeObject *createPyClassPropertyType()
64
104
PyClassProperty_slots,
65
105
};
66
106
67
- PyClassProperty_slots[0 ].pfunc = PyProperty_Type.tp_getset ;
68
107
if (_PepRuntimeVersion () >= 0x030A00 )
69
108
PyClassProperty_spec.basicsize = sizeof (propertyobject310);
70
- return SbkType_FromSpec (&PyClassProperty_spec);
109
+ return SbkType_FromSpecWithMeta (&PyClassProperty_spec, PyClassPropertyType_TypeF () );
71
110
}
72
111
73
112
PyTypeObject *PyClassProperty_TypeF ()
@@ -126,7 +165,6 @@ void init(PyObject *module)
126
165
{
127
166
PyTypeObject *type = SbkObjectType_TypeF ();
128
167
type->tp_setattro = SbkObjectType_meta_setattro;
129
- reinterpret_cast <PyObject *>(type)->ob_type = type;
130
168
131
169
if (InitSignatureStrings (PyClassProperty_TypeF (), PyClassProperty_SignatureStrings) < 0 )
132
170
return ;
0 commit comments