aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sources/pyside6/libpyside/feature_select.cpp30
-rw-r--r--sources/pyside6/tests/pysidetest/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/pysidetest/true_property_test.py38
3 files changed, 65 insertions, 4 deletions
diff --git a/sources/pyside6/libpyside/feature_select.cpp b/sources/pyside6/libpyside/feature_select.cpp
index 567ae79e0..cf55ae7cf 100644
--- a/sources/pyside6/libpyside/feature_select.cpp
+++ b/sources/pyside6/libpyside/feature_select.cpp
@@ -614,6 +614,28 @@ PyObject *adjustPropertyName(PyObject *dict, PyObject *name)
return name;
}
+static QByteArrayList GetPropertyStringsMro(PyTypeObject *type)
+{
+ /*
+ * PYSIDE-2042: There are possibly more methods which should become properties,
+ * because the wrapping process does not obey inheritance.
+ * Therefore, we need to walk the mro to find property strings.
+ */
+ auto res = QByteArrayList();
+
+ PyObject *mro = type->tp_mro;
+ Py_ssize_t idx, n = PyTuple_GET_SIZE(mro);
+ // We leave 'Shiboken.Object' and 'object' alone, therefore "n - 2".
+ for (idx = 0; idx < n - 2; idx++) {
+ auto *subType = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, idx));
+ auto props = SbkObjectType_GetPropertyStrings(subType);
+ if (props != nullptr)
+ for (; *props != nullptr; ++props)
+ res << QByteArray(*props);
+ }
+ return res;
+}
+
static bool feature_02_true_property(PyTypeObject *type, PyObject *prev_dict, int id)
{
/*
@@ -643,12 +665,12 @@ static bool feature_02_true_property(PyTypeObject *type, PyObject *prev_dict, in
}
// We then replace methods by properties.
bool lower = (id & 0x01) != 0;
- auto props = SbkObjectType_GetPropertyStrings(type);
- if (props == nullptr || *props == nullptr)
+ auto props = GetPropertyStringsMro(type);
+ if (props.isEmpty())
return true;
- for (; *props != nullptr; ++props) {
+
+ for (const auto &propStr : std::as_const(props)) {
bool isStdWrite;
- auto propStr = *props;
auto fields = parseFields(propStr, &isStdWrite);
bool haveWrite = fields.size() == 3;
PyObject *name = make_snake_case(fields[0], lower);
diff --git a/sources/pyside6/tests/pysidetest/CMakeLists.txt b/sources/pyside6/tests/pysidetest/CMakeLists.txt
index e88b866c4..d0932509e 100644
--- a/sources/pyside6/tests/pysidetest/CMakeLists.txt
+++ b/sources/pyside6/tests/pysidetest/CMakeLists.txt
@@ -149,6 +149,7 @@ PYSIDE_TEST(new_inherited_functions_test.py)
PYSIDE_TEST(notify_id.py)
PYSIDE_TEST(properties_test.py)
PYSIDE_TEST(property_python_test.py)
+PYSIDE_TEST(true_property_test.py)
PYSIDE_TEST(qapp_like_a_macro_test.py)
PYSIDE_TEST(qvariant_test.py)
PYSIDE_TEST(repr_test.py)
diff --git a/sources/pyside6/tests/pysidetest/true_property_test.py b/sources/pyside6/tests/pysidetest/true_property_test.py
new file mode 100644
index 000000000..671cc4571
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/true_property_test.py
@@ -0,0 +1,38 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import os
+import sys
+import unittest
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+from init_paths import init_test_paths
+init_test_paths(False)
+
+"""
+PYSIDE-2042: Tests true_property with inheritance
+"""
+
+from PySide6.QtCore import QSize
+from PySide6.QtWidgets import QWidget, QSpinBox
+from __feature__ import true_property
+from helper.usesqapplication import UsesQApplication
+
+
+class TruePropertyInheritanceTest(UsesQApplication):
+
+ def testTrueProperty(self):
+ # this worked
+ widget = QWidget()
+ check = widget.sizeHint
+ self.assertEqual(type(check), QSize)
+
+ # PYSIDE-2042: inheritance did not work
+ spin_box = QSpinBox()
+ check = spin_box.sizeHint
+ self.assertEqual(type(check), QSize)
+
+
+if __name__ == '__main__':
+ unittest.main()