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.cpp178
1 files changed, 89 insertions, 89 deletions
diff --git a/sources/pyside6/libpyside/class_property.cpp b/sources/pyside6/libpyside/class_property.cpp
index 63850be07..2bed97ef5 100644
--- a/sources/pyside6/libpyside/class_property.cpp
+++ b/sources/pyside6/libpyside/class_property.cpp
@@ -1,47 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt for Python.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "pyside.h"
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "class_property.h"
#include "pysidestaticstrings.h"
#include "feature_select.h"
-#include "class_property.h"
+#include <pep384ext.h>
#include <shiboken.h>
#include <sbkstaticstrings.h>
@@ -58,56 +22,97 @@ extern "C" {
*/
// `class_property.__get__()`: Always pass the class instead of the instance.
-static PyObject *PyClassProperty_get(PyObject *self, PyObject * /*ob*/, PyObject *cls)
+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_set(PyObject *self, PyObject *obj, PyObject *value)
+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
// 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.
-static int PyClassProperty_init(PyObject *self, PyObject *args, PyObject *kwargs)
+static int PyClassProperty_tp_init(PyObject *self, PyObject *args, PyObject *kwargs)
{
auto hold = Py_TYPE(self);
- Py_TYPE(self) = &PyProperty_Type;
- auto ret = PyProperty_Type.tp_init(self, args, kwargs);
- Py_TYPE(self) = hold;
+ self->ob_type = &PyProperty_Type;
+ 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_get)},
- {Py_tp_descr_set, reinterpret_cast<void *>(PyClassProperty_set)},
- {Py_tp_init, reinterpret_cast<void *>(PyClassProperty_init)},
- {0, 0}
-};
-
-static PyType_Spec PyClassProperty_spec = {
- "PySide6.QtCore.PyClassProperty",
- sizeof(propertyobject),
- 0,
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
- PyClassProperty_slots,
-};
-
-PyTypeObject *PyClassPropertyTypeF()
+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 = reinterpret_cast<PyTypeObject *>(
- PyType_FromSpec(&PyClassProperty_spec));
- }
+ static auto *type = createPyClassPropertyType();
return type;
}
@@ -129,16 +134,14 @@ static int SbkObjectType_meta_setattro(PyObject *obj, PyObject *name, PyObject *
// 1. `Type.class_prop = value` --> descr_set: `Type.class_prop.__set__(value)`
// 2. `Type.class_prop = other_class_prop` --> setattro: replace existing `class_prop`
// 3. `Type.regular_attribute = value` --> setattro: regular attribute assignment
- const auto class_prop = reinterpret_cast<PyObject *>(PyClassPropertyTypeF());
+ const auto class_prop = reinterpret_cast<PyObject *>(PyClassProperty_TypeF());
const auto call_descr_set = descr && PyObject_IsInstance(descr, class_prop)
&& !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"
@@ -146,15 +149,14 @@ 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,"
"fget:typing.Optional[typing.Callable[[typing.Any],typing.Any]]=None,"
"fset:typing.Optional[typing.Callable[[typing.Any,typing.Any],None]]=None,"
"fdel:typing.Optional[typing.Callable[[typing.Any],None]]=None,"
- "doc:typing.Optional[str]=None)"
- "->PySide6.QtCore.PyClassProperty",
+ "doc:typing.Optional[str]=None)",
"PySide6.QtCore.PyClassProperty.getter(cls,fget:typing.Callable[[typing.Any],typing.Any])->PySide6.QtCore.PyClassProperty",
"PySide6.QtCore.PyClassProperty.setter(cls,fset:typing.Callable[[typing.Any,typing.Any],None])->PySide6.QtCore.PyClassProperty",
"PySide6.QtCore.PyClassProperty.deleter(cls,fdel:typing.Callable[[typing.Any],None])->PySide6.QtCore.PyClassProperty",
@@ -164,15 +166,13 @@ void init(PyObject *module)
{
PyTypeObject *type = SbkObjectType_TypeF();
type->tp_setattro = SbkObjectType_meta_setattro;
- Py_TYPE(PyClassPropertyTypeF()) = type;
- if (InitSignatureStrings(PyClassPropertyTypeF(), PyClassProperty_SignatureStrings) < 0)
+ if (InitSignatureStrings(PyClassProperty_TypeF(), PyClassProperty_SignatureStrings) < 0)
return;
- Py_INCREF(PyClassPropertyTypeF());
- auto classproptype = reinterpret_cast<PyObject *>(PyClassPropertyTypeF());
+ Py_INCREF(PyClassProperty_TypeF());
+ auto classproptype = reinterpret_cast<PyObject *>(PyClassProperty_TypeF());
PyModule_AddObject(module, "PyClassProperty", classproptype);
}
-} // namespace ClassProperty
-} // namespace PySide
+} // namespace PySide::ClassProperty