aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/tests/pysidetest
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6/tests/pysidetest')
-rw-r--r--sources/pyside6/tests/pysidetest/CMakeLists.txt171
-rw-r--r--sources/pyside6/tests/pysidetest/all_modules_load_test.py29
-rw-r--r--sources/pyside6/tests/pysidetest/bug_1016.py26
-rw-r--r--sources/pyside6/tests/pysidetest/constructor_properties_test.py127
-rw-r--r--sources/pyside6/tests/pysidetest/container_test.py63
-rw-r--r--sources/pyside6/tests/pysidetest/containertest.cpp59
-rw-r--r--sources/pyside6/tests/pysidetest/containertest.h34
-rw-r--r--sources/pyside6/tests/pysidetest/curr_errors.txt12
-rw-r--r--sources/pyside6/tests/pysidetest/decoratedslot_test.py50
-rw-r--r--sources/pyside6/tests/pysidetest/delegatecreateseditor_test.py81
-rw-r--r--sources/pyside6/tests/pysidetest/enum_test.py186
-rw-r--r--sources/pyside6/tests/pysidetest/flagstest.cpp11
-rw-r--r--sources/pyside6/tests/pysidetest/flagstest.h32
-rw-r--r--sources/pyside6/tests/pysidetest/hiddenobject.cpp19
-rw-r--r--sources/pyside6/tests/pysidetest/hiddenobject.h27
-rw-r--r--sources/pyside6/tests/pysidetest/homonymoussignalandmethod_test.py109
-rw-r--r--sources/pyside6/tests/pysidetest/iterable_test.py68
-rw-r--r--sources/pyside6/tests/pysidetest/list_signal_test.py34
-rw-r--r--sources/pyside6/tests/pysidetest/mixin_signal_slots_test.py205
-rw-r--r--sources/pyside6/tests/pysidetest/mock_as_slot_test.py33
-rw-r--r--sources/pyside6/tests/pysidetest/modelview_test.py85
-rw-r--r--sources/pyside6/tests/pysidetest/multiple_inheritance_test.py189
-rw-r--r--sources/pyside6/tests/pysidetest/new_inherited_functions_test.py159
-rw-r--r--sources/pyside6/tests/pysidetest/notify_id.py65
-rw-r--r--sources/pyside6/tests/pysidetest/properties_test.py108
-rw-r--r--sources/pyside6/tests/pysidetest/property_python_test.py222
-rw-r--r--sources/pyside6/tests/pysidetest/pyenum_relax_options_test.py136
-rw-r--r--sources/pyside6/tests/pysidetest/pysidetest.pyproject33
-rw-r--r--sources/pyside6/tests/pysidetest/pysidetest_global.h16
-rw-r--r--sources/pyside6/tests/pysidetest/pysidetest_macros.h18
-rw-r--r--sources/pyside6/tests/pysidetest/qapp_like_a_macro_test.py68
-rw-r--r--sources/pyside6/tests/pysidetest/qvariant_test.py67
-rw-r--r--sources/pyside6/tests/pysidetest/repr_test.py64
-rw-r--r--sources/pyside6/tests/pysidetest/shared_pointer_test.py54
-rw-r--r--sources/pyside6/tests/pysidetest/sharedpointertestbench.cpp46
-rw-r--r--sources/pyside6/tests/pysidetest/sharedpointertestbench.h29
-rw-r--r--sources/pyside6/tests/pysidetest/signal_slot_warning.py50
-rw-r--r--sources/pyside6/tests/pysidetest/signal_tp_descr_get_test.py60
-rw-r--r--sources/pyside6/tests/pysidetest/signalandnamespace_test.py103
-rw-r--r--sources/pyside6/tests/pysidetest/signalemissionfrompython_test.py96
-rw-r--r--sources/pyside6/tests/pysidetest/signalinstance_equality_test.py85
-rw-r--r--sources/pyside6/tests/pysidetest/signalwithdefaultvalue_test.py96
-rw-r--r--sources/pyside6/tests/pysidetest/snake_case_sub.py23
-rw-r--r--sources/pyside6/tests/pysidetest/snake_case_test.py38
-rw-r--r--sources/pyside6/tests/pysidetest/symbols.filter7
-rw-r--r--sources/pyside6/tests/pysidetest/testobject.cpp73
-rw-r--r--sources/pyside6/tests/pysidetest/testobject.h140
-rw-r--r--sources/pyside6/tests/pysidetest/testqvariantenum.cpp29
-rw-r--r--sources/pyside6/tests/pysidetest/testqvariantenum.h35
-rw-r--r--sources/pyside6/tests/pysidetest/testview.cpp27
-rw-r--r--sources/pyside6/tests/pysidetest/testview.h35
-rw-r--r--sources/pyside6/tests/pysidetest/true_property_test.py58
-rw-r--r--sources/pyside6/tests/pysidetest/typedef_signal_test.py52
-rw-r--r--sources/pyside6/tests/pysidetest/typesystem_pysidetest.xml80
-rw-r--r--sources/pyside6/tests/pysidetest/version_test.py31
55 files changed, 3853 insertions, 0 deletions
diff --git a/sources/pyside6/tests/pysidetest/CMakeLists.txt b/sources/pyside6/tests/pysidetest/CMakeLists.txt
new file mode 100644
index 000000000..38f42f342
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/CMakeLists.txt
@@ -0,0 +1,171 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+project(pysidetest)
+project(testbinding)
+
+cmake_minimum_required(VERSION 3.18)
+
+set(QT_USE_QTCORE 1)
+# no more supported: include(${QT_USE_FILE})
+
+# removed after qtbase/054b66a65748c9ebfafeca88bf31669a24994237, is this required?
+# add_definitions(${Qt${QT_MAJOR_VERSION}Core_DEFINITIONS})
+
+set(CMAKE_AUTOMOC ON)
+
+add_definitions(-DQT_SHARED)
+add_definitions(-DRXX_ALLOCATOR_INIT_0)
+
+find_package(Qt6 REQUIRED COMPONENTS Widgets)
+
+set(pysidetest_SRC
+containertest.cpp containertest.h
+flagstest.cpp flagstest.h
+hiddenobject.cpp hiddenobject.h
+pysidetest_global.h
+pysidetest_macros.h
+sharedpointertestbench.cpp sharedpointertestbench.h
+testobject.cpp testobject.h
+testview.cpp testview.h
+testqvariantenum.cpp testqvariantenum.h
+)
+
+set(testbinding_SRC
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/containertest_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/flagsnamespace_classforenum_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/testobject_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/intvalue_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/pysidecpp_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/pysidecpp_testobjectwithnamespace_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/pysidecpp_testobject2withnamespace_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/pysidecpp2_testobjectwithoutnamespace_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/qsharedpointer_qobject_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/qsharedpointer_int_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/sharedpointertestbench_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/testview_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/testbinding_module_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/testqvariantenum_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/qvariantholder_wrapper.cpp
+)
+
+# Get per module include dirs.
+# There are usually 3 paths there:
+# ./qt/include/; ./qt/include/QtCore ; ./qt/mkspecs/linux-g++
+# on framework build they are:
+# ./qt/lib/QtCore.framework; ./qt/lib/QtCore.framework/Headers ; ./qt/mkspecs/macx-clang
+# Thus we use the second direct path, which contains the actual header files.
+
+set(Qt6Core_DIRECT_INCLUDE_DIR ${Qt6Core_INCLUDE_DIRS})
+set(Qt6Gui_DIRECT_INCLUDE_DIR ${Qt6Gui_INCLUDE_DIRS})
+set(Qt6Widgets_DIRECT_INCLUDE_DIR ${Qt6Widgets_INCLUDE_DIRS})
+
+# Adjust include headers paths for frameworks.
+set(shiboken_framework_include_dirs_option "")
+if(CMAKE_HOST_APPLE AND QtCore_is_framework)
+ set(shiboken_framework_include_dirs "${QT_FRAMEWORK_INCLUDE_DIR}")
+ set(shiboken_framework_include_dirs_option "--framework-include-paths=${shiboken_framework_include_dirs}")
+endif()
+
+make_path(testbinding_include_dirs ${pyside6_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../shiboken6/libshiboken
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../PySide6
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../libpyside
+ ${QT_INCLUDE_DIR}
+ ${Qt${QT_MAJOR_VERSION}Core_DIRECT_INCLUDE_DIR}
+ ${Qt${QT_MAJOR_VERSION}Gui_DIRECT_INCLUDE_DIR}
+ ${Qt${QT_MAJOR_VERSION}Widgets_DIRECT_INCLUDE_DIR}
+ )
+
+make_path(testbinding_typesystem_path ${pyside6_SOURCE_DIR}
+ ${pyside6_BINARY_DIR})
+
+shiboken_get_tool_shell_wrapper(shiboken tool_wrapper)
+
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log"
+ BYPRODUCTS ${testbinding_SRC}
+ COMMAND
+ ${tool_wrapper}
+ $<TARGET_FILE:Shiboken6::shiboken6>
+ ${GENERATOR_EXTRA_FLAGS}
+ ${CMAKE_CURRENT_SOURCE_DIR}/pysidetest_global.h
+ --include-paths=${testbinding_include_dirs}
+ ${shiboken_framework_include_dirs_option}
+ --typesystem-paths=${testbinding_typesystem_path}
+ --output-directory=${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/typesystem_pysidetest.xml
+ --api-version=${SUPPORTED_QT_VERSION}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ COMMENT "Running generator for test binding..."
+)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS}
+ ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS}
+ ${Qt${QT_MAJOR_VERSION}Widgets_INCLUDE_DIRS}
+ ${pyside6_SOURCE_DIR}
+ ${QtCore_GEN_DIR}
+ ${QtGui_GEN_DIR}
+ ${QtWidgets_GEN_DIR}
+ ${libpyside_SOURCE_DIR})
+
+add_library(pysidetest SHARED ${pysidetest_SRC})
+set_target_properties(pysidetest PROPERTIES
+ DEFINE_SYMBOL BUILD_PYSIDETEST)
+
+target_link_libraries(pysidetest
+ Shiboken6::libshiboken
+ Qt::Core Qt::Gui Qt::Widgets)
+
+add_library(testbinding MODULE ${testbinding_SRC})
+set_property(TARGET testbinding PROPERTY PREFIX "")
+set_property(TARGET testbinding PROPERTY OUTPUT_NAME "testbinding${SHIBOKEN_PYTHON_EXTENSION_SUFFIX}")
+if(WIN32)
+ set_property(TARGET testbinding PROPERTY SUFFIX ".pyd")
+endif()
+
+target_link_libraries(testbinding
+ pysidetest
+ pyside6
+ Shiboken6::libshiboken
+ Qt::Core Qt::Gui Qt::Widgets)
+
+add_dependencies(testbinding pyside6 QtCore QtGui QtWidgets pysidetest)
+create_generator_target(testbinding)
+
+PYSIDE_TEST(constructor_properties_test.py)
+PYSIDE_TEST(container_test.py)
+PYSIDE_TEST(decoratedslot_test.py)
+PYSIDE_TEST(delegatecreateseditor_test.py)
+PYSIDE_TEST(all_modules_load_test.py)
+PYSIDE_TEST(bug_1016.py)
+PYSIDE_TEST(enum_test.py)
+PYSIDE_TEST(homonymoussignalandmethod_test.py)
+PYSIDE_TEST(iterable_test.py)
+PYSIDE_TEST(list_signal_test.py)
+PYSIDE_TEST(mixin_signal_slots_test.py)
+PYSIDE_TEST(modelview_test.py)
+PYSIDE_TEST(multiple_inheritance_test.py)
+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(snake_case_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)
+PYSIDE_TEST(shared_pointer_test.py)
+PYSIDE_TEST(signal_tp_descr_get_test.py)
+PYSIDE_TEST(signal_slot_warning.py)
+PYSIDE_TEST(signalandnamespace_test.py)
+PYSIDE_TEST(signalemissionfrompython_test.py)
+PYSIDE_TEST(signalinstance_equality_test.py)
+PYSIDE_TEST(signalwithdefaultvalue_test.py)
+PYSIDE_TEST(typedef_signal_test.py)
+PYSIDE_TEST(version_test.py)
+PYSIDE_TEST(mock_as_slot_test.py)
+PYSIDE_TEST(pyenum_relax_options_test.py)
diff --git a/sources/pyside6/tests/pysidetest/all_modules_load_test.py b/sources/pyside6/tests/pysidetest/all_modules_load_test.py
new file mode 100644
index 000000000..454c2b14f
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/all_modules_load_test.py
@@ -0,0 +1,29 @@
+# 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)
+
+import PySide6
+
+# Note:
+# "from PySide6 import *" can only be used at module level.
+# It is also really not recommended to use. But for testing,
+# the "__all__" variable is a great feature!
+
+
+class AllModulesImportTest(unittest.TestCase):
+ def testAllModulesCanImport(self):
+ # would also work: exec("from PySide6 import *")
+ for name in PySide6.__all__:
+ exec(f"import PySide6.{name}")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/bug_1016.py b/sources/pyside6/tests/pysidetest/bug_1016.py
new file mode 100644
index 000000000..219384e66
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/bug_1016.py
@@ -0,0 +1,26 @@
+# 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(True)
+
+import shiboken6
+from testbinding import getHiddenObject
+
+
+class TestBug1016 (unittest.TestCase):
+
+ def testIt(self):
+ obj = getHiddenObject()
+ self.assertEqual(obj.callMe(), None)
+ self.assertTrue(obj.wasCalled())
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/constructor_properties_test.py b/sources/pyside6/tests/pysidetest/constructor_properties_test.py
new file mode 100644
index 000000000..ec6e39821
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/constructor_properties_test.py
@@ -0,0 +1,127 @@
+# Copyright (C) 2022 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
+
+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)
+
+from helper.usesqapplication import UsesQApplication
+from PySide6.QtCore import Qt
+from PySide6.QtGui import QColor, QAction
+from PySide6.QtWidgets import QApplication, QLabel, QFrame
+
+is_pypy = hasattr(sys, "pypy_version_info")
+if not is_pypy:
+ from PySide6.support import feature
+
+
+class ConstructorPropertiesTest(unittest.TestCase):
+
+ def setUp(self):
+ qApp or QApplication()
+ if not is_pypy:
+ feature.reset()
+
+ def tearDown(self):
+ if not is_pypy:
+ feature.reset()
+ qApp.shutdown()
+
+ # PYSIDE-1019: First property extension was support by the constructor.
+ def testCallConstructor(self):
+ label = QLabel(
+ frameStyle=QFrame.Panel | QFrame.Sunken, # QFrame attr, no property
+ lineWidth=2, # QFrame property
+ text="first line\nsecond line", # QLabel property
+ alignment=Qt.AlignBottom | Qt.AlignRight # QLabel property
+ )
+ self.assertEqual(label.lineWidth(), 2)
+ self.assertRaises(AttributeError, lambda: QLabel(
+ somethingelse=42,
+ ))
+
+ # PYSIDE-1705: The same with snake_case
+ @unittest.skipIf(is_pypy, "feature switching is not yet possible in PyPy")
+ def testCallConstructor_snake(self):
+ from __feature__ import snake_case
+
+ label = QLabel(
+ frame_style=QFrame.Panel | QFrame.Sunken, # QFrame attr, no property
+ line_width=2, # QFrame property
+ text="first line\nsecond line", # QLabel property
+ alignment=Qt.AlignBottom | Qt.AlignRight # QLabel property
+ )
+ self.assertEqual(label.line_width(), 2)
+ self.assertRaises(AttributeError, lambda: QLabel(
+ lineWidth=2, # QFrame property
+ ))
+
+ # PYSIDE-1705: The same with true_property
+ @unittest.skipIf(is_pypy, "feature switching is not yet possible in PyPy")
+ def testCallConstructor_prop(self):
+ from __feature__ import true_property
+
+ label = QLabel(
+ frameStyle=QFrame.Panel | QFrame.Sunken, # QFrame attr, no property
+ lineWidth=2, # QFrame property
+ text="first line\nsecond line", # QLabel property
+ alignment=Qt.AlignBottom | Qt.AlignRight # QLabel property
+ )
+ self.assertEqual(label.lineWidth, 2)
+ self.assertRaises(AttributeError, lambda: QLabel(
+ line_width=2, # QFrame property
+ ))
+
+ # PYSIDE-1705: The same with snake_case and true_property
+ @unittest.skipIf(is_pypy, "feature switching is not yet possible in PyPy")
+ def testCallConstructor_prop_snake(self):
+ from __feature__ import snake_case, true_property
+
+ label = QLabel(
+ frame_style=QFrame.Panel | QFrame.Sunken, # QFrame attr, no property
+ line_width=2, # QFrame property
+ text="first line\nsecond line", # QLabel property
+ alignment=Qt.AlignBottom | Qt.AlignRight # QLabel property
+ )
+ self.assertEqual(label.line_width, 2)
+ self.assertRaises(AttributeError, lambda: QLabel(
+ lineWidth=2, # QFrame property
+ ))
+
+
+class DiverseKeywordsTest(UsesQApplication):
+
+ def testDuplicateKeyword(self):
+ r, g, b, a = 1, 2, 3, 4
+ with self.assertRaises(TypeError) as cm:
+ QColor(r, g, b, a, a=0)
+ self.assertTrue("multiple" in cm.exception.args[0])
+
+ # PYSIDE-1305: Handle keyword args correctly.
+ def testUndefinedKeyword(self):
+ r, g, b, a = 1, 2, 3, 4
+ # From the jira issue:
+ with self.assertRaises(AttributeError) as cm:
+ QColor(r, g, b, a, alpha=0)
+ self.assertTrue("unsupported" in cm.exception.args[0])
+
+ # PYSIDE-1305: Handle keyword args correctly.
+ def testUndefinedConstructorKeyword(self):
+ # make sure that the given attribute lands in the constructor
+ x = QAction(autoRepeat=False)
+ self.assertEqual(x.autoRepeat(), False)
+ x = QAction(autoRepeat=True)
+ self.assertEqual(x.autoRepeat(), True)
+ # QAction derives from QObject, and so the missing attributes
+ # in the constructor are reported as AttributeError.
+ with self.assertRaises(AttributeError):
+ QAction(some_other_name=42)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/container_test.py b/sources/pyside6/tests/pysidetest/container_test.py
new file mode 100644
index 000000000..c83e1f26c
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/container_test.py
@@ -0,0 +1,63 @@
+# 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(True)
+
+from testbinding import ContainerTest
+
+
+EXPECTED_DICT = {1: ["v1"], 2: ["v2_1", "v2_2"],
+ 3: ["v3"],
+ 4: ["v4_1", "v4_2"]}
+
+
+EXPECTED_LIST = [1, 2]
+
+
+def sort_values(m):
+ """Sort value lists in dicts since passing through a QMultiMap changes the order"""
+ result = {}
+ for key, values in m.items():
+ result[key] = sorted(values)
+ return result
+
+
+class ContainerTestTest(unittest.TestCase):
+
+ def testMultiMap(self):
+ m1 = ContainerTest.createMultiMap()
+ self.assertEqual(sort_values(m1), EXPECTED_DICT)
+ m2 = ContainerTest.passThroughMultiMap(m1)
+ self.assertEqual(sort_values(m2), EXPECTED_DICT)
+
+ def testMultiHash(self):
+ m1 = ContainerTest.createMultiHash()
+ self.assertEqual(sort_values(m1), EXPECTED_DICT)
+ m2 = ContainerTest.passThroughMultiHash(m1)
+ self.assertEqual(sort_values(m2), EXPECTED_DICT)
+
+ def testList(self):
+ l1 = ContainerTest.createList()
+ self.assertEqual(l1, EXPECTED_LIST)
+ l2 = ContainerTest.passThroughList(l1)
+ self.assertEqual(l2, EXPECTED_LIST)
+
+ def testSet(self):
+ s1 = ContainerTest.createSet() # Order is not predictable
+ s2 = ContainerTest.passThroughSet(s1)
+ self.assertEqual(sorted(list(s1)), sorted(list(s2)))
+
+ # Since lists are iterable, it should be possible to pass them to set API
+ l2 = ContainerTest.passThroughSet(EXPECTED_LIST)
+ self.assertEqual(sorted(list(l2)), EXPECTED_LIST)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/containertest.cpp b/sources/pyside6/tests/pysidetest/containertest.cpp
new file mode 100644
index 000000000..da8729af3
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/containertest.cpp
@@ -0,0 +1,59 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "containertest.h"
+
+using namespace Qt::StringLiterals;
+
+ContainerTest::ContainerTest() = default;
+
+QMultiMap<int, QString> ContainerTest::createMultiMap()
+{
+ static const QMultiMap<int, QString>
+ result{{1, u"v1"_s},
+ {2, u"v2_1"_s}, {2, u"v2_2"_s},
+ {3, u"v3"_s},
+ {4, u"v4_1"_s}, {4, u"v4_2"_s}};
+ return result;
+}
+
+QMultiMap<int, QString> ContainerTest::passThroughMultiMap(const QMultiMap<int, QString> &in)
+{
+ return in;
+}
+
+QMultiHash<int, QString> ContainerTest::createMultiHash()
+{
+ static const QMultiHash<int, QString>
+ result{{1, u"v1"_s},
+ {2, u"v2_1"_s}, {2, u"v2_2"_s},
+ {3, u"v3"_s},
+ {4, u"v4_1"_s}, {4, u"v4_2"_s}};
+ return result;
+
+}
+
+QMultiHash<int, QString> ContainerTest::passThroughMultiHash(const QMultiHash<int, QString> &in)
+{
+ return in;
+}
+
+QList<int> ContainerTest::createList()
+{
+ return {1, 2};
+}
+
+QList<int> ContainerTest::passThroughList(const QList<int> &list)
+{
+ return list;
+}
+
+QSet<int> ContainerTest::createSet()
+{
+ return {1, 2};
+}
+
+QSet<int> ContainerTest::passThroughSet(const QSet<int> &set)
+{
+ return set;
+}
diff --git a/sources/pyside6/tests/pysidetest/containertest.h b/sources/pyside6/tests/pysidetest/containertest.h
new file mode 100644
index 000000000..068fb3c19
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/containertest.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include "pysidetest_macros.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QMultiMap>
+#include <QtCore/QMultiHash>
+#include <QtCore/QSet>
+#include <QtCore/QString>
+
+class PYSIDETEST_API ContainerTest
+{
+public:
+ ContainerTest();
+
+ static QMultiMap<int, QString> createMultiMap();
+
+ static QMultiMap<int, QString> passThroughMultiMap(const QMultiMap<int, QString> &in);
+
+ static QMultiHash<int, QString> createMultiHash();
+
+ static QMultiHash<int, QString> passThroughMultiHash(const QMultiHash<int, QString> &in);
+
+ static QList<int> createList();
+ static QList<int> passThroughList(const QList<int> &list);
+
+ static QSet<int> createSet();
+ static QSet<int> passThroughSet(const QSet<int> &set);
+};
diff --git a/sources/pyside6/tests/pysidetest/curr_errors.txt b/sources/pyside6/tests/pysidetest/curr_errors.txt
new file mode 100644
index 000000000..a02da203d
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/curr_errors.txt
@@ -0,0 +1,12 @@
+Generating class model... [OK]
+Generating enum model... [OK]
+Generating namespace model... [OK]
+Resolving typedefs... [OK]
+Fixing class inheritance... [OK]
+Detecting inconsistencies in class model... [OK]
+[OK]
+ type 'QPyTextObject' is specified in typesystem, but not defined. This could potentially lead to compilation errors.
+
+
+
+Done, 1 warnings (1051 known issues)
diff --git a/sources/pyside6/tests/pysidetest/decoratedslot_test.py b/sources/pyside6/tests/pysidetest/decoratedslot_test.py
new file mode 100644
index 000000000..3ec9ac9e3
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/decoratedslot_test.py
@@ -0,0 +1,50 @@
+#!/usr/bin/python
+# 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(True)
+
+from PySide6.QtCore import QObject
+from testbinding import TestObject
+
+
+class Receiver(QObject):
+ def __init__(self):
+ super().__init__()
+ self.called = False
+
+ def ReceiverDecorator(func):
+ def decoratedFunction(self, *args, **kw):
+ func(self, *args, **kw)
+ return decoratedFunction
+
+ # This method with the same name of the internal decorated function
+ # is here to test the binding capabilities.
+ def decoratedFunction(self):
+ pass
+
+ @ReceiverDecorator
+ def slot(self):
+ self.called = True
+
+
+class DecoratedSlotTest(unittest.TestCase):
+
+ def testCallingOfDecoratedSlot(self):
+ obj = TestObject(0)
+ receiver = Receiver()
+ obj.staticMethodDouble.connect(receiver.slot)
+ obj.emitStaticMethodDoubleSignal()
+ self.assertTrue(receiver.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/pysidetest/delegatecreateseditor_test.py b/sources/pyside6/tests/pysidetest/delegatecreateseditor_test.py
new file mode 100644
index 000000000..8964ec1ed
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/delegatecreateseditor_test.py
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+# 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(True)
+
+from helper.usesqapplication import UsesQApplication
+from testbinding import TestView
+from PySide6.QtCore import Qt
+from PySide6.QtGui import QStandardItem, QStandardItemModel
+from PySide6.QtWidgets import (QAbstractItemDelegate, QComboBox,
+ QSpinBox, QStyledItemDelegate,
+ QStyleOptionViewItem, QWidget)
+
+id_text = 'This is me'
+
+
+class DelegateDoesntKeepReferenceToEditor(QAbstractItemDelegate):
+ def createEditor(self, parent, option, index):
+ comboBox = QComboBox(parent)
+ comboBox.addItem(id_text)
+ return comboBox
+
+
+class DelegateKeepsReferenceToEditor(QAbstractItemDelegate):
+ def __init__(self, parent=None):
+ QAbstractItemDelegate.__init__(self, parent)
+ self.comboBox = QComboBox()
+ self.comboBox.addItem(id_text)
+
+ def createEditor(self, parent, option, index):
+ self.comboBox.setParent(parent)
+ return self.comboBox
+
+
+class EditorCreatedByDelegateTest(UsesQApplication):
+
+ def testDelegateDoesntKeepReferenceToEditor(self):
+ view = TestView(None)
+ delegate = DelegateDoesntKeepReferenceToEditor()
+ view.setItemDelegate(delegate)
+ editor = view.getEditorWidgetFromItemDelegate()
+ self.assertEqual(type(editor), QComboBox)
+ self.assertEqual(editor.count(), 1)
+ self.assertEqual(editor.itemData(0, Qt.DisplayRole), id_text)
+ editor.metaObject()
+
+ def testDelegateKeepsReferenceToEditor(self):
+ view = TestView(None)
+ delegate = DelegateKeepsReferenceToEditor()
+ view.setItemDelegate(delegate)
+ editor = view.getEditorWidgetFromItemDelegate()
+ self.assertEqual(type(editor), QComboBox)
+ self.assertEqual(editor.count(), 1)
+ self.assertEqual(editor.itemData(0, Qt.DisplayRole), id_text)
+ editor.metaObject()
+
+ def testIntDelegate(self):
+ """PYSIDE-1250: When creating a QVariant, use int instead of long long
+ for anything that fits into a int. Verify by checking that a spin
+ box is created as item view editor for int."""
+ item = QStandardItem()
+ item.setData(123123, Qt.EditRole) # <-- QVariant conversion here
+ model = QStandardItemModel()
+ model.appendRow(item)
+ style_option = QStyleOptionViewItem()
+ delegate = QStyledItemDelegate()
+ editor = delegate.createEditor(None, style_option, model.index(0, 0))
+ self.assertEqual(type(editor), QSpinBox)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/pysidetest/enum_test.py b/sources/pyside6/tests/pysidetest/enum_test.py
new file mode 100644
index 000000000..832834530
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/enum_test.py
@@ -0,0 +1,186 @@
+# 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(True)
+
+from PySide6.QtCore import Qt
+from testbinding import Enum1, TestObjectWithoutNamespace
+
+import dis
+
+
+class ListConnectionTest(unittest.TestCase):
+
+ def testEnumVisibility(self):
+ self.assertEqual(Enum1.Option1, 1)
+ self.assertEqual(Enum1.Option2, 2)
+ self.assertEqual(TestObjectWithoutNamespace.Enum2.Option3, 3)
+ self.assertEqual(TestObjectWithoutNamespace.Enum2.Option4, 4)
+
+ def testFlagComparisonOperators(self): # PYSIDE-1696, compare to self
+ f1 = Qt.AlignHCenter | Qt.AlignBottom
+ f2 = Qt.AlignHCenter | Qt.AlignBottom
+ self.assertTrue(f1 == f1)
+ self.assertTrue(f1 <= f1)
+ self.assertTrue(f1 >= f1)
+ self.assertFalse(f1 != f1)
+ self.assertFalse(f1 < f1)
+ self.assertFalse(f1 > f1)
+
+ self.assertTrue(f1 == f2)
+ self.assertTrue(f1 <= f2)
+ self.assertTrue(f1 >= f2)
+ self.assertFalse(f1 != f2)
+ self.assertFalse(f1 < f2)
+ self.assertFalse(f1 > f2)
+
+ self.assertTrue(Qt.AlignHCenter < Qt.AlignBottom)
+ self.assertFalse(Qt.AlignHCenter > Qt.AlignBottom)
+ self.assertFalse(Qt.AlignBottom < Qt.AlignHCenter)
+ self.assertTrue(Qt.AlignBottom > Qt.AlignHCenter)
+
+
+# PYSIDE-1735: We are testing that opcodes do what they are supposed to do.
+# This is needed in the PyEnum forgiveness mode where we need
+# to introspect the code if an Enum was called with no args.
+class InvestigateOpcodesTest(unittest.TestCase):
+
+ def probe_function1(self):
+ x = Qt.Alignment
+
+ def probe_function2(self):
+ x = Qt.Alignment()
+
+ @staticmethod
+ def read_code(func, **kw):
+ return list(instr[:3] for instr in dis.Bytecode(func, **kw))
+
+ @staticmethod
+ def get_sizes(func, **kw):
+ ops = list((instr.opname, instr.offset) for instr in dis.Bytecode(func, **kw))
+ res = []
+ for idx in range(1, len(ops)):
+ res.append((ops[idx - 1][0], ops[idx][1] - ops[idx - 1][1]))
+ return sorted(res, key=lambda x: (x[1], x[0]))
+
+ _sin = sys.implementation.name
+
+ @unittest.skipIf(hasattr(sys.flags, "nogil"), f"{_sin} has different opcodes")
+ def testByteCode(self):
+ import dis
+ # opname, opcode, arg
+ result_1 = [('LOAD_GLOBAL', 116, 0),
+ ('LOAD_ATTR', 106, 1),
+ ('STORE_FAST', 125, 1),
+ ('LOAD_CONST', 100, 0),
+ ('RETURN_VALUE', 83, None)]
+
+ result_2 = [('LOAD_GLOBAL', 116, 0),
+ ('LOAD_METHOD', 160, 1),
+ ('CALL_METHOD', 161, 0),
+ ('STORE_FAST', 125, 1),
+ ('LOAD_CONST', 100, 0),
+ ('RETURN_VALUE', 83, None)]
+
+ if sys.version_info[:2] <= (3, 6):
+
+ result_2 = [('LOAD_GLOBAL', 116, 0),
+ ('LOAD_ATTR', 106, 1),
+ ('CALL_FUNCTION', 131, 0),
+ ('STORE_FAST', 125, 1),
+ ('LOAD_CONST', 100, 0),
+ ('RETURN_VALUE', 83, None)]
+
+ if sys.version_info[:2] == (3, 11):
+ # Note: Python 3.11 is a bit more complex because it can optimize itself.
+ # Opcodes are a bit different, and a hidden second code object is used.
+ # We investigate this a bit, because we want to be warned when things change.
+ QUICKENING_WARMUP_DELAY = 8
+
+ result_1 = [('RESUME', 151, 0),
+ ('LOAD_GLOBAL', 116, 0),
+ ('LOAD_ATTR', 106, 1),
+ ('STORE_FAST', 125, 1),
+ ('LOAD_CONST', 100, 0),
+ ('RETURN_VALUE', 83, None)]
+
+ result_2 = [('RESUME', 151, 0),
+ ('LOAD_GLOBAL', 116, 1),
+ ('LOAD_ATTR', 106, 1),
+ ('PRECALL', 166, 0),
+ ('CALL', 171, 0),
+ ('STORE_FAST', 125, 1),
+ ('LOAD_CONST', 100, 0),
+ ('RETURN_VALUE', 83, None)]
+
+ sizes_2 = [('LOAD_CONST', 2),
+ ('RESUME', 2),
+ ('STORE_FAST', 2),
+ ('PRECALL', 4),
+ ('CALL', 10),
+ ('LOAD_ATTR', 10),
+ ('LOAD_GLOBAL', 12)]
+
+ self.assertEqual(self.read_code(self.probe_function2, adaptive=True), result_2)
+ self.assertEqual(self.get_sizes(self.probe_function2, adaptive=True), sizes_2)
+
+ @staticmethod
+ def code_quicken(f, times):
+ # running the code triggers acceleration after some runs.
+ for _ in range(times):
+ f()
+
+ code_quicken(self.probe_function2, QUICKENING_WARMUP_DELAY - 1)
+ self.assertEqual(self.read_code(self.probe_function2, adaptive=True), result_2)
+ self.assertEqual(self.get_sizes(self.probe_function2, adaptive=True), sizes_2)
+
+ result_3 = [('RESUME_QUICK', 150, 0),
+ ('LOAD_GLOBAL_MODULE', 55, 1),
+ ('LOAD_ATTR_ADAPTIVE', 39, 1),
+ ('PRECALL_ADAPTIVE', 64, 0),
+ ('CALL_ADAPTIVE', 22, 0),
+ ('STORE_FAST', 125, 1),
+ ('LOAD_CONST', 100, 0),
+ ('RETURN_VALUE', 83, None)]
+
+ sizes_3 = [('LOAD_CONST', 2),
+ ('RESUME_QUICK', 2),
+ ('STORE_FAST', 2),
+ ('PRECALL_ADAPTIVE', 4),
+ ('CALL_ADAPTIVE', 10),
+ ('LOAD_ATTR_ADAPTIVE', 10),
+ ('LOAD_GLOBAL_MODULE', 12)]
+
+ code_quicken(self.probe_function2, 1)
+ self.assertEqual(self.read_code(self.probe_function2, adaptive=True), result_3)
+ self.assertEqual(self.get_sizes(self.probe_function2, adaptive=True), sizes_3)
+
+ if sys.version_info[:2] >= (3, 12):
+
+ result_1 = [('RESUME', 151, 0),
+ ('LOAD_GLOBAL', 116, 0),
+ ('LOAD_ATTR', 106, 2),
+ ('STORE_FAST', 125, 1),
+ ('RETURN_CONST', 121, 0)]
+
+ result_2 = [('RESUME', 151, 0),
+ ('LOAD_GLOBAL', 116, 1),
+ ('LOAD_ATTR', 106, 2),
+ ('CALL', 171, 0),
+ ('STORE_FAST', 125, 1),
+ ('RETURN_CONST', 121, 0)]
+
+ self.assertEqual(self.read_code(self.probe_function1), result_1)
+ self.assertEqual(self.read_code(self.probe_function2), result_2)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/pysidetest/flagstest.cpp b/sources/pyside6/tests/pysidetest/flagstest.cpp
new file mode 100644
index 000000000..ac6c3b3b1
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/flagstest.cpp
@@ -0,0 +1,11 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "flagstest.h"
+
+namespace FlagsNamespace
+{
+ ClassForEnum::ClassForEnum(FlagsNamespace::Options) {}
+
+ ClassForEnum::~ClassForEnum() = default;
+}
diff --git a/sources/pyside6/tests/pysidetest/flagstest.h b/sources/pyside6/tests/pysidetest/flagstest.h
new file mode 100644
index 000000000..b5c73c9bd
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/flagstest.h
@@ -0,0 +1,32 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include "pysidetest_macros.h"
+
+#include <QtCore/QObject>
+
+namespace FlagsNamespace
+{
+
+enum Option {
+ NoOptions = 0x0,
+ ShowTabs = 0x1,
+ ShowAll = 0x2,
+ SqueezeBlank = 0x4
+};
+Q_DECLARE_FLAGS(Options, Option)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Options)
+
+class PYSIDETEST_API ClassForEnum : public QObject
+{
+ Q_OBJECT
+public:
+ Q_DISABLE_COPY_MOVE(ClassForEnum)
+
+ ClassForEnum(FlagsNamespace::Options opt = FlagsNamespace::Option::NoOptions);
+ virtual ~ClassForEnum() override;
+};
+
+} // namespace FlagsNamespace
diff --git a/sources/pyside6/tests/pysidetest/hiddenobject.cpp b/sources/pyside6/tests/pysidetest/hiddenobject.cpp
new file mode 100644
index 000000000..d4feabb66
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/hiddenobject.cpp
@@ -0,0 +1,19 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "hiddenobject.h"
+
+void HiddenObject::callMe()
+{
+ m_called = true;
+}
+
+bool HiddenObject::wasCalled() const
+{
+ return m_called;
+}
+
+QObject *getHiddenObject()
+{
+ return new HiddenObject();
+}
diff --git a/sources/pyside6/tests/pysidetest/hiddenobject.h b/sources/pyside6/tests/pysidetest/hiddenobject.h
new file mode 100644
index 000000000..f399be985
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/hiddenobject.h
@@ -0,0 +1,27 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef HIDDENOBJECT_H
+#define HIDDENOBJECT_H
+
+#include "pysidetest_macros.h"
+
+#include <QtCore/QObject>
+
+// This class shouldn't be exported!
+class HiddenObject : public QObject
+{
+ Q_OBJECT
+public:
+ HiddenObject() noexcept = default;
+ Q_INVOKABLE void callMe();
+public Q_SLOTS:
+ bool wasCalled() const;
+private:
+ bool m_called = false;
+};
+
+// Return a instance of HiddenObject
+PYSIDETEST_API QObject* getHiddenObject();
+
+#endif
diff --git a/sources/pyside6/tests/pysidetest/homonymoussignalandmethod_test.py b/sources/pyside6/tests/pysidetest/homonymoussignalandmethod_test.py
new file mode 100644
index 000000000..b58232a1b
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/homonymoussignalandmethod_test.py
@@ -0,0 +1,109 @@
+#!/usr/bin/python
+# 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 gc
+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(True)
+
+from testbinding import TestObject
+from PySide6.QtCore import QObject, Signal, SignalInstance
+
+'''Tests the behaviour of homonymous signals and slots.'''
+
+
+class HomonymousSignalAndMethodTest(unittest.TestCase):
+
+ def setUp(self):
+ self.value = 123
+ self.called = False
+ self.obj = TestObject(self.value)
+
+ def tearDown(self):
+ del self.value
+ del self.called
+ del self.obj
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testIdValueSignalEmission(self):
+ def callback(idValue):
+ self.assertEqual(idValue, self.value)
+ self.obj.idValue.connect(callback)
+ self.obj.emitIdValueSignal()
+
+ def testStaticMethodDoubleSignalEmission(self):
+ def callback():
+ self.called = True
+ self.obj.staticMethodDouble.connect(callback)
+ self.obj.emitStaticMethodDoubleSignal()
+ self.assertTrue(self.called)
+
+ def testSignalNotCallable(self):
+ self.assertRaises(TypeError, self.obj.justASignal)
+
+ def testCallingInstanceMethodWithArguments(self):
+ self.assertRaises(TypeError, TestObject.idValue, 1)
+
+ def testCallingInstanceMethodWithoutArguments(self):
+ self.assertRaises(TypeError, TestObject.idValue)
+
+ def testHomonymousSignalAndMethod(self):
+ self.assertEqual(self.obj.idValue(), self.value)
+
+ def testHomonymousSignalAndStaticMethod(self):
+ self.assertEqual(TestObject.staticMethodDouble(3), 6)
+
+ def testHomonymousSignalAndStaticMethodFromInstance(self):
+ self.assertEqual(self.obj.staticMethodDouble(4), 8)
+
+
+# PYSIDE-1730: Homonymous Methods with multiple inheritance
+
+class Q(QObject):
+ signal = Signal()
+
+ def method(self):
+ msg = 'Q::method'
+ print(msg)
+ return msg
+
+
+class M:
+
+ def signal(self):
+ msg = 'M::signal'
+ print(msg)
+ return msg
+
+ def method(self):
+ msg = 'M::method'
+ print(msg)
+ return msg
+
+
+class C(M, Q):
+
+ def __init__(self):
+ Q.__init__(self)
+ M.__init__(self)
+
+
+class HomonymousMultipleInheritanceTest(unittest.TestCase):
+
+ def testHomonymousMultipleInheritance(self):
+ c = C()
+ self.assertEqual(c.method(), "M::method") # okay
+ self.assertEqual(c.signal(), "M::signal") # problem on PySide6 6.2.2
+ self.assertEqual(type(c.signal), SignalInstance)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/pysidetest/iterable_test.py b/sources/pyside6/tests/pysidetest/iterable_test.py
new file mode 100644
index 000000000..bdb2ae7be
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/iterable_test.py
@@ -0,0 +1,68 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+"""
+iterable_test.py
+
+This test checks that the Iterable protocol is implemented correctly.
+"""
+
+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)
+
+import PySide6
+from PySide6 import QtCore, QtGui
+
+try:
+ import numpy as np
+ have_numpy = True
+except ImportError:
+ have_numpy = False
+
+
+class PySequenceTest(unittest.TestCase):
+
+ def test_iterable(self):
+ def gen(lis):
+ for item in lis:
+ if item == "crash":
+ raise IndexError
+ yield item
+ # testing "pyseq_to_cpplist_conversion"
+ testfunc = QtCore.QUrl.fromStringList
+ # use a generator (iterable)
+ self.assertEqual(testfunc(gen(["asd", "ghj"])),
+ [PySide6.QtCore.QUrl('asd'), PySide6.QtCore.QUrl('ghj')])
+ # use an iterator
+ self.assertEqual(testfunc(iter(["asd", "ghj"])),
+ [PySide6.QtCore.QUrl('asd'), PySide6.QtCore.QUrl('ghj')])
+ self.assertRaises(IndexError, testfunc, gen(["asd", "crash", "ghj"]))
+ # testing QMatrix4x4
+ testfunc = QtGui.QMatrix4x4
+ self.assertEqual(testfunc(gen(range(16))), testfunc(range(16)))
+ # Note: The errormessage needs to be improved!
+ # We should better get a ValueError
+ self.assertRaises((TypeError, ValueError), testfunc, gen(range(15)))
+ # All other matrix sizes:
+ testfunc = QtGui.QMatrix2x2
+ self.assertEqual(testfunc(gen(range(4))), testfunc(range(4)))
+ testfunc = QtGui.QMatrix2x3
+ self.assertEqual(testfunc(gen(range(6))), testfunc(range(6)))
+
+ @unittest.skipUnless(have_numpy, "requires numpy")
+ def test_iterable_numpy(self):
+ # Demo for numpy: We create a unit matrix.
+ num_mat = np.eye(4)
+ num_mat.shape = 16
+ unit = QtGui.QMatrix4x4(num_mat)
+ self.assertEqual(unit, QtGui.QMatrix4x4())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/list_signal_test.py b/sources/pyside6/tests/pysidetest/list_signal_test.py
new file mode 100644
index 000000000..da4bc298d
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/list_signal_test.py
@@ -0,0 +1,34 @@
+# 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(True)
+
+from testbinding import TestObject
+from PySide6.QtCore import QObject
+
+
+class ListConnectionTest(unittest.TestCase):
+
+ def childrenChanged(self, children):
+ self._child = children[0]
+
+ def testConnection(self):
+ o = TestObject(0)
+ c = QObject()
+ c.setObjectName("child")
+ self._child = None
+ o.childrenChanged.connect(self.childrenChanged)
+ o.addChild(c)
+ self.assertEqual(self._child.objectName(), "child")
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/pysidetest/mixin_signal_slots_test.py b/sources/pyside6/tests/pysidetest/mixin_signal_slots_test.py
new file mode 100644
index 000000000..1d536c0ae
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/mixin_signal_slots_test.py
@@ -0,0 +1,205 @@
+#!/usr/bin/python
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+''' PYSIDE-315: https://bugreports.qt.io/browse/PYSIDE-315
+ Test that all signals and slots of a class (including any mixin classes)
+ are registered at type parsing time. Also test that the signal and slot
+ indices do not change after signal connection or emission. '''
+
+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)
+
+from PySide6.QtCore import QObject, Signal, Slot
+
+
+class Mixin(object):
+ mixinSignal = Signal()
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+
+class MixinTwo(Mixin):
+ mixinTwoSignal = Signal()
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.mixinTwoSlotCalled = False
+
+ @Slot()
+ def mixinTwoSlot(self):
+ self.mixinTwoSlotCalled = True
+
+
+class MixinThree(object):
+ mixinThreeSignal = Signal()
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.mixinThreeSlotCalled = False
+
+ @Slot()
+ def mixinThreeSlot(self):
+ self.mixinThreeSlotCalled = True
+
+
+class Derived(Mixin, QObject):
+ derivedSignal = Signal(str)
+
+ def __init__(self):
+ super().__init__()
+ self.derivedSlotCalled = False
+ self.derivedSlotString = ''
+
+ @Slot(str)
+ def derivedSlot(self, theString):
+ self.derivedSlotCalled = True
+ self.derivedSlotString = theString
+
+
+class MultipleDerived(MixinTwo, MixinThree, Mixin, QObject):
+ derivedSignal = Signal(str)
+
+ def __init__(self):
+ super().__init__()
+ self.derivedSlotCalled = False
+ self.derivedSlotString = ''
+
+ @Slot(str)
+ def derivedSlot(self, theString):
+ self.derivedSlotCalled = True
+ self.derivedSlotString = theString
+
+
+class MixinTest(unittest.TestCase):
+ def testMixinSignalSlotRegistration(self):
+ obj = Derived()
+ m = obj.metaObject()
+
+ # Should contain 2 signals and 1 slot immediately after type parsing
+ self.assertEqual(m.methodCount() - m.methodOffset(), 3)
+
+ # Save method indices to check that they do not change
+ methodIndices = {}
+ for i in range(m.methodOffset(), m.methodCount()):
+ signature = m.method(i).methodSignature()
+ methodIndices[signature] = i
+
+ # Check derivedSignal emission
+ obj.derivedSignal.connect(obj.derivedSlot)
+ obj.derivedSignal.emit('emit1')
+ self.assertTrue(obj.derivedSlotCalled)
+ obj.derivedSlotCalled = False
+
+ # Check derivedSignal emission after mixingSignal connection
+ self.outsideSlotCalled = False
+
+ @Slot()
+ def outsideSlot():
+ self.outsideSlotCalled = True
+
+ obj.mixinSignal.connect(outsideSlot)
+ obj.derivedSignal.emit('emit2')
+ self.assertTrue(obj.derivedSlotCalled)
+ self.assertFalse(self.outsideSlotCalled)
+ obj.derivedSlotCalled = False
+
+ # Check mixinSignal emission
+ obj.mixinSignal.emit()
+ self.assertTrue(self.outsideSlotCalled)
+ self.assertFalse(obj.derivedSlotCalled)
+ self.outsideSlotCalled = False
+
+ # Check that method indices haven't changed.
+ # Make sure to requery for the meta object, to check that a new one was not
+ # created as a child of the old one.
+ m = obj.metaObject()
+ self.assertEqual(m.methodCount() - m.methodOffset(), 3)
+ for i in range(m.methodOffset(), m.methodCount()):
+ signature = m.method(i).methodSignature()
+ self.assertEqual(methodIndices[signature], i)
+
+ def testMixinSignalSlotRegistrationWithMultipleInheritance(self):
+ obj = MultipleDerived()
+ m = obj.metaObject()
+
+ # Should contain 4 signals and 3 slots immediately after type parsing
+ self.assertEqual(m.methodCount() - m.methodOffset(), 7)
+
+ # Save method indices to check that they do not change
+ methodIndices = {}
+ for i in range(m.methodOffset(), m.methodCount()):
+ signature = m.method(i).methodSignature()
+ methodIndices[signature] = i
+
+ # Check derivedSignal emission
+ obj.derivedSignal.connect(obj.derivedSlot)
+ obj.derivedSignal.emit('emit1')
+ self.assertTrue(obj.derivedSlotCalled)
+ self.assertFalse(obj.mixinTwoSlotCalled)
+ self.assertFalse(obj.mixinThreeSlotCalled)
+ obj.derivedSlotCalled = False
+
+ # Check derivedSignal emission after mixinThreeSignal connection
+ self.outsideSlotCalled = False
+
+ @Slot()
+ def outsideSlot():
+ self.outsideSlotCalled = True
+
+ obj.mixinThreeSignal.connect(obj.mixinThreeSlot)
+ obj.mixinThreeSignal.connect(outsideSlot)
+ obj.derivedSignal.emit('emit2')
+ self.assertTrue(obj.derivedSlotCalled)
+ self.assertFalse(obj.mixinTwoSlotCalled)
+ self.assertFalse(obj.mixinThreeSlotCalled)
+ self.assertFalse(self.outsideSlotCalled)
+ obj.derivedSlotCalled = False
+
+ # Check mixinThreeSignal emission
+ obj.mixinThreeSignal.emit()
+ self.assertTrue(self.outsideSlotCalled)
+ self.assertTrue(obj.mixinThreeSlotCalled)
+ self.assertFalse(obj.derivedSlotCalled)
+ self.assertFalse(obj.mixinTwoSlotCalled)
+ self.outsideSlotCalled = False
+ obj.mixinThreeSlotCalled = False
+
+ # Check mixinTwoSignal emission
+ obj.mixinTwoSignal.connect(obj.mixinTwoSlot)
+ obj.mixinTwoSignal.emit()
+ self.assertTrue(obj.mixinTwoSlotCalled)
+ self.assertFalse(obj.mixinThreeSlotCalled)
+ self.assertFalse(obj.derivedSlotCalled)
+ self.assertFalse(self.outsideSlotCalled)
+ obj.mixinTwoSlotCalled = False
+
+ # Check mixinSignal emission
+ obj.mixinSignal.connect(outsideSlot)
+ obj.mixinSignal.emit()
+ self.assertTrue(self.outsideSlotCalled)
+ self.assertFalse(obj.mixinTwoSlotCalled)
+ self.assertFalse(obj.mixinThreeSlotCalled)
+ self.assertFalse(obj.derivedSlotCalled)
+ self.outsideSlotCalled = False
+
+ # Check that method indices haven't changed.
+ # Make sure to requery for the meta object, to check that a new one was not
+ # created as a child of the old one.
+ m = obj.metaObject()
+ self.assertEqual(m.methodCount() - m.methodOffset(), 7)
+ for i in range(m.methodOffset(), m.methodCount()):
+ signature = m.method(i).methodSignature()
+ self.assertEqual(methodIndices[signature], i)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/pysidetest/mock_as_slot_test.py b/sources/pyside6/tests/pysidetest/mock_as_slot_test.py
new file mode 100644
index 000000000..39f52adea
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/mock_as_slot_test.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+""" PYSIDE-1755: https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1755
+ Tests that a unittest.mock.MagicMock() can be used as a slot for quick
+ prototyping. """
+
+import os
+import sys
+import unittest
+from unittest.mock import MagicMock
+
+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)
+
+from PySide6.QtCore import QObject
+
+
+class MockAsSlot(unittest.TestCase):
+ def testMockAsSlot(self):
+ obj = QObject()
+ mock = MagicMock()
+ obj.objectNameChanged.connect(mock)
+
+ obj.objectNameChanged.emit("test")
+ mock.assert_called_once()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/modelview_test.py b/sources/pyside6/tests/pysidetest/modelview_test.py
new file mode 100644
index 000000000..53231aebe
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/modelview_test.py
@@ -0,0 +1,85 @@
+#!/usr/bin/python
+# 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(True)
+
+from testbinding import TestView
+from PySide6.QtCore import QAbstractListModel, QObject, QModelIndex
+
+'''Tests model/view relationship.'''
+
+object_name = 'test object'
+
+
+class MyObject(QObject):
+ pass
+
+
+class ListModelKeepsReference(QAbstractListModel):
+ def __init__(self, parent=None):
+ QAbstractListModel.__init__(self, parent)
+ self.obj = MyObject()
+ self.obj.setObjectName(object_name)
+
+ def rowCount(self, parent=QModelIndex()):
+ return 1
+
+ def data(self, index, role):
+ return self.obj
+
+
+class ListModelDoesntKeepsReference(QAbstractListModel):
+ def rowCount(self, parent=QModelIndex()):
+ return 1
+
+ def data(self, index, role):
+ obj = MyObject()
+ obj.setObjectName(object_name)
+ return obj
+
+
+class ListModelThatReturnsString(QAbstractListModel):
+ def rowCount(self, parent=QModelIndex()):
+ return 1
+
+ def data(self, index, role):
+ self.obj = 'string'
+ return self.obj
+
+
+class ModelViewTest(unittest.TestCase):
+
+ def testListModelDoesntKeepsReference(self):
+ model = ListModelDoesntKeepsReference()
+ view = TestView(model)
+ obj = view.getData()
+ self.assertEqual(type(obj), MyObject)
+ self.assertEqual(obj.objectName(), object_name)
+ obj.metaObject()
+
+ def testListModelKeepsReference(self):
+ model = ListModelKeepsReference()
+ view = TestView(model)
+ obj = view.getData()
+ self.assertEqual(type(obj), MyObject)
+ self.assertEqual(obj.objectName(), object_name)
+
+ def testListModelThatReturnsString(self):
+ model = ListModelThatReturnsString()
+ view = TestView(model)
+ obj = view.getData()
+ self.assertEqual(type(obj), str)
+ self.assertEqual(obj, 'string')
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/pysidetest/multiple_inheritance_test.py b/sources/pyside6/tests/pysidetest/multiple_inheritance_test.py
new file mode 100644
index 000000000..49550ba55
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/multiple_inheritance_test.py
@@ -0,0 +1,189 @@
+# Copyright (C) 2023 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)
+
+from helper.usesqapplication import UsesQApplication
+from PySide6 import QtCore, QtGui, QtWidgets
+from PySide6.QtWidgets import QMainWindow, QLabel, QWidget
+
+
+def xprint(*args, **kw):
+ if "-v" in sys.argv:
+ print(*args, **kw)
+
+
+# This is the original testcase of PYSIDE-1564
+class Age(object):
+ def __init__(self, age=0, **kwds):
+ super().__init__(**kwds)
+
+ self.age = age
+
+
+class Person(QtCore.QObject, Age):
+ def __init__(self, name, **kwds):
+ super().__init__(**kwds)
+
+ self.name = name
+
+
+class OriginalMultipleInheritanceTest(unittest.TestCase):
+
+ def testIt(self):
+ xprint()
+ p = Person("Joe", age=38)
+ xprint(f"p.age = {p.age}")
+ # This would crash if MI does not work.
+
+# More tests follow:
+
+
+# mro ('C', 'A', 'QObject', 'Object', 'B', 'object')
+class A(QtCore.QObject):
+ def __init__(self, anna=77, **kw):
+ xprint(f'A: before init kw = {kw}')
+ super().__init__(**kw)
+ xprint('A: after init')
+
+
+class B:
+ def __init__(self, otto=6, age=7, **kw):
+ xprint(f'B: before init kw = {kw}')
+ if "killme" in kw:
+ raise AssertionError("asdf")
+ super().__init__(**kw)
+ self.age = age
+ xprint('B: after init')
+
+
+class C(A, B):
+ def __init__(self, **kw):
+ xprint(f'C: before init kw = {kw}')
+ super().__init__(**kw)
+ xprint('C: after init')
+
+
+# mro ('F', 'D', 'QCursor', 'E', 'QLabel', 'QFrame', 'QWidget', 'QObject',
+# 'QPaintDevice', 'Object', 'object')
+class D(QtGui.QCursor):
+ def __init__(self, anna=77, **kw):
+ xprint(f'D: before init kw = {kw}')
+ super().__init__(**kw)
+ xprint('D: after init')
+
+
+class E:
+ def __init__(self, age=7, **kw):
+ xprint(f'E: before init kw = {kw}')
+ super().__init__(**kw)
+ self.age = age
+ xprint('E: after init')
+
+
+class F(D, E, QtWidgets.QLabel):
+ def __init__(self, **kw):
+ xprint(f'F: before init kw = {kw}')
+ super().__init__(**kw)
+ xprint('F: after init')
+
+
+# mro ('I', 'G', 'QTextDocument', 'H', 'QLabel', 'QFrame', 'QWidget', 'QObject',
+# 'QPaintDevice', 'Object', 'object')
+# Similar, but this time we want to reach `H` without support from `super`.
+class G(QtGui.QTextDocument):
+ pass
+
+
+class H:
+ def __init__(self, age=7, **kw):
+ xprint(f'H: before init kw = {kw}')
+ super().__init__(**kw)
+ self.age = age
+ xprint('H: after init')
+
+
+class II(G, H, QtWidgets.QLabel):
+ pass
+
+
+# PYSIDE-2294: Friedemann's test adapted.
+# We need to ignore positional args in mixin classes.
+class Ui_X_MainWindow(object): # Emulating uic
+ def setupUi(self, MainWindow):
+ MainWindow.resize(400, 300)
+ self.lbl = QLabel(self)
+
+
+class MainWindow(QMainWindow, Ui_X_MainWindow):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setupUi(self)
+
+
+class AdditionalMultipleInheritanceTest(UsesQApplication):
+
+ def testABC(self):
+ xprint()
+ res = C(otto=3, anna=5)
+ self.assertEqual(res.age, 7)
+ xprint()
+ with self.assertRaises(AssertionError):
+ res = C(killme=42)
+ xprint()
+
+ def testDEF(self):
+ xprint()
+ res = F(anna=5)
+ self.assertEqual(res.age, 7)
+ xprint()
+
+ def testGHI(self):
+ xprint()
+ res = II(age=7)
+ self.assertEqual(res.age, 7)
+ xprint()
+
+ def testParentDoesNotCrash(self):
+ # This crashed with
+ # TypeError: object.__init__() takes exactly one argument (the instance to initialize)
+ MainWindow()
+
+
+# PYSIDE-2654: Additional missing init test.
+# This must work if no __init__ is defined (Ui_Form)
+class Ui_Form(object):
+ pass
+
+
+class Mixin:
+ def __init__(self, **kwargs) -> None:
+ super().__init__(**kwargs)
+
+
+class Card(Mixin, QWidget):
+ def __init__(self, parent=None) -> None:
+ super().__init__(parent=parent)
+
+
+class Demo(Card, Ui_Form):
+ def __init__(self) -> None:
+ super().__init__()
+
+
+class MissingInitFunctionTest(UsesQApplication):
+ def testMissing(self):
+ Demo()
+ # Tests if this works. Would crash without the extra
+ # check for object.__init__
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/new_inherited_functions_test.py b/sources/pyside6/tests/pysidetest/new_inherited_functions_test.py
new file mode 100644
index 000000000..924a2eea7
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/new_inherited_functions_test.py
@@ -0,0 +1,159 @@
+# 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)
+
+from PySide6 import *
+from PySide6.support.signature import get_signature
+for modname, mod in sys.modules.items():
+ # Python 2 leaves "None" in the dict.
+ if modname.startswith("PySide6.") and mod is not None:
+ print("importing", modname)
+ exec("import " + modname)
+
+# This test tests the existence and callability of the newly existing functions,
+# after the inheritance was made complete in the course of PYSIDE-331.
+
+new_functions = """
+ PySide6.QtCore.QAbstractItemModel().parent()
+ PySide6.QtCore.QAbstractListModel().parent()
+ PySide6.QtCore.QAbstractTableModel().parent()
+ PySide6.QtCore.QFile().resize(qint64)
+ m = PySide6.QtCore.QMutex(); m.tryLock(); m.unlock() # prevent a message "QMutex: destroying locked mutex"
+ PySide6.QtCore.QSortFilterProxyModel().parent()
+ PySide6.QtCore.QTemporaryFile(tfarg).open(openMode)
+"""
+
+new_functions += """
+ PySide6.QtGui.QStandardItemModel().insertColumn(int,qModelIndex)
+ PySide6.QtGui.QStandardItemModel().parent()
+ # PySide6.QtGui.QTextList(qTextDocument).setFormat(qTextFormat) # Segmentation fault: 11
+ # PySide6.QtGui.QTextTable(qTextDocument).setFormat(qTextFormat) # Segmentation fault: 11
+""" if "PySide6.QtGui" in sys.modules else ""
+
+new_functions += """
+ PySide6.QtWidgets.QAbstractItemView().update()
+ PySide6.QtWidgets.QApplication.palette()
+ PySide6.QtWidgets.QApplication.setFont(qFont)
+ PySide6.QtWidgets.QApplication.setPalette(qPalette)
+ PySide6.QtWidgets.QBoxLayout(direction).addWidget(qWidget)
+ PySide6.QtWidgets.QColorDialog().open()
+ PySide6.QtWidgets.QFileDialog().open()
+ PySide6.QtWidgets.QFileSystemModel().index(int,int,qModelIndex)
+ PySide6.QtWidgets.QFileSystemModel().parent()
+ PySide6.QtWidgets.QFontDialog().open()
+ PySide6.QtWidgets.QGestureEvent([]).accept()
+ PySide6.QtWidgets.QGestureEvent([]).ignore()
+ PySide6.QtWidgets.QGestureEvent([]).isAccepted()
+ PySide6.QtWidgets.QGestureEvent([]).setAccepted(bool)
+ # PySide6.QtWidgets.QGraphicsView().render(qPaintDevice,qPoint,qRegion,renderFlags) # QPaintDevice: NotImplementedError
+ PySide6.QtWidgets.QGridLayout().addWidget(qWidget)
+ PySide6.QtWidgets.QInputDialog().open()
+ PySide6.QtWidgets.QLineEdit().addAction(qAction)
+ PySide6.QtWidgets.QMessageBox().open()
+ PySide6.QtWidgets.QPlainTextEdit().find(findStr)
+ PySide6.QtWidgets.QProgressDialog().open()
+ PySide6.QtWidgets.QStackedLayout().widget()
+ # PySide6.QtWidgets.QStylePainter().begin(qPaintDevice) # QPaintDevice: NotImplementedError
+ PySide6.QtWidgets.QTextEdit().find(findStr)
+ PySide6.QtWidgets.QWidget.find(quintptr)
+""" if "PySide6.QtWidgets" in sys.modules else ""
+
+new_functions += """
+ # PySide6.QtPrintSupport.QPageSetupDialog().open() # Segmentation fault: 11
+ # PySide6.QtPrintSupport.QPrintDialog().open() # opens the dialog, but works
+ PySide6.QtPrintSupport.QPrintDialog().printer()
+ PySide6.QtPrintSupport.QPrintPreviewDialog().open() # note: this prints something, but really shouldn't ;-)
+""" if "PySide6.QtPrintSupport" in sys.modules else ""
+
+new_functions += """
+ PySide6.QtHelp.QHelpContentModel().parent()
+ # PySide6.QtHelp.QHelpIndexModel().createIndex(int,int,quintptr) # returned NULL without setting an error
+ # PySide6.QtHelp.QHelpIndexModel().createIndex(int,int,object()) # returned NULL without setting an error
+""" if "PySide6.QtHelp" in sys.modules else ""
+
+new_functions += """
+ PySide6.QtQuick.QQuickPaintedItem().update()
+""" if "PySide6.QtQuick" in sys.modules else ""
+
+
+class MainTest(unittest.TestCase):
+
+ def testNewInheriedFunctionsExist(self):
+ """
+ Run all new method signarures
+ """
+ for app in "QtWidgets.QApplication", "QtGui.QGuiApplication", "QtCore.QCoreApplication":
+ try:
+ exec(f"qApp = PySide6.{app}([]) or PySide6.{app}.instance()")
+ break
+ except AttributeError:
+ continue
+ bool = True
+ int = 42
+ qint64 = 42
+ tfarg = os.path.join(PySide6.QtCore.QDir.tempPath(), "XXXXXX.tmp")
+ findStr = 'bla'
+ orientation = PySide6.QtCore.Qt.Orientations()
+ openMode = PySide6.QtCore.QIODevice.OpenMode(PySide6.QtCore.QIODevice.ReadOnly)
+ qModelIndex = PySide6.QtCore.QModelIndex()
+ transformationMode = PySide6.QtCore.Qt.TransformationMode()
+ qObject = PySide6.QtCore.QObject()
+ qPoint = PySide6.QtCore.QPoint()
+ try:
+ PySide6.QtGui
+ #qPaintDevice = PySide6.QtGui.QPaintDevice() # NotImplementedError
+ qTextDocument = PySide6.QtGui.QTextDocument()
+ qTextFormat = PySide6.QtGui.QTextFormat()
+ quintptr = 42
+ qFont = PySide6.QtGui.QFont()
+ qPalette = PySide6.QtGui.QPalette()
+ except AttributeError:
+ pass
+ try:
+ PySide6.QtWidgets
+ direction = PySide6.QtWidgets.QBoxLayout.Direction()
+ qWidget = PySide6.QtWidgets.QWidget()
+ qStyleOptionFrame = PySide6.QtWidgets.QStyleOptionFrame()
+ qAction = PySide6.QtGui.QAction(qObject)
+ renderFlags = PySide6.QtWidgets.QWidget.RenderFlags
+ except AttributeError:
+ pass
+
+ for func in new_functions.splitlines():
+ func = func.strip()
+ if func.startswith("#"):
+ # this is a crashing or otherwise untestable function
+ print(func)
+ continue
+ try:
+ exec(func)
+ except NotImplementedError:
+ print(func, "# raises NotImplementedError")
+ else:
+ print(func)
+
+ def testQAppSignatures(self):
+ """
+ Verify that qApp.palette owns three signatures, especially
+ palette() without argument.
+ """
+ try:
+ qApp = (PySide6.QtWidgets.QApplication.instance() or
+ PySide6.QtWidgets.QApplication([]))
+ except AttributeError:
+ unittest.TestCase().skipTest("this test makes only sense if QtWidgets is available.")
+
+ sigs = get_signature(PySide6.QtWidgets.QApplication.palette)
+ self.assertEqual(len(sigs), 3)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/notify_id.py b/sources/pyside6/tests/pysidetest/notify_id.py
new file mode 100644
index 000000000..0c4f39f66
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/notify_id.py
@@ -0,0 +1,65 @@
+# 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 gc
+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)
+
+from PySide6.QtCore import QObject, Signal, Property, Slot
+
+'''Tests that the signal notify id of a property is correct, aka corresponds to the initially set
+notify method.'''
+
+
+class Foo(QObject):
+ def __init__(self):
+ super().__init__()
+ self._prop = "Empty"
+
+ def getProp(self):
+ return self._prop
+
+ def setProp(self, value):
+ if value != self._prop:
+ self._prop = value
+ self.propChanged.emit()
+
+ # Inside the dynamic QMetaObject, the methods have to be sorted, so that this slot comes
+ # after any signals. That means the property notify id has to be updated, to have the correct
+ # relative method id.
+ @Slot()
+ def randomSlot():
+ pass
+
+ propChanged = Signal()
+ prop = Property(str, getProp, setProp, notify=propChanged)
+
+
+class NotifyIdSignal(unittest.TestCase):
+ def setUp(self):
+ self.obj = Foo()
+
+ def tearDown(self):
+ del self.obj
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testSignalEmission(self):
+ metaObject = self.obj.metaObject()
+ propertyIndex = metaObject.indexOfProperty("prop")
+ property = metaObject.property(propertyIndex)
+
+ signalIndex = property.notifySignalIndex()
+ signal = metaObject.method(signalIndex)
+ signalName = signal.name()
+ self.assertEqual(signalName, "propChanged")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/properties_test.py b/sources/pyside6/tests/pysidetest/properties_test.py
new file mode 100644
index 000000000..8eb7812d1
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/properties_test.py
@@ -0,0 +1,108 @@
+# 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)
+
+from PySide6.QtCore import QObject, QStringListModel, Signal, Property, Slot
+
+"""Tests PySide6.QtCore.Property()"""
+
+
+class TestObject(QObject):
+
+ valueChanged = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._value = -1
+ self.valueChanged.connect(self._changed)
+ self.getter_called = 0
+ self.setter_called = 0
+ self.changed_emitted = 0
+
+ @Slot(int)
+ def _changed(self):
+ self.changed_emitted += 1
+
+ def getValue(self):
+ self.getter_called += 1
+ return self._value
+
+ def setValue(self, value):
+ self.setter_called += 1
+ if (self._value != value):
+ self._value = value
+ self.valueChanged.emit()
+
+ value = Property(int, fget=getValue, fset=setValue,
+ notify=valueChanged)
+
+
+class TestDerivedObject(QStringListModel):
+
+ valueChanged = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._value = -1
+ self.valueChanged.connect(self._changed)
+ self.getter_called = 0
+ self.setter_called = 0
+ self.changed_emitted = 0
+
+ @Slot(int)
+ def _changed(self):
+ self.changed_emitted += 1
+
+ def getValue(self):
+ self.getter_called += 1
+ return self._value
+
+ def setValue(self, value):
+ self.setter_called += 1
+ if (self._value != value):
+ self._value = value
+ self.valueChanged.emit()
+
+ value = Property(int, fget=getValue, fset=setValue,
+ notify=valueChanged)
+
+
+class PropertyTest(unittest.TestCase):
+
+ def test1Object(self):
+ """Basic property test."""
+ testObject = TestObject()
+ v = testObject.value
+ self.assertEqual(v, -1)
+ self.assertEqual(testObject.getter_called, 1)
+ testObject.value = 42
+ v = testObject.value
+ self.assertEqual(v, 42)
+ self.assertEqual(testObject.changed_emitted, 1)
+ self.assertEqual(testObject.setter_called, 1)
+ self.assertEqual(testObject.getter_called, 2)
+
+ def test2DerivedObject(self):
+ """PYSIDE-1255: Run the same test for a class inheriting QObject."""
+ testObject = TestDerivedObject()
+ v = testObject.value
+ self.assertEqual(v, -1)
+ self.assertEqual(testObject.getter_called, 1)
+ testObject.value = 42
+ v = testObject.value
+ self.assertEqual(v, 42)
+ self.assertEqual(testObject.changed_emitted, 1)
+ self.assertEqual(testObject.setter_called, 1)
+ self.assertEqual(testObject.getter_called, 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/property_python_test.py b/sources/pyside6/tests/pysidetest/property_python_test.py
new file mode 100644
index 000000000..1209aad4f
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/property_python_test.py
@@ -0,0 +1,222 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+"""
+Test for PySide's Property
+==========================
+
+This test is copied from Python's `test_property.py` and adapted to
+the PySide Property implementation.
+
+This test is to ensure maximum compatibility.
+"""
+
+# Test case for property
+# more tests are in test_descr
+
+import gc
+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)
+
+from PySide6.QtCore import Property, QObject
+
+# This are the original imports.
+import sys
+import unittest
+has_test = False
+try:
+ from test import support
+ has_test = True
+except ImportError:
+ pass
+
+
+class PropertyBase(Exception):
+ pass
+
+
+class PropertyGet(PropertyBase):
+ pass
+
+
+class PropertySet(PropertyBase):
+ pass
+
+
+class PropertyDel(PropertyBase):
+ pass
+
+
+class BaseClass(QObject):
+ def __init__(self):
+ super().__init__()
+
+ self._spam = 5
+
+ @Property(object)
+ def spam(self):
+ """BaseClass.getter"""
+ return self._spam
+
+ @spam.setter
+ def spam(self, value):
+ self._spam = value
+
+ @spam.deleter
+ def spam(self):
+ del self._spam
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+
+class SubClass(BaseClass):
+
+ @BaseClass.spam.getter
+ def spam(self):
+ """SubClass.getter"""
+ raise PropertyGet(self._spam)
+
+ @spam.setter
+ def spam(self, value):
+ raise PropertySet(self._spam)
+
+ @spam.deleter
+ def spam(self):
+ raise PropertyDel(self._spam)
+
+
+class PropertyDocBase(object):
+ _spam = 1
+
+ def _get_spam(self):
+ return self._spam
+ spam = Property(object, _get_spam, doc="spam spam spam")
+
+
+class PropertyDocSub(PropertyDocBase):
+ @PropertyDocBase.spam.getter
+ def spam(self):
+ """The decorator does not use this doc string"""
+ return self._spam
+
+
+class PropertySubNewGetter(BaseClass):
+ @BaseClass.spam.getter
+ def spam(self):
+ """new docstring"""
+ return 5
+
+
+class PropertyNewGetter(QObject):
+ def __init__(self):
+ super().__init__()
+
+ @Property(object)
+ def spam(self):
+ """original docstring"""
+ return 1
+
+ @spam.getter
+ def spam(self):
+ """new docstring"""
+ return 8
+
+
+class PropertyTests(unittest.TestCase):
+ def test_property_decorator_baseclass(self):
+ # see #1620
+ base = BaseClass()
+ self.assertEqual(base.spam, 5)
+ self.assertEqual(base._spam, 5)
+ base.spam = 10
+ self.assertEqual(base.spam, 10)
+ self.assertEqual(base._spam, 10)
+ delattr(base, "spam")
+ self.assertTrue(not hasattr(base, "spam"))
+ self.assertTrue(not hasattr(base, "_spam"))
+ base.spam = 20
+ self.assertEqual(base.spam, 20)
+ self.assertEqual(base._spam, 20)
+
+ def test_property_decorator_subclass(self):
+ # see #1620
+ sub = SubClass()
+ self.assertRaises(PropertyGet, getattr, sub, "spam")
+ self.assertRaises(PropertySet, setattr, sub, "spam", None)
+ self.assertRaises(PropertyDel, delattr, sub, "spam")
+
+ @unittest.skipIf(sys.flags.optimize >= 2,
+ "Docstrings are omitted with -O2 and above")
+ def test_property_decorator_subclass_doc(self):
+ sub = SubClass()
+ self.assertEqual(sub.__class__.spam.__doc__, "SubClass.getter")
+
+ @unittest.skipIf(sys.flags.optimize >= 2,
+ "Docstrings are omitted with -O2 and above")
+ def test_property_decorator_baseclass_doc(self):
+ base = BaseClass()
+ self.assertEqual(base.__class__.spam.__doc__, "BaseClass.getter")
+
+ def test_property_decorator_doc(self):
+ base = PropertyDocBase()
+ sub = PropertyDocSub()
+ self.assertEqual(base.__class__.spam.__doc__, "spam spam spam")
+ self.assertEqual(sub.__class__.spam.__doc__, "spam spam spam")
+
+ @unittest.skipIf(sys.flags.optimize >= 2,
+ "Docstrings are omitted with -O2 and above")
+ def test_property_getter_doc_override(self):
+ newgettersub = PropertySubNewGetter()
+ self.assertEqual(newgettersub.spam, 5)
+ self.assertEqual(newgettersub.__class__.spam.__doc__, "new docstring")
+ newgetter = PropertyNewGetter()
+ self.assertEqual(newgetter.spam, 8)
+ self.assertEqual(newgetter.__class__.spam.__doc__, "new docstring")
+
+ @unittest.skipIf(sys.flags.optimize >= 2,
+ "Docstrings are omitted with -O2 and above")
+ def test_property_builtin_doc_writable(self):
+ p = Property(object, doc='basic')
+ self.assertEqual(p.__doc__, 'basic')
+ p.__doc__ = 'extended'
+ self.assertEqual(p.__doc__, 'extended')
+
+ @unittest.skipIf(sys.flags.optimize >= 2,
+ "Docstrings are omitted with -O2 and above")
+ def test_property_decorator_doc_writable(self):
+ class PropertyWritableDoc(object):
+
+ @Property(object)
+ def spam(self):
+ """Eggs"""
+ return "eggs"
+
+ sub = PropertyWritableDoc()
+ self.assertEqual(sub.__class__.spam.__doc__, 'Eggs')
+ sub.__class__.spam.__doc__ = 'Spam'
+ self.assertEqual(sub.__class__.spam.__doc__, 'Spam')
+
+ if has_test: # This test has no support in Python 2
+ @support.refcount_test
+ def test_refleaks_in___init__(self):
+ gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount')
+ fake_prop = Property(object, 'fget', 'fset', "freset", 'fdel', 'doc')
+ refs_before = gettotalrefcount()
+ for i in range(100):
+ fake_prop.__init__(object, 'fget', 'fset', "freset", 'fdel', 'doc')
+ self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10)
+
+
+# Note: We ignore the whole subclass tests concerning __doc__ strings.
+# See the original Python test starting with:
+# "Issue 5890: subclasses of property do not preserve method __doc__ strings"
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/pyenum_relax_options_test.py b/sources/pyside6/tests/pysidetest/pyenum_relax_options_test.py
new file mode 100644
index 000000000..625f9cdc5
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/pyenum_relax_options_test.py
@@ -0,0 +1,136 @@
+#!/usr/bin/python
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+"""
+PYSIDE-1735: Testing different relax options for Enums
+
+This test uses different configurations and initializes QtCore with it.
+Because re-initialization is not possible, the test uses a subprocess
+for it. This makes the test pretty slow.
+
+Maybe we should implement a way to re-initialize QtCore enums without
+using subprocess, just to speed this up??
+"""
+
+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)
+
+import subprocess
+import tempfile
+from textwrap import dedent
+
+
+def runtest(program):
+ passed_path = os.fspath(Path(__file__).resolve().parents[1])
+ with tempfile.NamedTemporaryFile(mode="w+", delete=False, suffix=".py") as fp:
+ preamble = dedent(f"""
+ import os
+ import sys
+ from pathlib import Path
+ sys.path.append({passed_path!r})
+ from init_paths import init_test_paths
+ init_test_paths(False)
+ """)
+ print(preamble, program, file=fp)
+ fp.close()
+ try:
+ subprocess.run([sys.executable, fp.name], check=True, capture_output=True)
+ return True
+ except subprocess.CalledProcessError as e:
+ print(f"\ninfo: {e.__class__.__name__}: {e.stderr}")
+ return False
+ finally:
+ os.unlink(fp.name)
+
+
+def testprog2(option):
+ return runtest(dedent(f"""
+ sys.pyside6_option_python_enum = {option}
+ from PySide6 import QtCore
+ from enum import IntEnum
+ assert(issubclass(QtCore.Qt.DateFormat, IntEnum))
+ """))
+
+
+def testprog4(option):
+ return runtest(dedent(f"""
+ sys.pyside6_option_python_enum = {option}
+ from PySide6 import QtCore
+ QtCore.QtDebugMsg
+ """))
+
+
+def testprog8_16(option):
+ # this test needs flag 16, or the effect would be hidden by forgiving mode
+ return runtest(dedent(f"""
+ sys.pyside6_option_python_enum = {option}
+ from PySide6 import QtCore
+ QtCore.Qt.AlignTop
+ """))
+
+
+def testprog32(option):
+ return runtest(dedent(f"""
+ sys.pyside6_option_python_enum = {option}
+ from PySide6 import QtCore
+ QtCore.Qt.Alignment
+ """))
+
+
+def testprog64(option):
+ return runtest(dedent(f"""
+ sys.pyside6_option_python_enum = {option}
+ from PySide6 import QtCore
+ QtCore.Qt.AlignmentFlag()
+ """))
+
+
+def testprog128(option):
+ return runtest(dedent(f"""
+ sys.pyside6_option_python_enum = {option}
+ from PySide6 import QtCore
+ QtCore.Qt.Key(1234567)
+ """))
+
+
+class TestPyEnumRelaxOption(unittest.TestCase):
+ """
+ This test is a bit involved, because we cannot unload QtCore after it is loaded once.
+ We use subprocess to test different cases, anyway.
+ """
+
+ def test_enumIsIntEnum(self):
+ self.assertTrue(testprog2(2))
+ self.assertFalse(testprog2(4))
+
+ def test_globalDefault(self):
+ self.assertTrue(testprog4(4))
+ self.assertFalse(testprog4(1))
+ self.assertTrue(testprog4(12))
+
+ def test_localDefault(self):
+ self.assertTrue(testprog8_16(8 + 16))
+ self.assertFalse(testprog8_16(0 + 16))
+
+ def test_fakeRenames(self):
+ self.assertTrue(testprog32(1))
+ self.assertFalse(testprog32(32))
+
+ def test_zeroDefault(self):
+ self.assertTrue(testprog64(1))
+ self.assertFalse(testprog64(64))
+
+ def test_Missing(self):
+ self.assertTrue(testprog128(1))
+ self.assertFalse(testprog128(128))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/pysidetest.pyproject b/sources/pyside6/tests/pysidetest/pysidetest.pyproject
new file mode 100644
index 000000000..032d31c6f
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/pysidetest.pyproject
@@ -0,0 +1,33 @@
+{
+ "files": ["all_modules_load_test.py",
+ "bug_1016.py",
+ "constructor_properties_test.py",
+ "container_test.py",
+ "decoratedslot_test.py",
+ "delegatecreateseditor_test.py",
+ "enum_test.py",
+ "homonymoussignalandmethod_test.py",
+ "iterable_test.py",
+ "list_signal_test.py",
+ "mixin_signal_slots_test.py",
+ "mock_as_slot_test.py",
+ "modelview_test.py",
+ "new_inherited_functions_test.py",
+ "notify_id.py",
+ "properties_test.py",
+ "property_python_test.py",
+ "pyenum_relax_options_test.py",
+ "qapp_like_a_macro_test.py",
+ "qvariant_test.py",
+ "repr_test.py",
+ "shared_pointer_test.py",
+ "signal_slot_warning.py",
+ "signal_tp_descr_get_test.py",
+ "signalandnamespace_test.py",
+ "signalemissionfrompython_test.py",
+ "signalinstance_equality_test.py",
+ "signalwithdefaultvalue_test.py",
+ "typedef_signal_test.py",
+ "version_test.py",
+ "typesystem_pysidetest.xml"]
+}
diff --git a/sources/pyside6/tests/pysidetest/pysidetest_global.h b/sources/pyside6/tests/pysidetest/pysidetest_global.h
new file mode 100644
index 000000000..6f784dc58
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/pysidetest_global.h
@@ -0,0 +1,16 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef PYSIDETEST_GLOBAL_H
+#define PYSIDETEST_GLOBAL_H
+
+// PySide global.h file
+#include "containertest.h"
+#include "testobject.h"
+#include "testview.h"
+#include "flagstest.h"
+#include "hiddenobject.h"
+#include "sharedpointertestbench.h"
+#include "testqvariantenum.h"
+
+#endif // PYSIDETEST_GLOBAL_H
diff --git a/sources/pyside6/tests/pysidetest/pysidetest_macros.h b/sources/pyside6/tests/pysidetest/pysidetest_macros.h
new file mode 100644
index 000000000..29bd0dc39
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/pysidetest_macros.h
@@ -0,0 +1,18 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef PYSIDETEST_MACROS_H
+#define PYSIDETEST_MACROS_H
+
+#include <pysidemacros.h>
+
+#define PYSIDETEST_EXPORT PYSIDE_EXPORT
+#define PYSIDETEST_IMPORT PYSIDE_IMPORT
+
+#ifdef BUILD_PYSIDETEST
+# define PYSIDETEST_API PYSIDETEST_EXPORT
+#else
+# define PYSIDETEST_API PYSIDETEST_IMPORT
+#endif
+
+#endif // PYSIDETEST_MACROS_H
diff --git a/sources/pyside6/tests/pysidetest/qapp_like_a_macro_test.py b/sources/pyside6/tests/pysidetest/qapp_like_a_macro_test.py
new file mode 100644
index 000000000..2a3f34014
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/qapp_like_a_macro_test.py
@@ -0,0 +1,68 @@
+# 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)
+
+import PySide6
+
+# This test tests the new "macro" feature of qApp.
+# It also uses the qApp variable to finish the instance and start over.
+
+# Note: this test makes qapplication_singleton_test.py obsolete.
+
+
+class qAppMacroTest(unittest.TestCase):
+ _test_1093_is_first = True
+
+ def test_qApp_is_like_a_macro_and_can_restart(self):
+ self._test_1093_is_first = False
+ from PySide6 import QtCore
+ try:
+ from PySide6 import QtGui, QtWidgets
+ except ImportError:
+ QtWidgets = QtGui = QtCore
+ # qApp is in the builtins
+ self.assertEqual(bool(qApp), False)
+ # and the type is None
+ self.assertTrue(qApp is None)
+ # now we create an application for all cases
+ classes = (QtCore.QCoreApplication,
+ QtGui.QGuiApplication,
+ QtWidgets.QApplication)
+ fil = sys.stderr
+ for klass in classes:
+ print("CREATED", klass([]), file=fil)
+ fil.flush()
+ qApp.shutdown()
+ print("DELETED qApp", qApp, file=fil)
+ fil.flush()
+ # creating without deletion raises:
+ QtCore.QCoreApplication([])
+ with self.assertRaises(RuntimeError):
+ QtCore.QCoreApplication([])
+ self.assertEqual(QtCore.QCoreApplication.instance(), qApp)
+
+ def test_1093(self):
+ # Test that without creating a QApplication staticMetaObject still exists.
+ # Please see https://bugreports.qt.io/browse/PYSIDE-1093 for explanation.
+ # Note: This test must run first, otherwise we would be mislead!
+ assert self._test_1093_is_first
+ from PySide6 import QtCore
+ self.assertTrue(QtCore.QObject.staticMetaObject is not None)
+ app = QtCore.QCoreApplication.instance()
+ self.assertTrue(QtCore.QObject.staticMetaObject is not None)
+ if app is None:
+ app = QtCore.QCoreApplication([])
+ self.assertTrue(QtCore.QObject.staticMetaObject is not None)
+ qApp.shutdown()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/qvariant_test.py b/sources/pyside6/tests/pysidetest/qvariant_test.py
new file mode 100644
index 000000000..faefc8169
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/qvariant_test.py
@@ -0,0 +1,67 @@
+# 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 enum
+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(True)
+
+from testbinding import TestObject, TestQVariantEnum
+from PySide6.QtCore import Qt, QKeyCombination
+from PySide6.QtGui import QKeySequence, QAction
+
+from helper.usesqapplication import UsesQApplication
+
+
+class PyTestQVariantEnum(TestQVariantEnum):
+ def __init__(self, var_enum):
+ super().__init__(var_enum)
+
+ def getRValEnum(self):
+ return Qt.Orientation.Vertical
+
+ def channelingEnum(self, rval_enum):
+ return (isinstance(rval_enum, enum.Enum)
+ and rval_enum == Qt.Orientation.Vertical)
+
+
+class QVariantTest(UsesQApplication):
+
+ def testQKeySequenceQVariantOperator(self):
+ # bug #775
+ ks = QKeySequence(Qt.ShiftModifier, Qt.ControlModifier, Qt.Key_P, Qt.Key_R)
+ self.assertEqual(TestObject.checkType(ks), 4107)
+
+ def testQKeySequenceMoreVariations(self):
+ QAction().setShortcut(Qt.CTRL | Qt.Key_B)
+ QAction().setShortcut(Qt.CTRL | Qt.ALT | Qt.Key_B)
+ QAction().setShortcut(Qt.CTRL | Qt.AltModifier | Qt.Key_B)
+ QAction().setShortcut(QKeySequence(QKeyCombination(Qt.CTRL | Qt.Key_B)))
+ QKeySequence(Qt.CTRL | Qt.Key_Q)
+
+ def testEnum(self):
+ # Testing C++ class
+ testqvariant = TestQVariantEnum(Qt.CheckState.Checked)
+ self.assertEqual(testqvariant.getLValEnum(), Qt.CheckState.Checked)
+ self.assertIsInstance(testqvariant.getLValEnum(), enum.Enum)
+ # in the case where we return a QVariant of C++ enum, it returns a
+ # QVariant(int) to Python unless explicitly handled manually by Shiboken
+ self.assertEqual(testqvariant.getRValEnum(), 1)
+ self.assertEqual(testqvariant.isEnumChanneled(), False)
+
+ # Testing Python child class
+ pytestqvariant = PyTestQVariantEnum(Qt.CheckState.Checked)
+ self.assertEqual(pytestqvariant.isEnumChanneled(), True)
+ # check toInt() conversion works for PyObjectWrapper
+ self.assertEqual(PyTestQVariantEnum.getNumberFromQVarEnum(Qt.Orientation.Vertical), 2)
+ # check toInt() conversion for IntEnum
+ self.assertEqual(PyTestQVariantEnum.getNumberFromQVarEnum(Qt.GestureType.TapGesture), 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/repr_test.py b/sources/pyside6/tests/pysidetest/repr_test.py
new file mode 100644
index 000000000..863f17657
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/repr_test.py
@@ -0,0 +1,64 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2019 Andreas Beckermann
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+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(True)
+
+from testbinding import PySideCPP, TestObject
+
+
+class QObjectDerivedReprTest(unittest.TestCase):
+ """Test the __repr__ implementation of QObject derived classes"""
+
+ def testReprWithoutNamespace(self):
+ """Test that classes outside a namespace that have a operator<<(QDebug,...) defined use that
+ for __repr__"""
+ t = TestObject(123)
+
+ # We don't define __str__, so str(q) should call __repr__
+ self.assertEqual(t.__repr__(), str(t))
+
+ # __repr__ should use the operator<<(QDebug,...) implementation
+ self.assertIn('TestObject(id=123)', str(t))
+
+ def testReprWithNamespace(self):
+ """Test that classes inside a namespace that have a operator<<(QDebug,...) defined use that
+ for __repr__"""
+ t = PySideCPP.TestObjectWithNamespace(None)
+
+ # We don't define __str__, so str(q) should call __repr__
+ self.assertEqual(t.__repr__(), str(t))
+
+ # __repr__ should use the operator<<(QDebug,...) implementation
+ self.assertIn('TestObjectWithNamespace("TestObjectWithNamespace")', str(t))
+
+ def testReprInject(self):
+ """Test that injecting __repr__ via typesystem overrides the operator<<(QDebug, ...)"""
+ t = PySideCPP.TestObject2WithNamespace(None)
+
+ # We don't define __str__, so str(q) should call __repr__
+ self.assertEqual(t.__repr__(), str(t))
+
+ # __repr__ should use the operator<<(QDebug,...) implementation
+ self.assertEqual(str(t), "TestObject2WithNamespace(injected_repr)")
+
+ def testLatin1StringField(self):
+ self.assertEqual(TestObject.LATIN1_TEST_FIELD, "test")
+
+ def testLatin1Setter(self):
+ to = TestObject(123)
+ value = "test"
+ to.setQLatin1String(value)
+ self.assertEqual(to.qLatin1String(), value)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/pysidetest/shared_pointer_test.py b/sources/pyside6/tests/pysidetest/shared_pointer_test.py
new file mode 100644
index 000000000..6f49d69b1
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/shared_pointer_test.py
@@ -0,0 +1,54 @@
+# 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 gc
+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(True)
+
+from PySide6.QtCore import QObject
+
+from testbinding import SharedPointerTestbench, QSharedPointer_QObject
+
+
+def create_qobject(name):
+ result = QObject()
+ result.setObjectName(name)
+ return result
+
+
+class SharedPointerTests(unittest.TestCase):
+
+ def testObjSharedPointer(self):
+ p = SharedPointerTestbench.createSharedPointerQObject()
+ self.assertEqual(p.objectName(), "TestObject")
+ SharedPointerTestbench.printSharedPointerQObject(p)
+ p = SharedPointerTestbench.createSharedPointerConstQObject()
+ SharedPointerTestbench.printSharedPointerConstQObject(p)
+
+ def testIntSharedPointer(self):
+ p = SharedPointerTestbench.createSharedPointerInt(42)
+ SharedPointerTestbench.printSharedPointerInt(p)
+
+ def testConstruction(self):
+ name1 = "CreatedQObject1"
+ p1 = QSharedPointer_QObject(create_qobject(name1))
+ self.assertTrue(p1)
+ self.assertEqual(p1.objectName(), name1)
+
+ p1.reset()
+ self.assertFalse(p1)
+
+ name2 = "CreatedQObject2"
+ p1.reset(create_qobject(name2))
+ self.assertTrue(p1)
+ self.assertEqual(p1.objectName(), name2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/sharedpointertestbench.cpp b/sources/pyside6/tests/pysidetest/sharedpointertestbench.cpp
new file mode 100644
index 000000000..44c2a4fe0
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/sharedpointertestbench.cpp
@@ -0,0 +1,46 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "sharedpointertestbench.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QDebug>
+
+using namespace Qt::StringLiterals;
+
+SharedPointerTestbench::SharedPointerTestbench() = default;
+
+QSharedPointer<int> SharedPointerTestbench::createSharedPointerInt(int v)
+{
+ return QSharedPointer<int>(new int(v));
+}
+
+void SharedPointerTestbench::printSharedPointerInt(const QSharedPointer<int> &p)
+{
+ qDebug() << __FUNCTION__ << *p;
+}
+
+QSharedPointer<QObject> SharedPointerTestbench::createSharedPointerQObject()
+{
+ QSharedPointer<QObject> result(new QObject);
+ result->setObjectName(u"TestObject"_s);
+ return result;
+}
+
+void SharedPointerTestbench::printSharedPointerQObject(const QSharedPointer<QObject> &p)
+{
+ qDebug() << __FUNCTION__ << p.data();
+}
+
+QSharedPointer<const QObject> SharedPointerTestbench::createSharedPointerConstQObject()
+{
+ auto *o = new QObject;
+ o->setObjectName(u"ConstTestObject"_s);
+ QSharedPointer<const QObject> result(o);
+ return result;
+}
+
+void SharedPointerTestbench::printSharedPointerConstQObject(const QSharedPointer<const QObject> &p)
+{
+ qDebug() << __FUNCTION__ << p.data();
+}
diff --git a/sources/pyside6/tests/pysidetest/sharedpointertestbench.h b/sources/pyside6/tests/pysidetest/sharedpointertestbench.h
new file mode 100644
index 000000000..b23fd1b6c
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/sharedpointertestbench.h
@@ -0,0 +1,29 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef SHAREDPOINTERTESTBENCH_H
+#define SHAREDPOINTERTESTBENCH_H
+
+#include "pysidetest_macros.h"
+
+#include <QtCore/QSharedPointer>
+
+QT_FORWARD_DECLARE_CLASS(QObject)
+
+class PYSIDETEST_API SharedPointerTestbench
+{
+public:
+ SharedPointerTestbench();
+
+ static QSharedPointer<int> createSharedPointerInt(int v);
+ static void printSharedPointerInt(const QSharedPointer<int> &p);
+
+ static QSharedPointer<QObject> createSharedPointerQObject();
+ static void printSharedPointerQObject(const QSharedPointer<QObject> &p);
+
+ static QSharedPointer<const QObject> createSharedPointerConstQObject();
+ static void printSharedPointerConstQObject(const QSharedPointer<const QObject> &p);
+
+};
+
+#endif // SHAREDPOINTERTESTBENCH_H
diff --git a/sources/pyside6/tests/pysidetest/signal_slot_warning.py b/sources/pyside6/tests/pysidetest/signal_slot_warning.py
new file mode 100644
index 000000000..b94281643
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/signal_slot_warning.py
@@ -0,0 +1,50 @@
+#!/usr/bin/python
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+''' PYSIDE-315: https://bugreports.qt.io/browse/PYSIDE-315
+ Test that creating a signal in the wrong order triggers a warning. '''
+
+import os
+import sys
+import unittest
+import warnings
+
+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)
+
+import PySide6.QtCore as QtCore
+
+
+class Whatever(QtCore.QObject):
+ echoSignal = QtCore.Signal(str)
+
+ def __init__(self):
+ super().__init__()
+ self.echoSignal.connect(self.mySlot)
+
+ def mySlot(self, v):
+ pass
+
+
+class WarningTest(unittest.TestCase):
+ def testSignalSlotWarning(self):
+ # we create an object. This gives no warning.
+ obj = Whatever()
+ # then we insert a signal after slots have been created.
+ setattr(Whatever, "foo", QtCore.Signal())
+ with warnings.catch_warnings(record=True) as w:
+ # Cause all warnings to always be triggered.
+ warnings.simplefilter("always")
+ # Trigger a warning.
+ obj.foo.connect(obj.mySlot)
+ # Verify some things
+ assert issubclass(w[-1].category, RuntimeWarning)
+ assert "*** Sort Warning ***" in str(w[-1].message)
+ # note that this warning cannot be turned into an error (too hard)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/signal_tp_descr_get_test.py b/sources/pyside6/tests/pysidetest/signal_tp_descr_get_test.py
new file mode 100644
index 000000000..6025d119d
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/signal_tp_descr_get_test.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+"""
+PYSIDE-68: Test that signals have a `__get__` function after all.
+
+We supply a `tp_descr_get` slot for the signal type.
+That creates the `__get__` method via `PyType_Ready`.
+
+The original test script was converted to a unittest.
+See https://bugreports.qt.io/browse/PYSIDE-68 .
+
+Created: 16 May '12 21:25
+Updated: 17 Sep '20 17:02
+
+This fix was over 8 years late. :)
+"""
+
+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)
+
+from PySide6.QtCore import QObject, Signal
+
+
+def emit_upon_success(signal):
+ def f_(f):
+ def f__(self):
+ result = f(self)
+ s = signal.__get__(self)
+ print(result)
+ return result
+ return f__
+ return f_
+
+
+class Foo(QObject):
+ SIG = Signal()
+
+ @emit_upon_success(SIG)
+ def do_something(self):
+ print("hooka, it worrrks")
+ return 42
+
+
+class UnderUnderGetUnderUnderTest(unittest.TestCase):
+ def test_tp_descr_get(self):
+ foo = Foo()
+ ret = foo.do_something()
+ self.assertEqual(ret, 42)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/signalandnamespace_test.py b/sources/pyside6/tests/pysidetest/signalandnamespace_test.py
new file mode 100644
index 000000000..3e91ca338
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/signalandnamespace_test.py
@@ -0,0 +1,103 @@
+#!/usr/bin/python
+# 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(True)
+
+from testbinding import PySideCPP, TestObjectWithoutNamespace
+
+
+class ModelViewTest(unittest.TestCase):
+
+ def callback(self, o):
+ self._called = o
+
+ def testWithoutNamespace(self):
+ self._called = None
+ o = PySideCPP.TestObjectWithNamespace(None)
+ o.emitSignal.connect(self.callback)
+ o.emitSignal.emit(o)
+ self.assertTrue(o == self._called)
+
+ self._called = None
+ o = PySideCPP.TestObjectWithNamespace(None)
+ o.emitSignal.connect(self.callback)
+ o.callSignal(o)
+ self.assertTrue(o == self._called)
+
+ def testWithNamespace(self):
+ self._called = None
+ o = PySideCPP.TestObjectWithNamespace(None)
+ o.emitSignalWithNamespace.connect(self.callback)
+ o.emitSignalWithNamespace.emit(o)
+ self.assertTrue(o == self._called)
+
+ self._called = None
+ o = PySideCPP.TestObjectWithNamespace(None)
+ o.emitSignalWithNamespace.connect(self.callback)
+ o.callSignalWithNamespace(o)
+ self.assertTrue(o == self._called)
+
+ def testWithoutNamespace1(self):
+ self._called = None
+ o = TestObjectWithoutNamespace(None)
+ o.emitSignal.connect(self.callback)
+ o.emitSignal.emit(o)
+ self.assertTrue(o == self._called)
+
+ self._called = None
+ o = TestObjectWithoutNamespace(None)
+ o.emitSignal.connect(self.callback)
+ o.callSignal(o)
+ self.assertTrue(o == self._called)
+
+ def testWithNamespace1(self):
+ self._called = None
+ o = TestObjectWithoutNamespace(None)
+ o.emitSignalWithNamespace.connect(self.callback)
+ o.emitSignalWithNamespace.emit(o)
+ self.assertTrue(o == self._called)
+
+ self._called = None
+ o = TestObjectWithoutNamespace(None)
+ o.emitSignalWithNamespace.connect(self.callback)
+ o.callSignalWithNamespace(o)
+ self.assertTrue(o == self._called)
+
+ def testTypedfWithouNamespace(self):
+ self._called = None
+ o = PySideCPP.TestObjectWithNamespace(None)
+ o.emitSignalWithTypedef.connect(self.callback)
+ o.emitSignalWithTypedef.emit(10)
+ self.assertEqual(10, self._called)
+
+ self._called = None
+ o = PySideCPP.TestObjectWithNamespace(None)
+ o.emitSignalWithTypedef.connect(self.callback)
+ o.callSignalWithTypedef(10)
+ self.assertEqual(10, self._called)
+
+ def testTypedefWithNamespace(self):
+ self._called = None
+ o = TestObjectWithoutNamespace(None)
+ o.emitSignalWithTypedef.connect(self.callback)
+ o.emitSignalWithTypedef.emit(10)
+ self.assertEqual(10, self._called)
+
+ self._called = None
+ o = TestObjectWithoutNamespace(None)
+ o.emitSignalWithTypedef.connect(self.callback)
+ o.callSignalWithTypedef(10)
+ self.assertEqual(10, self._called)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/pysidetest/signalemissionfrompython_test.py b/sources/pyside6/tests/pysidetest/signalemissionfrompython_test.py
new file mode 100644
index 000000000..70c9e0082
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/signalemissionfrompython_test.py
@@ -0,0 +1,96 @@
+#!/usr/bin/python
+# 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 gc
+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(True)
+
+from testbinding import TestObject
+from PySide6.QtCore import QObject, SIGNAL
+
+'''Tests the behaviour of signals with default values when emitted from Python.'''
+
+
+class SignalEmissionFromPython(unittest.TestCase):
+
+ def setUp(self):
+ self.obj1 = TestObject(0)
+ self.obj2 = TestObject(0)
+ self.one_called = 0
+ self.two_called = 0
+
+ def tearDown(self):
+ del self.obj1
+ del self.obj2
+ del self.one_called
+ del self.two_called
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testConnectNewStyleEmitVoidSignal(self):
+ def callbackOne():
+ self.one_called += 1
+ self.obj2.signalWithDefaultValue.emit()
+
+ def callbackTwo():
+ self.two_called += 1
+ self.obj1.signalWithDefaultValue.connect(callbackOne)
+ self.obj2.signalWithDefaultValue.connect(callbackTwo)
+ self.obj1.emitSignalWithDefaultValue_void()
+ self.obj2.emitSignalWithDefaultValue_void()
+ self.assertEqual(self.one_called, 1)
+ self.assertEqual(self.two_called, 2)
+
+ def testConnectOldStyleEmitVoidSignal(self):
+ def callbackOne():
+ self.one_called += 1
+ self.obj2.signalWithDefaultValue.emit()
+
+ def callbackTwo():
+ self.two_called += 1
+ self.obj1.signalWithDefaultValue.connect(callbackOne)
+ self.obj2.signalWithDefaultValue.connect(callbackTwo)
+ self.obj1.emitSignalWithDefaultValue_void()
+ self.obj2.emitSignalWithDefaultValue_void()
+ self.assertEqual(self.one_called, 1)
+ self.assertEqual(self.two_called, 2)
+
+ def testConnectNewStyleEmitBoolSignal(self):
+ def callbackOne():
+ self.one_called += 1
+ self.obj2.signalWithDefaultValue[bool].emit(True)
+
+ def callbackTwo():
+ self.two_called += 1
+ self.obj1.signalWithDefaultValue.connect(callbackOne)
+ self.obj2.signalWithDefaultValue.connect(callbackTwo)
+ self.obj1.emitSignalWithDefaultValue_void()
+ self.obj2.emitSignalWithDefaultValue_void()
+ self.assertEqual(self.one_called, 1)
+ self.assertEqual(self.two_called, 2)
+
+ def testConnectOldStyleEmitBoolSignal(self):
+ def callbackOne():
+ self.one_called += 1
+ self.obj2.signalWithDefaultValue[bool].emit(True)
+
+ def callbackTwo():
+ self.two_called += 1
+ self.obj1.signalWithDefaultValue.connect(callbackOne)
+ self.obj2.signalWithDefaultValue.connect(callbackTwo)
+ self.obj1.emitSignalWithDefaultValue_void()
+ self.obj2.emitSignalWithDefaultValue_void()
+ self.assertEqual(self.one_called, 1)
+ self.assertEqual(self.two_called, 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/pysidetest/signalinstance_equality_test.py b/sources/pyside6/tests/pysidetest/signalinstance_equality_test.py
new file mode 100644
index 000000000..5faaa38d4
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/signalinstance_equality_test.py
@@ -0,0 +1,85 @@
+# 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)
+
+from helper.usesqapplication import UsesQApplication
+
+from PySide6.QtCore import QFile, QObject, QTimer, Signal, SignalInstance, Slot
+from PySide6.QtWidgets import QSlider
+
+
+class C(QObject):
+ custom_signal = Signal()
+
+
+class D(C):
+ pass
+
+
+class TestSignalInstance(unittest.TestCase):
+ def test_signal_instances_are_equal(self):
+ o = QTimer()
+ self.assertTrue(o.timeout == o.timeout)
+
+ def test_inherited_signal_instances_are_equal(self):
+ o = QFile()
+ self.assertTrue(o.readyRead == o.readyRead)
+
+ def test_custom_signal_instances_are_equal(self):
+ o = C()
+ self.assertTrue(o.custom_signal == o.custom_signal)
+
+ def test_custom_inherited_signal_instances_are_equal(self):
+ o = D()
+ self.assertTrue(o.custom_signal == o.custom_signal)
+
+ # additional tests of old errors from 2010 or so
+ def test_uninitialized_SignalInstance(self):
+ # This will no longer crash
+ print(SignalInstance())
+ with self.assertRaises(RuntimeError):
+ SignalInstance().connect(lambda: None)
+ with self.assertRaises(RuntimeError):
+ SignalInstance().disconnect()
+ with self.assertRaises(RuntimeError):
+ SignalInstance().emit()
+
+
+class MyWidget(QSlider):
+ valueChanged = Signal(tuple)
+
+ def __init__(self):
+ super().__init__()
+ self.valueChanged.connect(self._on_change)
+
+ def setValue(self, value):
+ self.valueChanged.emit(value)
+
+ @Slot()
+ def _on_change(self, new_value):
+ print("new_value:", new_value)
+ global result
+ result = new_value
+
+
+class TestRightOrder(UsesQApplication):
+ def test_rightOrder(self):
+ wdg = MyWidget()
+
+ # PYSIDE-1751: Fixes the wrong behavior we got on >=6.2
+ # PySide <=6.1.3 prints "new_value: (30, 40)"
+ # PySide >=6.2 prints "new_value: 0"
+ wdg.setValue((30, 40))
+ self.assertEqual(result, (30, 40))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/signalwithdefaultvalue_test.py b/sources/pyside6/tests/pysidetest/signalwithdefaultvalue_test.py
new file mode 100644
index 000000000..744b8c503
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/signalwithdefaultvalue_test.py
@@ -0,0 +1,96 @@
+#!/usr/bin/python
+# 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 gc
+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(True)
+
+from testbinding import TestObject
+from PySide6.QtCore import Qt
+
+'''Tests the behaviour of signals with default values.'''
+
+
+class SignalWithDefaultValueTest(unittest.TestCase):
+
+ def setUp(self):
+ self.obj = TestObject(0)
+ self.void_called = False
+ self.bool_called = False
+
+ def tearDown(self):
+ del self.obj
+ del self.void_called
+ del self.bool_called
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testConnectNewStyleEmitVoidSignal(self):
+ def callbackVoid():
+ self.void_called = True
+
+ def callbackBool(value):
+ self.bool_called = True
+ self.obj.signalWithDefaultValue.connect(callbackVoid)
+ self.obj.signalWithDefaultValue[bool].connect(callbackBool)
+ self.obj.emitSignalWithDefaultValue_void()
+ self.assertTrue(self.void_called)
+ self.assertTrue(self.bool_called)
+
+ def testConnectNewStyleEmitBoolSignal(self):
+ def callbackVoid():
+ self.void_called = True
+
+ def callbackBool(value):
+ self.bool_called = True
+ self.obj.signalWithDefaultValue.connect(callbackVoid)
+ self.obj.signalWithDefaultValue[bool].connect(callbackBool)
+ self.obj.emitSignalWithDefaultValue_bool()
+ self.assertTrue(self.void_called)
+ self.assertTrue(self.bool_called)
+
+ def testFlagsSignal(self):
+ test_value = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignBottom
+
+ def callbackAlignmentFlags(alignment):
+ self.alignment_flags_called = alignment
+
+ self.obj.flagsSignal.connect(callbackAlignmentFlags)
+ self.obj.emitFlagsSignal(test_value)
+ self.assertTrue(self.alignment_flags_called)
+ self.assertEqual(self.alignment_flags_called, test_value)
+
+ def testConnectOldStyleEmitVoidSignal(self):
+ def callbackVoid():
+ self.void_called = True
+
+ def callbackBool(value):
+ self.bool_called = True
+ self.obj.signalWithDefaultValue.connect(callbackVoid)
+ self.obj.signalWithDefaultValue.connect(callbackBool)
+ self.obj.emitSignalWithDefaultValue_void()
+ self.assertTrue(self.void_called)
+ self.assertTrue(self.bool_called)
+
+ def testConnectOldStyleEmitBoolSignal(self):
+ def callbackVoid():
+ self.void_called = True
+
+ def callbackBool(value):
+ self.bool_called = True
+ self.obj.signalWithDefaultValue.connect(callbackVoid)
+ self.obj.signalWithDefaultValue.connect(callbackBool)
+ self.obj.emitSignalWithDefaultValue_bool()
+ self.assertTrue(self.void_called)
+ self.assertTrue(self.bool_called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/snake_case_sub.py b/sources/pyside6/tests/pysidetest/snake_case_sub.py
new file mode 100644
index 000000000..4a482c35a
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/snake_case_sub.py
@@ -0,0 +1,23 @@
+# 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-2029: Tests that snake_case is isolated from imported modules
+"""
+
+from PySide6.QtWidgets import QWidget
+
+
+def test_no_snake_case():
+ print(__name__)
+ widget = QWidget()
+ check = widget.sizeHint
diff --git a/sources/pyside6/tests/pysidetest/snake_case_test.py b/sources/pyside6/tests/pysidetest/snake_case_test.py
new file mode 100644
index 000000000..14e035773
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/snake_case_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-2029: Tests that snake_case is isolated from imported modules
+"""
+is_pypy = hasattr(sys, "pypy_version_info")
+
+from PySide6.QtCore import QSize
+from PySide6.QtWidgets import QWidget, QSpinBox
+if not is_pypy:
+ from __feature__ import snake_case
+from helper.usesqapplication import UsesQApplication
+
+import snake_case_sub
+
+@unittest.skipIf(is_pypy, "__feature__ cannot yet be used with PyPy")
+class SnakeCaseNoPropagateTest(UsesQApplication):
+
+ def testSnakeCase(self):
+ # this worked
+ widget = QWidget()
+ check = widget.size_hint
+
+ snake_case_sub.test_no_snake_case()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/symbols.filter b/sources/pyside6/tests/pysidetest/symbols.filter
new file mode 100644
index 000000000..af6c744dd
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/symbols.filter
@@ -0,0 +1,7 @@
+{
+local:
+_ZSt*;
+_ZNSt*;
+_ZNSs*;
+_ZNKSt*;
+};
diff --git a/sources/pyside6/tests/pysidetest/testobject.cpp b/sources/pyside6/tests/pysidetest/testobject.cpp
new file mode 100644
index 000000000..fe4ec98f7
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/testobject.cpp
@@ -0,0 +1,73 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "testobject.h"
+
+#include <QtCore/QDebug>
+
+void TestObject::emitIdValueSignal()
+{
+ emit idValue(m_idValue);
+}
+
+void TestObject::emitStaticMethodDoubleSignal()
+{
+ emit staticMethodDouble();
+}
+
+void TestObject::emitSignalWithDefaultValue_void()
+{
+ emit signalWithDefaultValue();
+}
+
+void TestObject::emitSignalWithDefaultValue_bool()
+{
+ emit signalWithDefaultValue(true);
+}
+
+void TestObject::emitSignalWithTypedefValue(int value)
+{
+ emit signalWithTypedefValue(TypedefValue(value));
+}
+
+void TestObject::emitSignalWithContainerTypedefValue(const IntList &il)
+{
+ emit signalWithContainerTypedefValue(il);
+}
+
+void TestObject::emitFlagsSignal(Qt::Alignment alignment)
+{
+ emit flagsSignal(alignment);
+}
+
+void TestObject::setQLatin1String(QLatin1String v)
+{
+ m_qLatin1String = v;
+}
+
+QString TestObject::qLatin1String() const
+{
+ return m_qLatin1String;
+}
+
+QDebug operator<<(QDebug dbg, TestObject& testObject)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "TestObject(id=" << testObject.idValue() << ") ";
+ return dbg;
+}
+
+namespace PySideCPP {
+ QDebug operator<<(QDebug dbg, TestObjectWithNamespace& testObject)
+ {
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "TestObjectWithNamespace(" << testObject.name() << ") ";
+ return dbg;
+ }
+ QDebug operator<<(QDebug dbg, TestObject2WithNamespace& testObject)
+ {
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "TestObject2WithNamespace(" << testObject.name() << ") ";
+ return dbg;
+ }
+}
diff --git a/sources/pyside6/tests/pysidetest/testobject.h b/sources/pyside6/tests/pysidetest/testobject.h
new file mode 100644
index 000000000..a095a382e
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/testobject.h
@@ -0,0 +1,140 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef TESTOBJECT_H
+#define TESTOBJECT_H
+
+#include "pysidetest_macros.h"
+
+#include <QtWidgets/QApplication>
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QMetaType>
+#include <QtCore/QVariant>
+
+QT_FORWARD_DECLARE_CLASS(QDebug)
+
+using IntList = QList<int>;
+
+class IntValue
+{
+public:
+
+ IntValue(int val): value(val){};
+ IntValue() : value(0) {};
+ int value;
+};
+
+using TypedefValue = IntValue;
+
+class PYSIDETEST_API TestObject : public QObject
+{
+ Q_OBJECT
+public:
+ static void createApp() { int argc=0; new QApplication(argc, nullptr); };
+ static int checkType(const QVariant& var) { return var.metaType().id(); }
+
+ TestObject(int idValue, QObject* parent = nullptr) : QObject(parent), m_idValue(idValue) {}
+ int idValue() const { return m_idValue; }
+ static int staticMethodDouble(int value) { return value * 2; }
+ void addChild(QObject* c) { m_children.append(c); emit childrenChanged(m_children); }
+
+ void emitIdValueSignal();
+ void emitStaticMethodDoubleSignal();
+
+ void emitSignalWithDefaultValue_void();
+ void emitSignalWithDefaultValue_bool();
+
+ void emitSignalWithTypedefValue(int value);
+ void emitSignalWithContainerTypedefValue(const IntList &il);
+
+ void emitFlagsSignal(Qt::Alignment alignment);
+
+ static constexpr auto LATIN1_TEST_FIELD = QLatin1StringView("test");
+
+ void setQLatin1String(QLatin1String v);
+ QString qLatin1String() const;
+
+signals:
+ void idValue(int newValue);
+ void justASignal();
+ void staticMethodDouble();
+ void childrenChanged(const QList<QObject*>&);
+ void signalWithDefaultValue(bool value = false);
+ void signalWithTypedefValue(TypedefValue value);
+ void signalWithContainerTypedefValue(const IntList &il);
+ void flagsSignal(Qt::Alignment alignment);
+
+private:
+ int m_idValue;
+ QList<QObject*> m_children;
+ QString m_qLatin1String;
+};
+
+PYSIDETEST_API QDebug operator<<(QDebug dbg, TestObject &testObject);
+
+using PySideInt = int;
+
+namespace PySideCPP {
+
+class PYSIDETEST_API TestObjectWithNamespace : public QObject
+{
+ Q_OBJECT
+public:
+ TestObjectWithNamespace(QObject* parent) : QObject(parent) {}
+ QString name() { return QStringLiteral("TestObjectWithNamespace"); }
+
+ void callSignal(TestObjectWithNamespace* obj) { emit emitSignal(obj); }
+ void callSignalWithNamespace(TestObjectWithNamespace* obj) { emit emitSignalWithNamespace(obj); }
+ void callSignalWithTypedef(int val) { emit emitSignalWithTypedef(val); }
+
+signals:
+ void emitSignal(TestObjectWithNamespace* obj);
+ void emitSignalWithNamespace(PySideCPP::TestObjectWithNamespace* obj);
+ void emitSignalWithTypedef(PySideInt val);
+};
+
+PYSIDETEST_API QDebug operator<<(QDebug dbg, TestObjectWithNamespace &testObject);
+
+class PYSIDETEST_API TestObject2WithNamespace : public QObject
+{
+ Q_OBJECT
+public:
+ TestObject2WithNamespace(QObject* parent) : QObject(parent) {}
+ QString name() { return QStringLiteral("TestObject2WithNamespace"); }
+};
+
+PYSIDETEST_API QDebug operator<<(QDebug dbg, TestObject2WithNamespace& testObject);
+
+} // Namespace PySideCPP
+
+namespace PySideCPP2 {
+
+enum Enum1 { Option1 = 1, Option2 = 2 };
+
+using PySideLong = long;
+
+class PYSIDETEST_API TestObjectWithoutNamespace : public QObject
+{
+ Q_OBJECT
+public:
+ enum Enum2 { Option3 = 3, Option4 = 4};
+ TestObjectWithoutNamespace(QObject* parent) : QObject(parent) {}
+ QString name() { return QStringLiteral("TestObjectWithoutNamespace"); }
+
+ void callSignal(TestObjectWithoutNamespace* obj) { emitSignal(obj); }
+ void callSignalWithNamespace(TestObjectWithoutNamespace* obj) { emitSignalWithNamespace(obj); }
+ void callSignalWithTypedef(long val) { emitSignalWithTypedef(val); }
+
+signals:
+ void emitSignal(TestObjectWithoutNamespace* obj);
+ void emitSignalWithNamespace(PySideCPP2::TestObjectWithoutNamespace* obj);
+ void emitSignalWithTypedef(PySideLong val);
+};
+
+
+} // Namespace PySideCPP2
+
+#endif // TESTOBJECT_H
+
diff --git a/sources/pyside6/tests/pysidetest/testqvariantenum.cpp b/sources/pyside6/tests/pysidetest/testqvariantenum.cpp
new file mode 100644
index 000000000..7135e422a
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/testqvariantenum.cpp
@@ -0,0 +1,29 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "testqvariantenum.h"
+
+QVariant TestQVariantEnum::getLValEnum() const
+{
+ return this->m_enum;
+}
+
+QVariant TestQVariantEnum::getRValEnum() const
+{
+ return QVariant(Qt::Orientation::Horizontal);
+}
+
+int TestQVariantEnum::getNumberFromQVarEnum(QVariant variantEnum)
+{
+ return variantEnum.toInt();
+}
+
+bool TestQVariantEnum::channelingEnum([[maybe_unused]] QVariant rvalEnum) const
+{
+ return false;
+}
+
+bool TestQVariantEnum::isEnumChanneled() const
+{
+ return this->channelingEnum(this->getRValEnum());
+}
diff --git a/sources/pyside6/tests/pysidetest/testqvariantenum.h b/sources/pyside6/tests/pysidetest/testqvariantenum.h
new file mode 100644
index 000000000..4b729e3dd
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/testqvariantenum.h
@@ -0,0 +1,35 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef TESTQVARIANT_H
+#define TESTQVARIANT_H
+
+#include "pysidetest_macros.h"
+
+#include <QtCore/QVariant>
+
+class PYSIDETEST_API TestQVariantEnum
+{
+public:
+ TestQVariantEnum(QVariant lvalue_enum) : m_enum(lvalue_enum) {}
+ QVariant getLValEnum() const;
+ static int getNumberFromQVarEnum(QVariant variantEnum = QVariant());
+ bool isEnumChanneled() const;
+ virtual QVariant getRValEnum() const;
+ virtual bool channelingEnum(QVariant rvalEnum) const;
+ virtual ~TestQVariantEnum() = default;
+private:
+ QVariant m_enum;
+};
+
+class PYSIDETEST_API QVariantHolder // modeled after Q3DParameter, test QVariant conversion
+{
+public:
+ void setValue(QVariant v) { m_variant = v; }
+ QVariant value() const { return m_variant; }
+
+private:
+ QVariant m_variant;
+};
+
+#endif // TESTQVARIANT_H
diff --git a/sources/pyside6/tests/pysidetest/testview.cpp b/sources/pyside6/tests/pysidetest/testview.cpp
new file mode 100644
index 000000000..362239112
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/testview.cpp
@@ -0,0 +1,27 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "testview.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QAbstractListModel>
+#include <QtWidgets/QAbstractItemDelegate>
+#include <QtWidgets/QWidget>
+
+QVariant
+TestView::getData()
+{
+ QModelIndex index;
+ return m_model->data(index);
+}
+
+QWidget*
+TestView::getEditorWidgetFromItemDelegate() const
+{
+ if (m_delegate == nullptr)
+ return nullptr;
+
+ QModelIndex index;
+ QStyleOptionViewItem options;
+ return m_delegate->createEditor(nullptr, options, index);
+}
diff --git a/sources/pyside6/tests/pysidetest/testview.h b/sources/pyside6/tests/pysidetest/testview.h
new file mode 100644
index 000000000..746def83e
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/testview.h
@@ -0,0 +1,35 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef TESTVIEW_H
+#define TESTVIEW_H
+
+#include "pysidetest_macros.h"
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+class QWidget;
+class QAbstractListModel;
+class QAbstractItemDelegate;
+QT_END_NAMESPACE
+
+class PYSIDETEST_API TestView : public QObject
+{
+ Q_OBJECT
+public:
+ TestView(QAbstractListModel* model, QObject* parent = nullptr) :
+ QObject(parent), m_model(model) {}
+ QAbstractListModel* model() { return m_model; }
+ QVariant getData();
+
+ void setItemDelegate(QAbstractItemDelegate* delegate) { m_delegate = delegate; }
+ QWidget* getEditorWidgetFromItemDelegate() const;
+
+private:
+ QAbstractListModel* m_model;
+ QAbstractItemDelegate* m_delegate = nullptr;
+};
+
+#endif // TESTVIEW_H
+
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..62f6505dc
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/true_property_test.py
@@ -0,0 +1,58 @@
+# 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
+"""
+is_pypy = hasattr(sys, "pypy_version_info")
+
+from PySide6.QtCore import QSize
+from PySide6.QtWidgets import QWidget, QSpinBox
+if not is_pypy:
+ from __feature__ import true_property
+from helper.usesqapplication import UsesQApplication
+
+
+@unittest.skipIf(is_pypy, "__feature__ cannot yet be used with PyPy")
+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)
+
+ def testHiddenMethods(self):
+ # PYSIDE-1889: setVisible is no longer a meta function but comes from the Property
+ widget = QWidget()
+ self.assertTrue("visible" in QWidget.__dict__)
+ self.assertFalse("isVisible" in QWidget.__dict__)
+ self.assertFalse("setVisible" in QWidget.__dict__)
+ self.assertTrue(hasattr(widget, "isVisible"))
+ self.assertTrue(hasattr(widget, "setVisible"))
+ self.assertEqual(widget.isVisible, QWidget.visible.fget)
+ self.assertEqual(widget.setVisible, QWidget.visible.fset)
+
+ # This works with inheritance as well:
+ class SubClass(QWidget):
+ pass
+ sub_widget = SubClass()
+ self.assertEqual(sub_widget.isVisible, QWidget.visible.fget)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/typedef_signal_test.py b/sources/pyside6/tests/pysidetest/typedef_signal_test.py
new file mode 100644
index 000000000..d0bdc880b
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/typedef_signal_test.py
@@ -0,0 +1,52 @@
+# 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(True)
+
+from PySide6.QtCore import QObject, Slot
+from testbinding import TestObject
+
+
+class Receiver(QObject):
+
+ def __init__(self):
+ super().__init__()
+ self.received = None
+
+ def slot(self, value):
+ self.received = value
+
+ @Slot("IntList")
+ def containerSlot(self, value):
+ self.received = value
+
+
+class TypedefSignal(unittest.TestCase):
+
+ def testTypedef(self):
+ obj = TestObject(0)
+ receiver = Receiver()
+
+ obj.signalWithTypedefValue.connect(receiver.slot)
+ obj.emitSignalWithTypedefValue(2)
+ self.assertEqual(receiver.received.value, 2)
+
+ def testContainerTypedef(self):
+ obj = TestObject(0)
+ receiver = Receiver()
+
+ test_list = [1, 2]
+ obj.signalWithContainerTypedefValue.connect(receiver.containerSlot)
+ obj.emitSignalWithContainerTypedefValue(test_list)
+ self.assertEqual(receiver.received, test_list)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/typesystem_pysidetest.xml b/sources/pyside6/tests/pysidetest/typesystem_pysidetest.xml
new file mode 100644
index 000000000..592d90a83
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/typesystem_pysidetest.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<typesystem package="testbinding">
+ <load-typesystem name="QtWidgets/typesystem_widgets.xml" generate="no"/>
+ <value-type name="IntValue"/>
+ <primitive-type name="TypedefValue">
+ <!--
+ A conversion rule is used here because ApiExtractor can't associate
+ a primitive typedef to a non-primitive type. That would be a good
+ improvement to ApiExtractor.
+ -->
+ <conversion-rule>
+ <native-to-target>
+ return %CONVERTTOPYTHON[IntValue](%in);
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="IntValue">
+ IntValue value = %CONVERTTOCPP[IntValue](%in);
+ %out = %OUTTYPE(value);
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </primitive-type>
+ <object-type name="TestObject" />
+
+ <primitive-type name="PySideInt"/>
+ <primitive-type name="PySideCPP2::PySideLong"/>
+ <!--<primitive-type name="PySideLong"/>-->
+
+ <function signature="getHiddenObject()" />
+
+ <inject-code position="end">
+ Shiboken::Conversions::registerConverterName(Shiboken::Conversions::PrimitiveTypeConverter&lt;long&gt;(), "PySideLong");
+ Shiboken::Conversions::registerConverterName(Shiboken::Conversions::PrimitiveTypeConverter&lt;long&gt;(), "PySideCPP2::PySideLong");
+ qRegisterMetaType&lt;PySideInt>("PySideInt");
+ qRegisterMetaType&lt;PySideCPP2::PySideLong>("PySideLong");
+ </inject-code>
+
+ <object-type name="ContainerTest"/>
+
+ <namespace-type name="PySideCPP">
+ <object-type name="TestObjectWithNamespace"/>
+ <object-type name="TestObject2WithNamespace">
+ <add-function signature="__repr__" return-type="PyObject*">
+ <inject-code class="target" position="beginning">
+ %PYARG_0 = Shiboken::String::fromCString("TestObject2WithNamespace(injected_repr)");
+ </inject-code>
+ </add-function>
+ </object-type>
+ </namespace-type>
+
+ <namespace-type name="PySideCPP2" generate="no">
+ <enum-type name="Enum1" />
+ <object-type name="TestObjectWithoutNamespace">
+ <enum-type name="Enum2" />
+ </object-type>
+ </namespace-type>
+
+ <object-type name="TestView" >
+ <modify-function signature="TestView(QAbstractListModel*,QObject*)">
+ <modify-argument index="1">
+ <reference-count action="set"/>
+ </modify-argument>
+ </modify-function>
+ </object-type>
+
+ <value-type name="TestQVariantEnum"/>
+
+ <namespace-type name="FlagsNamespace" visible="no">
+ <enum-type name="Option" flags="Options"/>
+ <object-type name="ClassForEnum" />
+ </namespace-type>
+
+ <object-type name="SharedPointerTestbench"/>
+
+ <value-type name="QVariantHolder"/>
+
+ <smart-pointer-type name="QSharedPointer" type="shared" getter="data"
+ reset-method="reset"/>
+
+</typesystem>
diff --git a/sources/pyside6/tests/pysidetest/version_test.py b/sources/pyside6/tests/pysidetest/version_test.py
new file mode 100644
index 000000000..f47ffc6d0
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/version_test.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+# 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)
+
+from PySide6 import __version_info__, __version__
+
+
+class CheckForVariablesTest(unittest.TestCase):
+ def testVesions(self):
+ version_tuple = (__version_info__[0], __version_info__[1], __version_info__[2])
+ self.assertTrue(version_tuple >= (1, 0, 0))
+
+ self.assertTrue(version_tuple < (99, 99, 99))
+ self.assertTrue(__version__)
+
+ self.assertTrue(__version_info__ >= (4, 5, 0))
+ self.assertTrue(__version__)
+
+
+if __name__ == '__main__':
+ unittest.main()
+