aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/tests
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6/tests')
-rw-r--r--sources/pyside6/tests/CMakeLists.txt73
-rw-r--r--sources/pyside6/tests/Qt3DAnimation/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/Qt3DCore/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/Qt3DExtras/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/Qt3DExtras/Qt3DExtras.pyproject3
-rw-r--r--sources/pyside6/tests/Qt3DExtras/qt3dextras_test.py140
-rw-r--r--sources/pyside6/tests/Qt3DInput/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/Qt3DLogic/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/Qt3DQuick/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/Qt3DRender/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtAsyncio/CMakeLists.txt2
-rw-r--r--sources/pyside6/tests/QtAsyncio/QtAsyncio.pyproject3
-rw-r--r--sources/pyside6/tests/QtAsyncio/qasyncio_test.py51
-rw-r--r--sources/pyside6/tests/QtAsyncio/qasyncio_test_cancel_task.py46
-rw-r--r--sources/pyside6/tests/QtAsyncio/qasyncio_test_cancel_taskgroup.py57
-rw-r--r--sources/pyside6/tests/QtAsyncio/qasyncio_test_chain.py57
-rw-r--r--sources/pyside6/tests/QtAsyncio/qasyncio_test_executor.py47
-rw-r--r--sources/pyside6/tests/QtAsyncio/qasyncio_test_queues.py70
-rw-r--r--sources/pyside6/tests/QtAsyncio/qasyncio_test_threadsafe.py58
-rw-r--r--sources/pyside6/tests/QtAsyncio/qasyncio_test_time.py49
-rw-r--r--sources/pyside6/tests/QtAxContainer/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtBluetooth/CMakeLists.txt2
-rw-r--r--sources/pyside6/tests/QtBluetooth/QtBluetooth.pyproject4
-rw-r--r--sources/pyside6/tests/QtBluetooth/localdevice.py25
-rw-r--r--sources/pyside6/tests/QtBluetooth/lowenergy_characteristics.py51
-rw-r--r--sources/pyside6/tests/QtCharts/CMakeLists.txt2
-rw-r--r--sources/pyside6/tests/QtCharts/QtCharts.pyproject3
-rw-r--r--sources/pyside6/tests/QtCharts/qcharts_numpy_test.py49
-rw-r--r--sources/pyside6/tests/QtCharts/qcharts_test.py46
-rw-r--r--sources/pyside6/tests/QtConcurrent/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtCore/CMakeLists.txt148
-rw-r--r--sources/pyside6/tests/QtCore/QtCore.pyproject148
-rw-r--r--sources/pyside6/tests/QtCore/attr_cache_py3k.py36
-rw-r--r--sources/pyside6/tests/QtCore/blocking_signals_test.py154
-rw-r--r--sources/pyside6/tests/QtCore/bug_1019.py48
-rw-r--r--sources/pyside6/tests/QtCore/bug_1063.py41
-rw-r--r--sources/pyside6/tests/QtCore/bug_1069.py35
-rw-r--r--sources/pyside6/tests/QtCore/bug_1313.py58
-rw-r--r--sources/pyside6/tests/QtCore/bug_278_test.py34
-rw-r--r--sources/pyside6/tests/QtCore/bug_300_test.py29
-rw-r--r--sources/pyside6/tests/QtCore/bug_324.py43
-rw-r--r--sources/pyside6/tests/QtCore/bug_332.py30
-rw-r--r--sources/pyside6/tests/QtCore/bug_408.py41
-rw-r--r--sources/pyside6/tests/QtCore/bug_428.py31
-rw-r--r--sources/pyside6/tests/QtCore/bug_462.py59
-rw-r--r--sources/pyside6/tests/QtCore/bug_505.py38
-rw-r--r--sources/pyside6/tests/QtCore/bug_515.py35
-rw-r--r--sources/pyside6/tests/QtCore/bug_606.py46
-rw-r--r--sources/pyside6/tests/QtCore/bug_656.py23
-rw-r--r--sources/pyside6/tests/QtCore/bug_686.py118
-rw-r--r--sources/pyside6/tests/QtCore/bug_699.py30
-rw-r--r--sources/pyside6/tests/QtCore/bug_706.py40
-rw-r--r--sources/pyside6/tests/QtCore/bug_820.py82
-rw-r--r--sources/pyside6/tests/QtCore/bug_826.py38
-rw-r--r--sources/pyside6/tests/QtCore/bug_829.py54
-rw-r--r--sources/pyside6/tests/QtCore/bug_835.py80
-rw-r--r--sources/pyside6/tests/QtCore/bug_920.py36
-rw-r--r--sources/pyside6/tests/QtCore/bug_927.py50
-rw-r--r--sources/pyside6/tests/QtCore/bug_931.py35
-rw-r--r--sources/pyside6/tests/QtCore/bug_938.py27
-rw-r--r--sources/pyside6/tests/QtCore/bug_953.py35
-rw-r--r--sources/pyside6/tests/QtCore/bug_987.py26
-rw-r--r--sources/pyside6/tests/QtCore/bug_994.py38
-rw-r--r--sources/pyside6/tests/QtCore/bug_PYSIDE-164.py54
-rw-r--r--sources/pyside6/tests/QtCore/bug_PYSIDE-2745.py37
-rw-r--r--sources/pyside6/tests/QtCore/bug_PYSIDE-41.py49
-rw-r--r--sources/pyside6/tests/QtCore/bug_PYSIDE-42.py29
-rw-r--r--sources/pyside6/tests/QtCore/child_event_test.py64
-rw-r--r--sources/pyside6/tests/QtCore/classinfo_test.py114
-rw-r--r--sources/pyside6/tests/QtCore/deepcopy_test.py102
-rw-r--r--sources/pyside6/tests/QtCore/deletelater_test.py36
-rw-r--r--sources/pyside6/tests/QtCore/destroysignal_test.py78
-rw-r--r--sources/pyside6/tests/QtCore/duck_punching_test.py89
-rw-r--r--sources/pyside6/tests/QtCore/emoji_string_test.py51
-rw-r--r--sources/pyside6/tests/QtCore/errormessages_with_features_test.py102
-rw-r--r--sources/pyside6/tests/QtCore/feature_with_uic/window.py52
-rw-r--r--sources/pyside6/tests/QtCore/feature_with_uic/window.ui62
-rw-r--r--sources/pyside6/tests/QtCore/feature_with_uic_test.py59
-rw-r--r--sources/pyside6/tests/QtCore/hash_test.py101
-rw-r--r--sources/pyside6/tests/QtCore/inherits_test.py29
-rw-r--r--sources/pyside6/tests/QtCore/loggingcategorymacros_test.py84
-rw-r--r--sources/pyside6/tests/QtCore/max_signals.py48
-rw-r--r--sources/pyside6/tests/QtCore/missing_symbols_test.py28
-rw-r--r--sources/pyside6/tests/QtCore/mockclass_test.py40
-rw-r--r--sources/pyside6/tests/QtCore/multiple_feature_test.py116
-rw-r--r--sources/pyside6/tests/QtCore/python_conversion.py77
-rw-r--r--sources/pyside6/tests/QtCore/qabs_test.py31
-rw-r--r--sources/pyside6/tests/QtCore/qabstractitemmodel_test.py52
-rw-r--r--sources/pyside6/tests/QtCore/qanimationgroup_test.py37
-rw-r--r--sources/pyside6/tests/QtCore/qbitarray_test.py134
-rw-r--r--sources/pyside6/tests/QtCore/qbytearray_concatenation_operator_test.py40
-rw-r--r--sources/pyside6/tests/QtCore/qbytearray_operator_iadd_test.py70
-rw-r--r--sources/pyside6/tests/QtCore/qbytearray_operator_test.py92
-rw-r--r--sources/pyside6/tests/QtCore/qbytearray_test.py290
-rw-r--r--sources/pyside6/tests/QtCore/qcalendar_test.py29
-rw-r--r--sources/pyside6/tests/QtCore/qcbor_test.py62
-rw-r--r--sources/pyside6/tests/QtCore/qcollator_test.py43
-rw-r--r--sources/pyside6/tests/QtCore/qcommandlineparser_test.py38
-rw-r--r--sources/pyside6/tests/QtCore/qcoreapplication_argv_test.py25
-rw-r--r--sources/pyside6/tests/QtCore/qcoreapplication_instance_test.py31
-rw-r--r--sources/pyside6/tests/QtCore/qcoreapplication_test.py23
-rw-r--r--sources/pyside6/tests/QtCore/qdatastream_test.py326
-rw-r--r--sources/pyside6/tests/QtCore/qdate_test.py45
-rw-r--r--sources/pyside6/tests/QtCore/qdatetime_test.py35
-rw-r--r--sources/pyside6/tests/QtCore/qdir_test.py39
-rw-r--r--sources/pyside6/tests/QtCore/qeasingcurve_test.py42
-rw-r--r--sources/pyside6/tests/QtCore/qenum_test.py202
-rw-r--r--sources/pyside6/tests/QtCore/qevent_test.py36
-rw-r--r--sources/pyside6/tests/QtCore/qfile_test.py85
-rw-r--r--sources/pyside6/tests/QtCore/qfileinfo_test.py33
-rw-r--r--sources/pyside6/tests/QtCore/qfileread_test.py66
-rw-r--r--sources/pyside6/tests/QtCore/qflags_test.py131
-rw-r--r--sources/pyside6/tests/QtCore/qhandle_test.py28
-rw-r--r--sources/pyside6/tests/QtCore/qinstallmsghandler_test.py76
-rw-r--r--sources/pyside6/tests/QtCore/qiodevice_buffered_read_test.py78
-rw-r--r--sources/pyside6/tests/QtCore/qiopipe_test.py36
-rw-r--r--sources/pyside6/tests/QtCore/qjsondocument_test.py32
-rw-r--r--sources/pyside6/tests/QtCore/qlinef_test.py31
-rw-r--r--sources/pyside6/tests/QtCore/qlocale_test.py73
-rw-r--r--sources/pyside6/tests/QtCore/qlockfile_test.py42
-rw-r--r--sources/pyside6/tests/QtCore/qmessageauthenticationcode_test.py28
-rw-r--r--sources/pyside6/tests/QtCore/qmetaobject_test.py213
-rw-r--r--sources/pyside6/tests/QtCore/qmetatype_test.py43
-rw-r--r--sources/pyside6/tests/QtCore/qmimedatabase_test.py59
-rw-r--r--sources/pyside6/tests/QtCore/qmodelindex_internalpointer_test.py63
-rw-r--r--sources/pyside6/tests/QtCore/qobject_children_segfault_test.py42
-rw-r--r--sources/pyside6/tests/QtCore/qobject_connect_notify_test.py99
-rw-r--r--sources/pyside6/tests/QtCore/qobject_destructor.py33
-rw-r--r--sources/pyside6/tests/QtCore/qobject_event_filter_test.py150
-rw-r--r--sources/pyside6/tests/QtCore/qobject_inherits_test.py115
-rw-r--r--sources/pyside6/tests/QtCore/qobject_objectproperty_test.py42
-rw-r--r--sources/pyside6/tests/QtCore/qobject_parent_test.py335
-rw-r--r--sources/pyside6/tests/QtCore/qobject_property_test.py53
-rw-r--r--sources/pyside6/tests/QtCore/qobject_protected_methods_test.py50
-rw-r--r--sources/pyside6/tests/QtCore/qobject_test.py96
-rw-r--r--sources/pyside6/tests/QtCore/qobject_timer_event_test.py57
-rw-r--r--sources/pyside6/tests/QtCore/qobject_tr_as_instance_test.py54
-rw-r--r--sources/pyside6/tests/QtCore/qoperatingsystemversion_test.py24
-rw-r--r--sources/pyside6/tests/QtCore/qpoint_test.py32
-rw-r--r--sources/pyside6/tests/QtCore/qprocess_test.py40
-rw-r--r--sources/pyside6/tests/QtCore/qproperty_decorator.py54
-rw-r--r--sources/pyside6/tests/QtCore/qrandomgenerator_test.py33
-rw-r--r--sources/pyside6/tests/QtCore/qrect_test.py123
-rw-r--r--sources/pyside6/tests/QtCore/qregularexpression_test.py41
-rw-r--r--sources/pyside6/tests/QtCore/qresource_test.py56
-rw-r--r--sources/pyside6/tests/QtCore/qrunnable_test.py45
-rw-r--r--sources/pyside6/tests/QtCore/qsettings_test.ini4
-rw-r--r--sources/pyside6/tests/QtCore/qsettings_test.py130
-rw-r--r--sources/pyside6/tests/QtCore/qsharedmemory_client.py36
-rw-r--r--sources/pyside6/tests/QtCore/qsharedmemory_test.py73
-rw-r--r--sources/pyside6/tests/QtCore/qsize_test.py37
-rw-r--r--sources/pyside6/tests/QtCore/qslot_object_test.py54
-rw-r--r--sources/pyside6/tests/QtCore/qsocketnotifier_test.py38
-rw-r--r--sources/pyside6/tests/QtCore/qsrand_test.py33
-rw-r--r--sources/pyside6/tests/QtCore/qstandardpaths_test.py32
-rw-r--r--sources/pyside6/tests/QtCore/qstorageinfo_test.py26
-rw-r--r--sources/pyside6/tests/QtCore/qstring_test.py37
-rw-r--r--sources/pyside6/tests/QtCore/qsysinfo_test.py28
-rw-r--r--sources/pyside6/tests/QtCore/qtextstream_test.py92
-rw-r--r--sources/pyside6/tests/QtCore/qthread_prod_cons_test.py116
-rw-r--r--sources/pyside6/tests/QtCore/qthread_signal_test.py71
-rw-r--r--sources/pyside6/tests/QtCore/qthread_test.py84
-rw-r--r--sources/pyside6/tests/QtCore/qtimer_singleshot_test.py195
-rw-r--r--sources/pyside6/tests/QtCore/qtimer_timeout_test.py73
-rw-r--r--sources/pyside6/tests/QtCore/qtimezone_test.py27
-rw-r--r--sources/pyside6/tests/QtCore/qtnamespace_test.py30
-rw-r--r--sources/pyside6/tests/QtCore/quoteEnUS.txt1
-rw-r--r--sources/pyside6/tests/QtCore/qurl_test.py149
-rw-r--r--sources/pyside6/tests/QtCore/qurlquery_test.py39
-rw-r--r--sources/pyside6/tests/QtCore/quuid_test.py29
-rw-r--r--sources/pyside6/tests/QtCore/qversionnumber_test.py31
-rw-r--r--sources/pyside6/tests/QtCore/repr_test.py97
-rw-r--r--sources/pyside6/tests/QtCore/resources.qrc7
-rw-r--r--sources/pyside6/tests/QtCore/resources_mc.py3547
-rw-r--r--sources/pyside6/tests/QtCore/sample.pngbin0 -> 55944 bytes
-rw-r--r--sources/pyside6/tests/QtCore/setprop_on_ctor_test.py24
-rw-r--r--sources/pyside6/tests/QtCore/signal_sender.py91
-rw-r--r--sources/pyside6/tests/QtCore/snake_prop_feature_test.py143
-rw-r--r--sources/pyside6/tests/QtCore/staticMetaObject_test.py36
-rw-r--r--sources/pyside6/tests/QtCore/static_method_test.py65
-rw-r--r--sources/pyside6/tests/QtCore/thread_signals_test.py47
-rw-r--r--sources/pyside6/tests/QtCore/tr_noop_test.py66
-rw-r--r--sources/pyside6/tests/QtCore/translation_test.py102
-rw-r--r--sources/pyside6/tests/QtCore/translations/trans_latin.qmbin0 -> 125 bytes
-rw-r--r--sources/pyside6/tests/QtCore/translations/trans_latin.ts11
-rw-r--r--sources/pyside6/tests/QtCore/translations/trans_russian.qmbin0 -> 114 bytes
-rw-r--r--sources/pyside6/tests/QtCore/translations/trans_russian.ts11
-rw-r--r--sources/pyside6/tests/QtCore/unaryoperator_test.py53
-rw-r--r--sources/pyside6/tests/QtCore/unicode_test.py44
-rw-r--r--sources/pyside6/tests/QtCore/versioninfo_test.py32
-rw-r--r--sources/pyside6/tests/QtDBus/CMakeLists.txt6
-rw-r--r--sources/pyside6/tests/QtDBus/QtDBus.pyproject3
-rw-r--r--sources/pyside6/tests/QtDBus/test_dbus.py44
-rw-r--r--sources/pyside6/tests/QtDataVisualization/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtDataVisualization/QtDataVisualization.pyproject3
-rw-r--r--sources/pyside6/tests/QtDataVisualization/datavisualization_test.py104
-rw-r--r--sources/pyside6/tests/QtDesigner/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtGraphs/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtGui/CMakeLists.txt60
-rw-r--r--sources/pyside6/tests/QtGui/QtGui.pyproject56
-rw-r--r--sources/pyside6/tests/QtGui/bug_1091.py25
-rw-r--r--sources/pyside6/tests/QtGui/bug_367.py35
-rw-r--r--sources/pyside6/tests/QtGui/bug_493.py32
-rw-r--r--sources/pyside6/tests/QtGui/bug_606.py45
-rw-r--r--sources/pyside6/tests/QtGui/bug_617.py34
-rw-r--r--sources/pyside6/tests/QtGui/bug_652.py47
-rw-r--r--sources/pyside6/tests/QtGui/bug_660.py40
-rw-r--r--sources/pyside6/tests/QtGui/bug_716.py20
-rw-r--r--sources/pyside6/tests/QtGui/bug_740.py25
-rw-r--r--sources/pyside6/tests/QtGui/bug_743.py27
-rw-r--r--sources/pyside6/tests/QtGui/bug_785.py41
-rw-r--r--sources/pyside6/tests/QtGui/bug_991.py28
-rw-r--r--sources/pyside6/tests/QtGui/bug_PYSIDE-344.py49
-rw-r--r--sources/pyside6/tests/QtGui/deepcopy_test.py140
-rw-r--r--sources/pyside6/tests/QtGui/event_filter_test.py51
-rw-r--r--sources/pyside6/tests/QtGui/float_to_int_implicit_conversion_test.py45
-rw-r--r--sources/pyside6/tests/QtGui/pyside_reload_test.py63
-rw-r--r--sources/pyside6/tests/QtGui/qbrush_test.py43
-rw-r--r--sources/pyside6/tests/QtGui/qcolor_reduce_test.py44
-rw-r--r--sources/pyside6/tests/QtGui/qcolor_test.py111
-rw-r--r--sources/pyside6/tests/QtGui/qcursor_test.py29
-rw-r--r--sources/pyside6/tests/QtGui/qdatastream_gui_operators_test.py45
-rw-r--r--sources/pyside6/tests/QtGui/qdesktopservices_test.py27
-rw-r--r--sources/pyside6/tests/QtGui/qfont_test.py35
-rw-r--r--sources/pyside6/tests/QtGui/qfontmetrics_test.py215
-rw-r--r--sources/pyside6/tests/QtGui/qguiapplication_test.py23
-rw-r--r--sources/pyside6/tests/QtGui/qicon_test.py48
-rw-r--r--sources/pyside6/tests/QtGui/qimage_test.py56
-rw-r--r--sources/pyside6/tests/QtGui/qimage_win_test.py41
-rw-r--r--sources/pyside6/tests/QtGui/qitemselection_test.py31
-rw-r--r--sources/pyside6/tests/QtGui/qkeysequence_test.py36
-rw-r--r--sources/pyside6/tests/QtGui/qpainter_test.py115
-rw-r--r--sources/pyside6/tests/QtGui/qpdfwriter_test.py32
-rw-r--r--sources/pyside6/tests/QtGui/qpen_test.py57
-rw-r--r--sources/pyside6/tests/QtGui/qpixelformat_test.py40
-rw-r--r--sources/pyside6/tests/QtGui/qpixmap_constructor.py260
-rw-r--r--sources/pyside6/tests/QtGui/qpixmap_test.py67
-rw-r--r--sources/pyside6/tests/QtGui/qpixmapcache_test.py56
-rw-r--r--sources/pyside6/tests/QtGui/qpolygonf_test.py42
-rw-r--r--sources/pyside6/tests/QtGui/qradialgradient_test.py41
-rw-r--r--sources/pyside6/tests/QtGui/qrasterwindow_test.py77
-rw-r--r--sources/pyside6/tests/QtGui/qregion_test.py40
-rw-r--r--sources/pyside6/tests/QtGui/qshortcut_test.py60
-rw-r--r--sources/pyside6/tests/QtGui/qstandarditemmodel_test.py85
-rw-r--r--sources/pyside6/tests/QtGui/qstring_qkeysequence_test.py42
-rw-r--r--sources/pyside6/tests/QtGui/qstylehints_test.py26
-rw-r--r--sources/pyside6/tests/QtGui/qtextdocument_functions.py37
-rw-r--r--sources/pyside6/tests/QtGui/qtextdocument_undoredo_test.py42
-rw-r--r--sources/pyside6/tests/QtGui/qtextdocumentwriter_test.py31
-rw-r--r--sources/pyside6/tests/QtGui/qtextline_test.py39
-rw-r--r--sources/pyside6/tests/QtGui/qtransform_test.py90
-rw-r--r--sources/pyside6/tests/QtGui/repr_test.py96
-rw-r--r--sources/pyside6/tests/QtGui/sample.pngbin0 -> 55944 bytes
-rw-r--r--sources/pyside6/tests/QtGui/timed_app_and_patching_test.py27
-rw-r--r--sources/pyside6/tests/QtGui/xpm_data.py237
-rw-r--r--sources/pyside6/tests/QtHelp/CMakeLists.txt2
-rw-r--r--sources/pyside6/tests/QtHelp/QtHelp.pyproject4
-rw-r--r--sources/pyside6/tests/QtHelp/help_test.py25
-rw-r--r--sources/pyside6/tests/QtHelp/helpsearchengine_test.py28
-rw-r--r--sources/pyside6/tests/QtHttpServer/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtLocation/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtLocation/QtLocation.pyproject3
-rw-r--r--sources/pyside6/tests/QtLocation/location.py26
-rw-r--r--sources/pyside6/tests/QtMultimedia/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtMultimedia/QtMultimedia.pyproject3
-rw-r--r--sources/pyside6/tests/QtMultimedia/audio_test.py58
-rw-r--r--sources/pyside6/tests/QtMultimediaWidgets/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtMultimediaWidgets/QtMultimediaWidgets.pyproject3
-rw-r--r--sources/pyside6/tests/QtMultimediaWidgets/qmultimediawidgets.py44
-rw-r--r--sources/pyside6/tests/QtNetwork/CMakeLists.txt13
-rw-r--r--sources/pyside6/tests/QtNetwork/QtNetwork.pyproject11
-rw-r--r--sources/pyside6/tests/QtNetwork/accessManager_test.py55
-rw-r--r--sources/pyside6/tests/QtNetwork/bug_1084.py28
-rw-r--r--sources/pyside6/tests/QtNetwork/bug_446.py58
-rw-r--r--sources/pyside6/tests/QtNetwork/dnslookup_test.py46
-rw-r--r--sources/pyside6/tests/QtNetwork/qhostinfo_test.py76
-rw-r--r--sources/pyside6/tests/QtNetwork/qipv6address_test.py34
-rw-r--r--sources/pyside6/tests/QtNetwork/qpassworddigestor_test.py28
-rw-r--r--sources/pyside6/tests/QtNetwork/tcpserver_test.py39
-rw-r--r--sources/pyside6/tests/QtNetwork/udpsocket_test.py65
-rw-r--r--sources/pyside6/tests/QtNetworkAuth/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtNfc/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtNfc/QtNfc.pyproject3
-rw-r--r--sources/pyside6/tests/QtNfc/test_nfc.py29
-rw-r--r--sources/pyside6/tests/QtOpenGL/CMakeLists.txt2
-rw-r--r--sources/pyside6/tests/QtOpenGL/QtOpenGL.pyproject4
-rw-r--r--sources/pyside6/tests/QtOpenGL/qopenglbuffer_test.py77
-rw-r--r--sources/pyside6/tests/QtOpenGL/qopenglwindow_test.py96
-rw-r--r--sources/pyside6/tests/QtOpenGLWidgets/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtPdf/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtPdfWidgets/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtPositioning/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtPositioning/QtPositioning.pyproject3
-rw-r--r--sources/pyside6/tests/QtPositioning/positioning.py28
-rw-r--r--sources/pyside6/tests/QtPrintSupport/CMakeLists.txt2
-rw-r--r--sources/pyside6/tests/QtPrintSupport/QtPrintSupport.pyproject4
-rw-r--r--sources/pyside6/tests/QtPrintSupport/bug_500.py25
-rw-r--r--sources/pyside6/tests/QtPrintSupport/returnquadruplesofnumbers_test.py65
-rw-r--r--sources/pyside6/tests/QtQml/CMakeLists.txt37
-rw-r--r--sources/pyside6/tests/QtQml/ModuleType.qml8
-rw-r--r--sources/pyside6/tests/QtQml/QtQml.pyproject65
-rw-r--r--sources/pyside6/tests/QtQml/bug_1029.py43
-rw-r--r--sources/pyside6/tests/QtQml/bug_1029.qml18
-rw-r--r--sources/pyside6/tests/QtQml/bug_451.py93
-rw-r--r--sources/pyside6/tests/QtQml/bug_451.qml31
-rw-r--r--sources/pyside6/tests/QtQml/bug_456.py63
-rw-r--r--sources/pyside6/tests/QtQml/bug_456.qml36
-rw-r--r--sources/pyside6/tests/QtQml/bug_557.py28
-rw-r--r--sources/pyside6/tests/QtQml/bug_726.py63
-rw-r--r--sources/pyside6/tests/QtQml/bug_726.qml36
-rw-r--r--sources/pyside6/tests/QtQml/bug_814.py65
-rw-r--r--sources/pyside6/tests/QtQml/bug_814.qml13
-rw-r--r--sources/pyside6/tests/QtQml/bug_825.py80
-rw-r--r--sources/pyside6/tests/QtQml/bug_825.qml13
-rw-r--r--sources/pyside6/tests/QtQml/bug_825_old.py80
-rw-r--r--sources/pyside6/tests/QtQml/bug_847.py70
-rw-r--r--sources/pyside6/tests/QtQml/bug_847.qml37
-rw-r--r--sources/pyside6/tests/QtQml/bug_915.py40
-rw-r--r--sources/pyside6/tests/QtQml/bug_926.py57
-rw-r--r--sources/pyside6/tests/QtQml/bug_926.qml20
-rw-r--r--sources/pyside6/tests/QtQml/bug_951.py51
-rw-r--r--sources/pyside6/tests/QtQml/bug_951.qml10
-rw-r--r--sources/pyside6/tests/QtQml/bug_995.py31
-rw-r--r--sources/pyside6/tests/QtQml/bug_995.qml15
-rw-r--r--sources/pyside6/tests/QtQml/bug_997.py51
-rw-r--r--sources/pyside6/tests/QtQml/bug_997.qml13
-rw-r--r--sources/pyside6/tests/QtQml/connect_python_qml.py55
-rw-r--r--sources/pyside6/tests/QtQml/connect_python_qml.qml23
-rw-r--r--sources/pyside6/tests/QtQml/groupedproperty.py112
-rw-r--r--sources/pyside6/tests/QtQml/groupedproperty.qml9
-rw-r--r--sources/pyside6/tests/QtQml/hw.qml23
-rw-r--r--sources/pyside6/tests/QtQml/javascript_exceptions.py91
-rw-r--r--sources/pyside6/tests/QtQml/javascript_exceptions.qml28
-rw-r--r--sources/pyside6/tests/QtQml/listproperty.py136
-rw-r--r--sources/pyside6/tests/QtQml/listproperty.qml50
-rw-r--r--sources/pyside6/tests/QtQml/qmlregistertype_test.py53
-rw-r--r--sources/pyside6/tests/QtQml/qmlregistertype_test.qml7
-rw-r--r--sources/pyside6/tests/QtQml/qqmlapplicationengine.qml23
-rw-r--r--sources/pyside6/tests/QtQml/qqmlapplicationengine_test.py38
-rw-r--r--sources/pyside6/tests/QtQml/qqmlcomponent_test.py36
-rw-r--r--sources/pyside6/tests/QtQml/qqmlincubator_incubateWhile.py84
-rw-r--r--sources/pyside6/tests/QtQml/qqmlincubator_incubateWhile.qml42
-rw-r--r--sources/pyside6/tests/QtQml/qqmlincubator_incubateWhile_component.qml10
-rw-r--r--sources/pyside6/tests/QtQml/qqmlnetwork_test.py76
-rw-r--r--sources/pyside6/tests/QtQml/qquickitem_grabToImage.py69
-rw-r--r--sources/pyside6/tests/QtQml/qquickitem_grabToImage.qml44
-rw-r--r--sources/pyside6/tests/QtQml/qquickview_test.py87
-rw-r--r--sources/pyside6/tests/QtQml/registerattached.py101
-rw-r--r--sources/pyside6/tests/QtQml/registerattached.qml20
-rw-r--r--sources/pyside6/tests/QtQml/registerextended.py74
-rw-r--r--sources/pyside6/tests/QtQml/registerextended.qml9
-rw-r--r--sources/pyside6/tests/QtQml/registerforeign.py52
-rw-r--r--sources/pyside6/tests/QtQml/registerforeign.qml8
-rw-r--r--sources/pyside6/tests/QtQml/registerparserstatus.py60
-rw-r--r--sources/pyside6/tests/QtQml/registerparserstatus.qml8
-rw-r--r--sources/pyside6/tests/QtQml/registerqmlfile.py30
-rw-r--r--sources/pyside6/tests/QtQml/registersingletontype.py152
-rw-r--r--sources/pyside6/tests/QtQml/registersingletontype.qml14
-rw-r--r--sources/pyside6/tests/QtQml/registertype.py116
-rw-r--r--sources/pyside6/tests/QtQml/registertype.qml32
-rw-r--r--sources/pyside6/tests/QtQml/registeruncreatable.qml13
-rw-r--r--sources/pyside6/tests/QtQml/registeruncreatabletype.py62
-rw-r--r--sources/pyside6/tests/QtQml/signal_arguments.py61
-rw-r--r--sources/pyside6/tests/QtQml/signal_arguments.qml36
-rw-r--r--sources/pyside6/tests/QtQml/signal_types.py124
-rw-r--r--sources/pyside6/tests/QtQml/signal_types.qml26
-rw-r--r--sources/pyside6/tests/QtQml/view.qml19
-rw-r--r--sources/pyside6/tests/QtQml/viewmodel.qml16
-rw-r--r--sources/pyside6/tests/QtQuick/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtQuick3D/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtQuickControls2/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtQuickTest/CMakeLists.txt3
-rw-r--r--sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/data/tst_setup.qml20
-rw-r--r--sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml3
-rw-r--r--sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir2
-rw-r--r--sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/quicktestmainwithsetup.pyproject4
-rw-r--r--sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/tst_quicktestmainwithsetup.py46
-rw-r--r--sources/pyside6/tests/QtQuickWidgets/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtRemoteObjects/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtScxml/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtScxml/QtScxml.pyproject3
-rw-r--r--sources/pyside6/tests/QtScxml/test_dynamic.py53
-rw-r--r--sources/pyside6/tests/QtScxml/trafficlight.scxml64
-rw-r--r--sources/pyside6/tests/QtSensors/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtSensors/QtSensors.pyproject3
-rw-r--r--sources/pyside6/tests/QtSensors/sensors.py46
-rw-r--r--sources/pyside6/tests/QtSerialBus/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtSerialPort/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtSerialPort/QtSerialPort.pyproject3
-rw-r--r--sources/pyside6/tests/QtSerialPort/serial.py72
-rw-r--r--sources/pyside6/tests/QtSpatialAudio/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtSql/CMakeLists.txt6
-rw-r--r--sources/pyside6/tests/QtSql/QtSql.pyproject5
-rw-r--r--sources/pyside6/tests/QtSql/bug_1013.py43
-rw-r--r--sources/pyside6/tests/QtSql/qsqldatabaseandqueries_test.py86
-rw-r--r--sources/pyside6/tests/QtSql/qvarianttype_test.py39
-rw-r--r--sources/pyside6/tests/QtStateMachine/CMakeLists.txt8
-rw-r--r--sources/pyside6/tests/QtStateMachine/QtStateMachine.pyproject7
-rw-r--r--sources/pyside6/tests/QtStateMachine/bug_1031.py18
-rw-r--r--sources/pyside6/tests/QtStateMachine/qabstracttransition_test.py175
-rw-r--r--sources/pyside6/tests/QtStateMachine/qstate_test.py49
-rw-r--r--sources/pyside6/tests/QtStateMachine/qstatemachine_test.py68
-rw-r--r--sources/pyside6/tests/QtStateMachine/setprop_on_ctor_test.py24
-rw-r--r--sources/pyside6/tests/QtSvg/CMakeLists.txt2
-rw-r--r--sources/pyside6/tests/QtSvg/QtSvg.pyproject4
-rw-r--r--sources/pyside6/tests/QtSvg/qsvggenerator_test.py47
-rw-r--r--sources/pyside6/tests/QtSvg/qsvgrenderer_test.py37
-rw-r--r--sources/pyside6/tests/QtSvg/tiger.svg730
-rw-r--r--sources/pyside6/tests/QtSvgWidgets/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtSvgWidgets/QtSvgWidgets.pyproject3
-rw-r--r--sources/pyside6/tests/QtSvgWidgets/qsvgwidget_test.py41
-rw-r--r--sources/pyside6/tests/QtTest/CMakeLists.txt9
-rw-r--r--sources/pyside6/tests/QtTest/QtTest.pyproject7
-rw-r--r--sources/pyside6/tests/QtTest/click_test.py38
-rw-r--r--sources/pyside6/tests/QtTest/eventfilter_test.py57
-rw-r--r--sources/pyside6/tests/QtTest/qsignalspy_test.py42
-rw-r--r--sources/pyside6/tests/QtTest/qvalidator_test.py122
-rw-r--r--sources/pyside6/tests/QtTest/touchevent_test.py63
-rw-r--r--sources/pyside6/tests/QtTextToSpeech/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtTextToSpeech/QtTextToSpeech.pyproject3
-rw-r--r--sources/pyside6/tests/QtTextToSpeech/qtexttospeech_test.py49
-rw-r--r--sources/pyside6/tests/QtUiTools/CMakeLists.txt16
-rw-r--r--sources/pyside6/tests/QtUiTools/QtUiTools.pyproject28
-rw-r--r--sources/pyside6/tests/QtUiTools/action.ui16
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_1060.py32
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_1060.ui19
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_360.py48
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_376.py31
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_392.py63
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_426.py32
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_426.ui19
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_552.py37
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_552.ui42
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_797.py25
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_909.py37
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_909.ui31
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_913.py32
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_913.ui57
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_958.py40
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_958.ui48
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_965.py35
-rw-r--r--sources/pyside6/tests/QtUiTools/bug_965.ui27
-rw-r--r--sources/pyside6/tests/QtUiTools/loadUiType_test.py52
-rw-r--r--sources/pyside6/tests/QtUiTools/minimal.ui6
-rw-r--r--sources/pyside6/tests/QtUiTools/pycustomwidget.ui36
-rw-r--r--sources/pyside6/tests/QtUiTools/pycustomwidget2.ui48
-rw-r--r--sources/pyside6/tests/QtUiTools/test.ui48
-rw-r--r--sources/pyside6/tests/QtUiTools/ui_test.py25
-rw-r--r--sources/pyside6/tests/QtUiTools/uiloader_test.py54
-rw-r--r--sources/pyside6/tests/QtWebChannel/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtWebEngineCore/CMakeLists.txt5
-rw-r--r--sources/pyside6/tests/QtWebEngineCore/QtWebEngineCore.pyproject4
-rw-r--r--sources/pyside6/tests/QtWebEngineCore/qwebenginecookiestore_test.py46
-rw-r--r--sources/pyside6/tests/QtWebEngineCore/resources/index.html12
-rw-r--r--sources/pyside6/tests/QtWebEngineCore/web_engine_custom_scheme.py70
-rw-r--r--sources/pyside6/tests/QtWebEngineQuick/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtWebEngineWidgets/CMakeLists.txt4
-rw-r--r--sources/pyside6/tests/QtWebEngineWidgets/QtWebEngineWidgets.pyproject3
-rw-r--r--sources/pyside6/tests/QtWebEngineWidgets/fox.html7
-rw-r--r--sources/pyside6/tests/QtWebEngineWidgets/pyside-474-qtwebengineview.py59
-rw-r--r--sources/pyside6/tests/QtWebSockets/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtWidgets/CMakeLists.txt134
-rw-r--r--sources/pyside6/tests/QtWidgets/QtWidgets.pyproject130
-rw-r--r--sources/pyside6/tests/QtWidgets/action_clear.py68
-rw-r--r--sources/pyside6/tests/QtWidgets/add_action_test.py60
-rw-r--r--sources/pyside6/tests/QtWidgets/api2_test.py73
-rw-r--r--sources/pyside6/tests/QtWidgets/application_test.py42
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_1002.py35
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_1006.py99
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_1048.py21
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_1077.py32
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_172.py26
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_243.py28
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_307.py37
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_338.py38
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_389.py28
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_400.py38
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_429.py22
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_430.py29
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_433.py28
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_467.py32
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_480.py39
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_512.py34
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_525.py35
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_546.py27
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_547.py73
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_549.py28
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_569.py30
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_575.py33
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_576.py49
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_585.py38
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_589.py32
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_635.py41
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_640.py23
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_653.py29
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_662.py42
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_667.py37
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_668.py34
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_674.py35
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_675.py28
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_688.py98
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_693.py42
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_696.py38
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_711.py34
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_722.py36
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_728.py39
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_736.py30
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_750.py38
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_778.py34
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_793.py45
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_811.py46
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_834.py33
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_836.py46
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_844.py31
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_854.py54
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_860.py46
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_862.py78
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_871.py53
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_879.py43
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_919.py51
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_921.py67
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_941.py31
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_964.py31
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_967.py31
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_972.py52
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_979.py21
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_988.py31
-rw-r--r--sources/pyside6/tests/QtWidgets/bug_998.py23
-rw-r--r--sources/pyside6/tests/QtWidgets/customproxywidget_test.py47
-rw-r--r--sources/pyside6/tests/QtWidgets/grandparent_method_test.py35
-rw-r--r--sources/pyside6/tests/QtWidgets/hashabletype_test.py30
-rw-r--r--sources/pyside6/tests/QtWidgets/import_test.py2
-rw-r--r--sources/pyside6/tests/QtWidgets/keep_reference_test.py91
-rw-r--r--sources/pyside6/tests/QtWidgets/missing_symbols_test.py43
-rw-r--r--sources/pyside6/tests/QtWidgets/paint_event_test.py68
-rw-r--r--sources/pyside6/tests/QtWidgets/parent_method_test.py38
-rw-r--r--sources/pyside6/tests/QtWidgets/private_mangle_test.py94
-rw-r--r--sources/pyside6/tests/QtWidgets/python_properties_test.py31
-rw-r--r--sources/pyside6/tests/QtWidgets/qabstracttextdocumentlayout_test.py59
-rw-r--r--sources/pyside6/tests/QtWidgets/qaccessible_test.py138
-rw-r--r--sources/pyside6/tests/QtWidgets/qaction_test.py65
-rw-r--r--sources/pyside6/tests/QtWidgets/qapp_issue_585.py53
-rw-r--r--sources/pyside6/tests/QtWidgets/qapp_test.py31
-rw-r--r--sources/pyside6/tests/QtWidgets/qapplication_exit_segfault_test.py30
-rw-r--r--sources/pyside6/tests/QtWidgets/qapplication_test.py23
-rw-r--r--sources/pyside6/tests/QtWidgets/qcolormap_test.py25
-rw-r--r--sources/pyside6/tests/QtWidgets/qdialog_test.py52
-rw-r--r--sources/pyside6/tests/QtWidgets/qdynamic_signal.py41
-rw-r--r--sources/pyside6/tests/QtWidgets/qfontdialog_test.py31
-rw-r--r--sources/pyside6/tests/QtWidgets/qformlayout_test.py99
-rw-r--r--sources/pyside6/tests/QtWidgets/qgraphicsitem_isblocked_test.py41
-rw-r--r--sources/pyside6/tests/QtWidgets/qgraphicsitem_test.py50
-rw-r--r--sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py62
-rw-r--r--sources/pyside6/tests/QtWidgets/qgraphicsproxywidget_test.py42
-rw-r--r--sources/pyside6/tests/QtWidgets/qgraphicsscene_test.py213
-rw-r--r--sources/pyside6/tests/QtWidgets/qinputdialog_get_test.py47
-rw-r--r--sources/pyside6/tests/QtWidgets/qkeysequenceedit_test.py31
-rw-r--r--sources/pyside6/tests/QtWidgets/qlabel_test.py77
-rw-r--r--sources/pyside6/tests/QtWidgets/qlayout_ref_test.py171
-rw-r--r--sources/pyside6/tests/QtWidgets/qlayout_test.py139
-rw-r--r--sources/pyside6/tests/QtWidgets/qlcdnumber_test.py33
-rw-r--r--sources/pyside6/tests/QtWidgets/qlistwidget_test.py77
-rw-r--r--sources/pyside6/tests/QtWidgets/qlistwidgetitem_test.py42
-rw-r--r--sources/pyside6/tests/QtWidgets/qmainwindow_test.py97
-rw-r--r--sources/pyside6/tests/QtWidgets/qmenu_test.py76
-rw-r--r--sources/pyside6/tests/QtWidgets/qmenuadd_test.py33
-rw-r--r--sources/pyside6/tests/QtWidgets/qobject_mi_test.py51
-rw-r--r--sources/pyside6/tests/QtWidgets/qpicture_test.py48
-rw-r--r--sources/pyside6/tests/QtWidgets/qpushbutton_test.py54
-rw-r--r--sources/pyside6/tests/QtWidgets/qsplitter_test.py29
-rw-r--r--sources/pyside6/tests/QtWidgets/qstyle_test.py76
-rw-r--r--sources/pyside6/tests/QtWidgets/qstyleoption_test.py43
-rw-r--r--sources/pyside6/tests/QtWidgets/qtableview_test.py28
-rw-r--r--sources/pyside6/tests/QtWidgets/qtabwidget_test.py43
-rw-r--r--sources/pyside6/tests/QtWidgets/qtabwidgetclear_test.py48
-rw-r--r--sources/pyside6/tests/QtWidgets/qtextedit_signal_test.py50
-rw-r--r--sources/pyside6/tests/QtWidgets/qtextedit_test.py45
-rw-r--r--sources/pyside6/tests/QtWidgets/qtoolbar_test.py50
-rw-r--r--sources/pyside6/tests/QtWidgets/qtoolbox_test.py45
-rw-r--r--sources/pyside6/tests/QtWidgets/qtreeview_test.py84
-rw-r--r--sources/pyside6/tests/QtWidgets/qtreewidget_test.py48
-rw-r--r--sources/pyside6/tests/QtWidgets/qtreewidgetitem_test.py47
-rw-r--r--sources/pyside6/tests/QtWidgets/qvariant_test.py142
-rw-r--r--sources/pyside6/tests/QtWidgets/qwidget_setlayout_test.py44
-rw-r--r--sources/pyside6/tests/QtWidgets/qwidget_test.py61
-rw-r--r--sources/pyside6/tests/QtWidgets/reference_count_test.py84
-rw-r--r--sources/pyside6/tests/QtWidgets/sample.pngbin0 -> 55944 bytes
-rw-r--r--sources/pyside6/tests/QtWidgets/signature_test.py59
-rw-r--r--sources/pyside6/tests/QtWidgets/standardpixmap_test.py27
-rw-r--r--sources/pyside6/tests/QtWidgets/test_module_template.py27
-rw-r--r--sources/pyside6/tests/QtWidgets/virtual_protected_inheritance_test.py84
-rw-r--r--sources/pyside6/tests/QtWidgets/virtual_pure_override_test.py61
-rw-r--r--sources/pyside6/tests/QtWidgets/wrong_return_test.py39
-rw-r--r--sources/pyside6/tests/QtXml/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/QtXml/QtXml.pyproject3
-rw-r--r--sources/pyside6/tests/QtXml/qdomdocument_test.py82
-rw-r--r--sources/pyside6/tests/init_paths.py78
-rw-r--r--sources/pyside6/tests/mac/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/mac/qmacstyle_test.py32
-rw-r--r--sources/pyside6/tests/manually/README.txt5
-rw-r--r--sources/pyside6/tests/manually/bug_841.py57
-rw-r--r--sources/pyside6/tests/manually/lazytiming.py38
-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
-rw-r--r--sources/pyside6/tests/registry/CMakeLists.txt4
-rw-r--r--sources/pyside6/tests/registry/existence_test.py229
-rw-r--r--sources/pyside6/tests/registry/init_platform.py210
-rw-r--r--sources/pyside6/tests/registry/scrape_testresults.py338
-rw-r--r--sources/pyside6/tests/registry/util.py149
-rwxr-xr-xsources/pyside6/tests/run_test.sh15
-rw-r--r--sources/pyside6/tests/signals/CMakeLists.txt47
-rw-r--r--sources/pyside6/tests/signals/anonymous_slot_leak_test.py55
-rw-r--r--sources/pyside6/tests/signals/args_dont_match_test.py36
-rw-r--r--sources/pyside6/tests/signals/bug_189.py38
-rw-r--r--sources/pyside6/tests/signals/bug_311.py54
-rw-r--r--sources/pyside6/tests/signals/bug_312.py45
-rw-r--r--sources/pyside6/tests/signals/bug_319.py47
-rw-r--r--sources/pyside6/tests/signals/bug_79.py59
-rw-r--r--sources/pyside6/tests/signals/decorators_test.py95
-rw-r--r--sources/pyside6/tests/signals/disconnect_test.py70
-rw-r--r--sources/pyside6/tests/signals/invalid_callback_test.py41
-rw-r--r--sources/pyside6/tests/signals/lambda_gui_test.py50
-rw-r--r--sources/pyside6/tests/signals/lambda_test.py123
-rw-r--r--sources/pyside6/tests/signals/leaking_signal_test.py27
-rw-r--r--sources/pyside6/tests/signals/multiple_connections_gui_test.py60
-rw-r--r--sources/pyside6/tests/signals/multiple_connections_test.py90
-rw-r--r--sources/pyside6/tests/signals/pysignal_test.py203
-rw-r--r--sources/pyside6/tests/signals/qobject_callable_connect_test.py45
-rw-r--r--sources/pyside6/tests/signals/qobject_destroyed_test.py39
-rw-r--r--sources/pyside6/tests/signals/qobject_receivers_test.py65
-rw-r--r--sources/pyside6/tests/signals/qobject_sender_test.py117
-rw-r--r--sources/pyside6/tests/signals/ref01_test.py39
-rw-r--r--sources/pyside6/tests/signals/ref02_test.py60
-rw-r--r--sources/pyside6/tests/signals/ref03_test.py42
-rw-r--r--sources/pyside6/tests/signals/ref04_test.py58
-rw-r--r--sources/pyside6/tests/signals/ref05_test.py58
-rw-r--r--sources/pyside6/tests/signals/ref06_test.py61
-rw-r--r--sources/pyside6/tests/signals/segfault_proxyparent_test.py78
-rw-r--r--sources/pyside6/tests/signals/self_connect_test.py64
-rw-r--r--sources/pyside6/tests/signals/short_circuit_test.py85
-rw-r--r--sources/pyside6/tests/signals/signal2signal_connect_test.py121
-rw-r--r--sources/pyside6/tests/signals/signal_across_threads.py82
-rw-r--r--sources/pyside6/tests/signals/signal_autoconnect_test.py41
-rw-r--r--sources/pyside6/tests/signals/signal_connectiontype_support_test.py42
-rw-r--r--sources/pyside6/tests/signals/signal_emission_gui_test.py118
-rw-r--r--sources/pyside6/tests/signals/signal_emission_test.py142
-rw-r--r--sources/pyside6/tests/signals/signal_enum_test.py57
-rw-r--r--sources/pyside6/tests/signals/signal_func_test.py31
-rw-r--r--sources/pyside6/tests/signals/signal_manager_refcount_test.py36
-rw-r--r--sources/pyside6/tests/signals/signal_newenum_test.py50
-rw-r--r--sources/pyside6/tests/signals/signal_number_limit_test.py74
-rw-r--r--sources/pyside6/tests/signals/signal_object_test.py98
-rw-r--r--sources/pyside6/tests/signals/signal_signature_test.py105
-rw-r--r--sources/pyside6/tests/signals/signal_with_primitive_type_test.py38
-rw-r--r--sources/pyside6/tests/signals/signals.pyproject19
-rw-r--r--sources/pyside6/tests/signals/slot_reference_count_test.py70
-rw-r--r--sources/pyside6/tests/signals/static_metaobject_test.py83
-rw-r--r--sources/pyside6/tests/support/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/support/voidptr_test.py49
-rw-r--r--sources/pyside6/tests/tools/__init__.py1
-rw-r--r--sources/pyside6/tests/tools/list-class-hierarchy.py88
-rw-r--r--sources/pyside6/tests/tools/metaobjectdump/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/tools/metaobjectdump/baseline_default_birthdayparty.json1
-rw-r--r--sources/pyside6/tests/tools/metaobjectdump/baseline_default_person.json1
-rw-r--r--sources/pyside6/tests/tools/metaobjectdump/baseline_inheritance_birthdayparty.json1
-rw-r--r--sources/pyside6/tests/tools/metaobjectdump/baseline_inheritance_person.json1
-rw-r--r--sources/pyside6/tests/tools/metaobjectdump/baseline_property_happybirthdaysong.json1
-rw-r--r--sources/pyside6/tests/tools/metaobjectdump/test_metaobjectdump.py73
-rw-r--r--sources/pyside6/tests/tools/pyside6-android-deploy/CMakeLists.txt3
-rw-r--r--sources/pyside6/tests/tools/pyside6-android-deploy/extensive_android_deploy_test.py88
-rw-r--r--sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py274
-rw-r--r--sources/pyside6/tests/tools/pyside6-deploy/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/tools/pyside6-deploy/extensive_deploy_test.py88
-rw-r--r--sources/pyside6/tests/tools/pyside6-deploy/test_pyside6_deploy.py400
-rw-r--r--sources/pyside6/tests/tools/pyside6-qml/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/tools/pyside6-qml/test_pyside6_qml.py75
-rw-r--r--sources/pyside6/tests/util/color.py14
-rw-r--r--sources/pyside6/tests/util/helper/__init__.py1
-rw-r--r--sources/pyside6/tests/util/helper/basicpyslotcase.py33
-rw-r--r--sources/pyside6/tests/util/helper/docmodifier.py91
-rw-r--r--sources/pyside6/tests/util/helper/helper.py37
-rw-r--r--sources/pyside6/tests/util/helper/helper.pyproject5
-rw-r--r--sources/pyside6/tests/util/helper/timedqapplication.py27
-rw-r--r--sources/pyside6/tests/util/helper/timedqguiapplication.py27
-rw-r--r--sources/pyside6/tests/util/helper/usesqapplication.py43
-rw-r--r--sources/pyside6/tests/util/httpd.py153
-rw-r--r--sources/pyside6/tests/util/processtimer.py54
-rwxr-xr-xsources/pyside6/tests/util/rename_imports.sh16
-rw-r--r--sources/pyside6/tests/util/test_processtimer.py73
-rw-r--r--sources/pyside6/tests/util/valgrind-python.supp349
743 files changed, 42410 insertions, 0 deletions
diff --git a/sources/pyside6/tests/CMakeLists.txt b/sources/pyside6/tests/CMakeLists.txt
new file mode 100644
index 000000000..539e1aea8
--- /dev/null
+++ b/sources/pyside6/tests/CMakeLists.txt
@@ -0,0 +1,73 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(PYSIDE_IS_CROSS_BUILD)
+ # SHIBOKEN_PYTHON_INTERPRETER will be empty when cross-building.
+ message(WARNING
+ "Running tests when cross-compiling is not supported because it would require running "
+ "a target python interpreter which might have a different architecture than the host."
+ )
+endif()
+
+if(NOT CTEST_TESTING_TIMEOUT)
+ set(CTEST_TESTING_TIMEOUT 60)
+endif()
+
+# BUILD_DIR and QT_DIR are used by init_paths.py for setting
+# the path to the testbinding module
+get_filename_component(BUILD_DIR "${CMAKE_BINARY_DIR}" DIRECTORY)
+get_filename_component(BUILD_DIR "${CMAKE_BINARY_DIR}" DIRECTORY)
+set(QT_DIR "${QT6_INSTALL_PREFIX}")
+
+macro(TEST_QT_MODULE var name)
+ if(NOT DISABLE_${name} AND ${var})
+ add_subdirectory(${name})
+ endif()
+endmacro()
+
+macro(PYSIDE_TEST)
+ string(REGEX MATCH "/([^/]+)//?([^/]+)\\.py" foo "${CMAKE_CURRENT_SOURCE_DIR}/${ARGV0}" )
+ set(TEST_NAME "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}")
+ if (${ARGC} EQUAL 1)
+ set(EXPECT_TO_FAIL 0)
+ elseif(${ARGC} EQUAL 2)
+ set(EXPECT_TO_FAIL ${ARGV1})
+ else()
+ message(WARNING "Invalid call of macro PYSIDE_TEST")
+ endif()
+ set(TEST_CMD ${XVFB_EXEC} ${SHIBOKEN_PYTHON_INTERPRETER} "${CMAKE_CURRENT_SOURCE_DIR}/${ARGV0}")
+ add_test(${TEST_NAME} ${TEST_CMD})
+ # QT_NO_GLIB=1 is required to avoid crashes on CI RHEL 6.6 machines.
+ # See QTBUG-64716 for details.
+ set_tests_properties(${TEST_NAME} PROPERTIES
+ TIMEOUT ${CTEST_TESTING_TIMEOUT}
+ WILL_FAIL ${EXPECT_TO_FAIL}
+ ENVIRONMENT "BUILD_DIR=${BUILD_DIR};QT_DIR=${QT_DIR};PYSIDE_DISABLE_INTERNAL_QT_CONF=1;QT_NO_GLIB=1")
+endmacro()
+
+if (NOT DISABLE_QtCore AND NOT DISABLE_QtGui AND NOT DISABLE_QtWidgets)
+ add_subdirectory(pysidetest)
+endif()
+add_subdirectory(registry)
+add_subdirectory(signals)
+add_subdirectory(support)
+add_subdirectory(tools/metaobjectdump)
+add_subdirectory(tools/pyside6-deploy)
+
+if(UNIX AND NOT APPLE)
+ add_subdirectory(tools/pyside6-android-deploy)
+endif()
+
+if (NOT DISABLE_QtQuick)
+ add_subdirectory(tools/pyside6-qml)
+endif()
+
+foreach(shortname IN LISTS all_module_shortnames)
+ message(STATUS "preparing tests for module 'Qt${shortname}'")
+ TEST_QT_MODULE(Qt${QT_MAJOR_VERSION}${shortname}_FOUND Qt${shortname})
+endforeach()
+
+#platform specific
+if (ENABLE_MAC)
+ add_subdirectory(mac)
+endif ()
diff --git a/sources/pyside6/tests/Qt3DAnimation/CMakeLists.txt b/sources/pyside6/tests/Qt3DAnimation/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/Qt3DAnimation/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/Qt3DCore/CMakeLists.txt b/sources/pyside6/tests/Qt3DCore/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/Qt3DCore/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/Qt3DExtras/CMakeLists.txt b/sources/pyside6/tests/Qt3DExtras/CMakeLists.txt
new file mode 100644
index 000000000..5f8d2e77b
--- /dev/null
+++ b/sources/pyside6/tests/Qt3DExtras/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(qt3dextras_test.py)
diff --git a/sources/pyside6/tests/Qt3DExtras/Qt3DExtras.pyproject b/sources/pyside6/tests/Qt3DExtras/Qt3DExtras.pyproject
new file mode 100644
index 000000000..4ac255226
--- /dev/null
+++ b/sources/pyside6/tests/Qt3DExtras/Qt3DExtras.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["qt3dextras_test.py"]
+}
diff --git a/sources/pyside6/tests/Qt3DExtras/qt3dextras_test.py b/sources/pyside6/tests/Qt3DExtras/qt3dextras_test.py
new file mode 100644
index 000000000..23e2d6e7e
--- /dev/null
+++ b/sources/pyside6/tests/Qt3DExtras/qt3dextras_test.py
@@ -0,0 +1,140 @@
+#!/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
+
+'''Test cases for Q3DExtras'''
+
+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 (Property, QObject, QPropertyAnimation, QTimer, Signal, Slot)
+from PySide6.QtGui import (QGuiApplication, QMatrix4x4, QQuaternion, QVector3D, QWindow)
+from PySide6.Qt3DCore import (Qt3DCore)
+from PySide6.Qt3DRender import (Qt3DRender)
+from PySide6.Qt3DExtras import (Qt3DExtras)
+
+
+class OrbitTransformController(QObject):
+ def __init__(self, parent):
+ super().__init__(parent)
+ self._target = None
+ self._matrix = QMatrix4x4()
+ self._radius = 1
+ self._angle = 0
+
+ def setTarget(self, t):
+ self._target = t
+
+ def getTarget(self):
+ return self._target
+
+ def setRadius(self, radius):
+ if self._radius != radius:
+ self._radius = radius
+ self.updateMatrix()
+ self.radiusChanged.emit()
+
+ def getRadius(self):
+ return self._radius
+
+ def setAngle(self, angle):
+ if self._angle != angle:
+ self._angle = angle
+ self.updateMatrix()
+ self.angleChanged.emit()
+
+ def getAngle(self):
+ return self._angle
+
+ def updateMatrix(self):
+ self._matrix.setToIdentity()
+ self._matrix.rotate(self._angle, QVector3D(0, 1, 0))
+ self._matrix.translate(self._radius, 0, 0)
+ if self._target is not None:
+ self._target.setMatrix(self._matrix)
+
+ angleChanged = Signal()
+ radiusChanged = Signal()
+ angle = Property(float, getAngle, setAngle, notify=angleChanged)
+ radius = Property(float, getRadius, setRadius, notify=radiusChanged)
+
+
+class Window(Qt3DExtras.Qt3DWindow):
+ def __init__(self):
+ super().__init__()
+
+ # Camera
+ self.camera().lens().setPerspectiveProjection(45, 16 / 9, 0.1, 1000)
+ self.camera().setPosition(QVector3D(0, 0, 40))
+ self.camera().setViewCenter(QVector3D(0, 0, 0))
+
+ # For camera controls
+ self.createScene()
+ self.camController = Qt3DExtras.QOrbitCameraController(self.rootEntity)
+ self.camController.setLinearSpeed(50)
+ self.camController.setLookSpeed(180)
+ self.camController.setCamera(self.camera())
+
+ self.setRootEntity(self.rootEntity)
+
+ def createScene(self):
+ # Root entity
+ self.rootEntity = Qt3DCore.QEntity()
+
+ # Material
+ self.material = Qt3DExtras.QPhongMaterial(self.rootEntity)
+
+ # Torus
+ self.torusEntity = Qt3DCore.QEntity(self.rootEntity)
+ self.torusMesh = Qt3DExtras.QTorusMesh()
+ self.torusMesh.setRadius(5)
+ self.torusMesh.setMinorRadius(1)
+ self.torusMesh.setRings(100)
+ self.torusMesh.setSlices(20)
+
+ self.torusTransform = Qt3DCore.QTransform()
+ self.torusTransform.setScale3D(QVector3D(1.5, 1, 0.5))
+ self.torusTransform.setRotation(QQuaternion.fromAxisAndAngle(QVector3D(1, 0, 0), 45))
+
+ self.torusEntity.addComponent(self.torusMesh)
+ self.torusEntity.addComponent(self.torusTransform)
+ self.torusEntity.addComponent(self.material)
+
+ # Sphere
+ self.sphereEntity = Qt3DCore.QEntity(self.rootEntity)
+ self.sphereMesh = Qt3DExtras.QSphereMesh()
+ self.sphereMesh.setRadius(3)
+
+ self.sphereTransform = Qt3DCore.QTransform()
+ self.controller = OrbitTransformController(self.sphereTransform)
+ self.controller.setTarget(self.sphereTransform)
+ self.controller.setRadius(20)
+
+ self.sphereEntity.addComponent(self.sphereMesh)
+ self.sphereEntity.addComponent(self.sphereTransform)
+ self.sphereEntity.addComponent(self.material)
+
+
+class Qt3DExtrasTestCase(UsesQApplication):
+ '''Tests related to Q3DExtras'''
+
+ def test3DExtras(self):
+
+ window = Window()
+ window.show()
+ while not window.isExposed():
+ self.app.processEvents()
+ QTimer.singleShot(2000, self.app.quit)
+ self.app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/Qt3DInput/CMakeLists.txt b/sources/pyside6/tests/Qt3DInput/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/Qt3DInput/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/Qt3DLogic/CMakeLists.txt b/sources/pyside6/tests/Qt3DLogic/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/Qt3DLogic/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/Qt3DQuick/CMakeLists.txt b/sources/pyside6/tests/Qt3DQuick/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/Qt3DQuick/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/Qt3DRender/CMakeLists.txt b/sources/pyside6/tests/Qt3DRender/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/Qt3DRender/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtAsyncio/CMakeLists.txt b/sources/pyside6/tests/QtAsyncio/CMakeLists.txt
new file mode 100644
index 000000000..935e0d90a
--- /dev/null
+++ b/sources/pyside6/tests/QtAsyncio/CMakeLists.txt
@@ -0,0 +1,2 @@
+PYSIDE_TEST(qasyncio_test.py)
+PYSIDE_TEST(qasyncio_test_chain.py)
diff --git a/sources/pyside6/tests/QtAsyncio/QtAsyncio.pyproject b/sources/pyside6/tests/QtAsyncio/QtAsyncio.pyproject
new file mode 100644
index 000000000..a36dcd5ad
--- /dev/null
+++ b/sources/pyside6/tests/QtAsyncio/QtAsyncio.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["qt_asyncio_test.py", "qt_asyncio_test_chain.py", "qt_asyncio_test_time.py"]
+}
diff --git a/sources/pyside6/tests/QtAsyncio/qasyncio_test.py b/sources/pyside6/tests/QtAsyncio/qasyncio_test.py
new file mode 100644
index 000000000..f3c971285
--- /dev/null
+++ b/sources/pyside6/tests/QtAsyncio/qasyncio_test.py
@@ -0,0 +1,51 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for QtAsyncio'''
+
+import unittest
+import asyncio
+
+from PySide6.QtAsyncio import QAsyncioEventLoopPolicy
+
+
+class QAsyncioTestCase(unittest.TestCase):
+ async def sleep(self, output):
+ output += "Hello"
+ await asyncio.sleep(0.2)
+ output += "World"
+
+ async def gather(self, output):
+ await asyncio.gather(self.sleep(output), self.sleep(output), self.sleep(output))
+
+ def test_sleep(self):
+ outputs_expected = []
+ outputs_real = []
+
+ # Run the code without QAsyncioEventLoopPolicy
+ asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy())
+ asyncio.run(self.sleep(outputs_expected))
+
+ # Run the code with QAsyncioEventLoopPolicy and QtEventLoop
+ asyncio.set_event_loop_policy(QAsyncioEventLoopPolicy())
+ asyncio.run(self.sleep(outputs_real))
+
+ self.assertEqual(outputs_expected, outputs_real)
+
+ def test_gather(self):
+ outputs_expected = []
+ outputs_real = []
+
+ # Run the code without QAsyncioEventLoopPolicy
+ asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy())
+ asyncio.run(self.gather(outputs_expected))
+
+ # Run the code with QAsyncioEventLoopPolicy and QtEventLoop
+ asyncio.set_event_loop_policy(QAsyncioEventLoopPolicy())
+ asyncio.run(self.gather(outputs_real))
+
+ self.assertEqual(outputs_expected, outputs_real)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtAsyncio/qasyncio_test_cancel_task.py b/sources/pyside6/tests/QtAsyncio/qasyncio_test_cancel_task.py
new file mode 100644
index 000000000..7ef2bb90d
--- /dev/null
+++ b/sources/pyside6/tests/QtAsyncio/qasyncio_test_cancel_task.py
@@ -0,0 +1,46 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for QtAsyncio'''
+
+import asyncio
+import unittest
+
+import PySide6.QtAsyncio as QtAsyncio
+
+
+class QAsyncioTestCaseCancelTask(unittest.TestCase):
+ # Taken from https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel
+
+ async def cancel_me(self, output):
+ output += "(1) cancel_me(): before sleep"
+
+ try:
+ await asyncio.sleep(10)
+ except asyncio.CancelledError:
+ output += "(2) cancel_me(): cancel sleep"
+ raise
+ finally:
+ output += "(3) cancel_me(): after sleep"
+
+ async def main(self, output):
+ task = asyncio.create_task(self.cancel_me(output))
+ await asyncio.sleep(0.1)
+ task.cancel()
+ try:
+ await task
+ except asyncio.CancelledError:
+ output += "(4) main(): cancel_me is cancelled now"
+
+ def test_await_tasks(self):
+ output_expected = []
+ output_real = []
+
+ asyncio.run(self.main(output_expected))
+ QtAsyncio.run(self.main(output_real), keep_running=False)
+
+ self.assertEqual(output_real, output_expected)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtAsyncio/qasyncio_test_cancel_taskgroup.py b/sources/pyside6/tests/QtAsyncio/qasyncio_test_cancel_taskgroup.py
new file mode 100644
index 000000000..aa8ce4718
--- /dev/null
+++ b/sources/pyside6/tests/QtAsyncio/qasyncio_test_cancel_taskgroup.py
@@ -0,0 +1,57 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for QtAsyncio'''
+
+import asyncio
+import unittest
+
+import PySide6.QtAsyncio as QtAsyncio
+
+
+class QAsyncioTestCaseCancelTaskGroup(unittest.TestCase):
+ def setUp(self) -> None:
+ super().setUp()
+ # We only reach the end of the loop if the task is not cancelled.
+ self.loop_end_reached = False
+
+ async def raise_error(self):
+ raise RuntimeError
+
+ async def loop_short(self):
+ self._loop_end_reached = False
+ for _ in range(1000):
+ await asyncio.sleep(1e-3)
+ self._loop_end_reached = True
+
+ async def loop_shorter(self):
+ self._loop_end_reached = False
+ for _ in range(1000):
+ await asyncio.sleep(1e-4)
+ self._loop_end_reached = True
+
+ async def loop_the_shortest(self):
+ self._loop_end_reached = False
+ for _ in range(1000):
+ await asyncio.to_thread(lambda: None)
+ self._loop_end_reached = True
+
+ async def main(self, coro):
+ async with asyncio.TaskGroup() as tg:
+ tg.create_task(coro())
+ tg.create_task(self.raise_error())
+
+ def test_cancel_taskgroup(self):
+ coros = [self.loop_short, self.loop_shorter, self.loop_the_shortest]
+
+ for coro in coros:
+ try:
+ QtAsyncio.run(self.main(coro), keep_running=False)
+ except ExceptionGroup as e:
+ self.assertEqual(len(e.exceptions), 1)
+ self.assertIsInstance(e.exceptions[0], RuntimeError)
+ self.assertFalse(self._loop_end_reached)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtAsyncio/qasyncio_test_chain.py b/sources/pyside6/tests/QtAsyncio/qasyncio_test_chain.py
new file mode 100644
index 000000000..a0a949720
--- /dev/null
+++ b/sources/pyside6/tests/QtAsyncio/qasyncio_test_chain.py
@@ -0,0 +1,57 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for QtAsyncio'''
+
+import unittest
+import asyncio
+import random
+import time
+
+from PySide6.QtAsyncio import QAsyncioEventLoopPolicy
+
+
+class QAsyncioTestCaseChain(unittest.TestCase):
+
+ async def link(self, output, n, i):
+ t = random.randint(0, 5)
+ output += f"link {i}({n}): {t}s "
+ await asyncio.sleep(i)
+ result = f"result {n}-{i}"
+ output += f"link {i}({n}) finished with {result} "
+ return result
+
+ async def chain(self, output, n):
+ link1 = await self.link(output, n, 0.2)
+ link2 = await self.link(output, n, 0.5)
+ output += f"chain {n}: {link1} -> {link2} "
+
+ async def gather(self, output, *args):
+ await asyncio.gather(*(self.chain(output, n) for n in args))
+
+ def test_chain(self):
+ args = [1, 2, 3]
+
+ outputs_expected = []
+ outputs_real = []
+
+ # Run the code without QAsyncioEventLoopPolicy
+ random.seed(17)
+ asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy())
+ start = time.perf_counter()
+ asyncio.run(self.gather(outputs_expected, *args))
+ end_expected = time.perf_counter() - start
+
+ # Run the code with QAsyncioEventLoopPolicy and QtEventLoop
+ random.seed(17)
+ asyncio.set_event_loop_policy(QAsyncioEventLoopPolicy())
+ start = time.perf_counter()
+ asyncio.run(self.gather(outputs_real, *args))
+ end_real = time.perf_counter() - start
+
+ self.assertEqual(outputs_expected, outputs_real)
+ self.assertAlmostEqual(end_expected, end_real, delta=0.5)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtAsyncio/qasyncio_test_executor.py b/sources/pyside6/tests/QtAsyncio/qasyncio_test_executor.py
new file mode 100644
index 000000000..25e680b39
--- /dev/null
+++ b/sources/pyside6/tests/QtAsyncio/qasyncio_test_executor.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for QtAsyncio'''
+
+import unittest
+import asyncio
+
+from concurrent.futures import ThreadPoolExecutor
+
+from PySide6.QtCore import QThread
+from PySide6.QtAsyncio import QAsyncioEventLoopPolicy
+
+
+class QAsyncioTestCaseExecutor(unittest.TestCase):
+ def setUp(self) -> None:
+ super().setUp()
+ self.executor_thread = None
+
+ def tearDown(self) -> None:
+ super().tearDown()
+
+ def blocking_function(self):
+ self.executor_thread = QThread.currentThread()
+ return 42
+
+ async def run_asyncio_executor(self):
+ main_thread = QThread.currentThread()
+ with ThreadPoolExecutor(max_workers=2) as executor:
+ result = await asyncio.get_running_loop().run_in_executor(
+ executor, self.blocking_function)
+
+ # Assert that we are back to the main thread.
+ self.assertEqual(QThread.currentThread(), main_thread)
+
+ # Assert that the blocking function was executed in a different thread.
+ self.assertNotEqual(self.executor_thread, main_thread)
+
+ self.assertEqual(result, 42)
+
+ def test_qasyncio_executor(self):
+ asyncio.set_event_loop_policy(QAsyncioEventLoopPolicy())
+ asyncio.run(self.run_asyncio_executor())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtAsyncio/qasyncio_test_queues.py b/sources/pyside6/tests/QtAsyncio/qasyncio_test_queues.py
new file mode 100644
index 000000000..0bd98c361
--- /dev/null
+++ b/sources/pyside6/tests/QtAsyncio/qasyncio_test_queues.py
@@ -0,0 +1,70 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for QtAsyncio'''
+
+import unittest
+import asyncio
+import random
+import time
+
+from PySide6.QtAsyncio import QAsyncioEventLoopPolicy
+
+
+class QAsyncioTestCaseQueues(unittest.TestCase):
+
+ async def produce(self, output, queue):
+ for _ in range(random.randint(0, 2)):
+ await asyncio.sleep(random.random())
+ await queue.put(self.i)
+ output += f"{self.i} added to queue\n"
+ self.i += 1
+
+ async def consume(self, output, queue):
+ while True:
+ await asyncio.sleep(random.random())
+ i = await queue.get()
+ output += f"{i} pulled from queue\n"
+ queue.task_done()
+
+ async def main(self, output1, output2, num_producers, num_consumers):
+ self.i = 0
+ queue = asyncio.Queue()
+ producers = [
+ asyncio.create_task(self.produce(output1, queue)) for _ in range(num_producers)]
+ consumers = [
+ asyncio.create_task(self.consume(output2, queue)) for _ in range(num_consumers)]
+ await asyncio.gather(*producers)
+ await queue.join()
+ for consumer in consumers:
+ consumer.cancel()
+
+ def test_queues(self):
+ args = [(2, 3), (2, 1)]
+ for arg in args:
+ outputs_expected1 = []
+ outputs_expected2 = []
+ outputs_real1 = []
+ outputs_real2 = []
+
+ # Run the code without QAsyncioEventLoopPolicy
+ random.seed(17)
+ start = time.perf_counter()
+ asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy())
+ asyncio.run(self.main(outputs_expected1, outputs_expected2, *arg))
+ end_expected = time.perf_counter() - start
+
+ # Run the code with QAsyncioEventLoopPolicy and QtEventLoop
+ random.seed(17)
+ start = time.perf_counter()
+ asyncio.set_event_loop_policy(QAsyncioEventLoopPolicy())
+ asyncio.run(self.main(outputs_real1, outputs_real2, *arg))
+ end_real = time.perf_counter() - start
+
+ self.assertEqual(outputs_expected1, outputs_real1)
+ self.assertEqual(outputs_expected2, outputs_real2)
+ self.assertAlmostEqual(end_expected, end_real, delta=1)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtAsyncio/qasyncio_test_threadsafe.py b/sources/pyside6/tests/QtAsyncio/qasyncio_test_threadsafe.py
new file mode 100644
index 000000000..5b52db239
--- /dev/null
+++ b/sources/pyside6/tests/QtAsyncio/qasyncio_test_threadsafe.py
@@ -0,0 +1,58 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for QtAsyncio'''
+
+import unittest
+import asyncio
+import threading
+import time
+
+from PySide6.QtAsyncio import QAsyncioEventLoopPolicy
+
+
+class QAsyncioTestCaseThreadsafe(unittest.TestCase):
+
+ def setUp(self) -> None:
+ super().setUp()
+ asyncio.set_event_loop_policy(QAsyncioEventLoopPolicy())
+ self.loop_event = asyncio.Event()
+
+ def thread_target(self, is_threadsafe):
+ time.sleep(1)
+ if is_threadsafe:
+ # call_soon_threadsafe() wakes the loop that is in another thread, so the
+ # loop checks the event and will not hang.
+ asyncio.get_event_loop().call_soon_threadsafe(self.loop_event.set)
+ else:
+ # call_soon() does not wake the loop that is in another thread, and so the
+ # loop keeps waiting without checking the event and will hang.
+ asyncio.get_event_loop().call_soon(self.loop_event.set)
+
+ async def coro(self, is_threadsafe):
+ thread = threading.Thread(target=self.thread_target, args=(is_threadsafe,))
+ thread.start()
+
+ task = asyncio.create_task(self.loop_event.wait())
+
+ # The timeout is necessary because the loop will hang for the non-threadsafe case.
+ done, pending = await asyncio.wait([task], timeout=2)
+
+ thread.join()
+
+ if is_threadsafe:
+ self.assertEqual(len(done), 1)
+ self.assertEqual(len(pending), 0)
+ else:
+ self.assertEqual(len(done), 0)
+ self.assertEqual(len(pending), 1)
+
+ def test_not_threadsafe(self):
+ asyncio.run(self.coro(False))
+
+ def test_threadsafe(self):
+ asyncio.run(self.coro(True))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtAsyncio/qasyncio_test_time.py b/sources/pyside6/tests/QtAsyncio/qasyncio_test_time.py
new file mode 100644
index 000000000..07a126644
--- /dev/null
+++ b/sources/pyside6/tests/QtAsyncio/qasyncio_test_time.py
@@ -0,0 +1,49 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for QtAsyncio'''
+
+import unittest
+import asyncio
+import datetime
+
+from PySide6.QtAsyncio import QAsyncioEventLoopPolicy
+
+
+class QAsyncioTestCaseTime(unittest.TestCase):
+
+ def setUp(self):
+ self.previous_time = None
+ self.exception = None
+
+ def display_date(self, end_time, loop):
+ if self.previous_time is not None:
+ try:
+ self.assertAlmostEqual(
+ (datetime.datetime.now() - self.previous_time).total_seconds(), 1, delta=0.1)
+ except AssertionError as e:
+ self.exception = e
+ self.previous_time = datetime.datetime.now()
+ if (loop.time() + 1.0) < end_time:
+ loop.call_later(1, self.display_date, end_time, loop)
+ else:
+ loop.stop()
+
+ def test_time(self):
+ asyncio.set_event_loop_policy(QAsyncioEventLoopPolicy())
+ loop = asyncio.new_event_loop()
+
+ end_time = loop.time() + 3.0
+ loop.call_soon(self.display_date, end_time, loop)
+
+ try:
+ loop.run_forever()
+ finally:
+ loop.close()
+
+ if self.exception is not None:
+ raise self.exception
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtAxContainer/CMakeLists.txt b/sources/pyside6/tests/QtAxContainer/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtAxContainer/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtBluetooth/CMakeLists.txt b/sources/pyside6/tests/QtBluetooth/CMakeLists.txt
new file mode 100644
index 000000000..a075c3c9b
--- /dev/null
+++ b/sources/pyside6/tests/QtBluetooth/CMakeLists.txt
@@ -0,0 +1,2 @@
+PYSIDE_TEST(localdevice.py)
+PYSIDE_TEST(lowenergy_characteristics.py)
diff --git a/sources/pyside6/tests/QtBluetooth/QtBluetooth.pyproject b/sources/pyside6/tests/QtBluetooth/QtBluetooth.pyproject
new file mode 100644
index 000000000..176b335e2
--- /dev/null
+++ b/sources/pyside6/tests/QtBluetooth/QtBluetooth.pyproject
@@ -0,0 +1,4 @@
+{
+ "files": ["localdevice.py",
+ "lowenergy_characteristics.py"]
+}
diff --git a/sources/pyside6/tests/QtBluetooth/localdevice.py b/sources/pyside6/tests/QtBluetooth/localdevice.py
new file mode 100644
index 000000000..21801106f
--- /dev/null
+++ b/sources/pyside6/tests/QtBluetooth/localdevice.py
@@ -0,0 +1,25 @@
+#!/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
+
+'''Test cases for QBluetoothLocalDevice'''
+
+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.QtBluetooth import QBluetoothLocalDevice
+
+
+class QBluetoothLocalDeviceTest(unittest.TestCase):
+ def testInitialization(self):
+ device = QBluetoothLocalDevice()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtBluetooth/lowenergy_characteristics.py b/sources/pyside6/tests/QtBluetooth/lowenergy_characteristics.py
new file mode 100644
index 000000000..0f7298fec
--- /dev/null
+++ b/sources/pyside6/tests/QtBluetooth/lowenergy_characteristics.py
@@ -0,0 +1,51 @@
+#!/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
+
+'''Test cases for QLowEnergyServiceData'''
+
+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 QUuid
+from PySide6.QtBluetooth import (QBluetoothUuid, QLowEnergyServiceData,
+ QLowEnergyDescriptorData,
+ QLowEnergyCharacteristicData)
+
+
+class QLowEnergyCharacteristicsTest(unittest.TestCase):
+
+ def testCharacteristics(self):
+ uuid = QUuid("11111111-1111-1111-1111-111111111111")
+ self.assertFalse(uuid.isNull())
+
+ new_characteristic = QLowEnergyCharacteristicData()
+ bluetooth_uuid = QBluetoothUuid(uuid)
+ new_characteristic.setUuid(bluetooth_uuid)
+ new_characteristic.setValue(b"blabla")
+ new_characteristic.setValueLength(6, 20)
+
+ desc = QLowEnergyDescriptorData()
+ desc.setUuid(bluetooth_uuid)
+ desc.setValue(b"blabla")
+
+ new_characteristic.addDescriptor(desc)
+ self.assertTrue(new_characteristic.isValid())
+
+ data = QLowEnergyServiceData()
+ data.addCharacteristic(new_characteristic)
+
+ characteristics = data.characteristics()
+ self.assertEqual(len(characteristics), 1)
+
+ self.assertEqual(characteristics[0].uuid(), bluetooth_uuid)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCharts/CMakeLists.txt b/sources/pyside6/tests/QtCharts/CMakeLists.txt
new file mode 100644
index 000000000..4d031937a
--- /dev/null
+++ b/sources/pyside6/tests/QtCharts/CMakeLists.txt
@@ -0,0 +1,2 @@
+PYSIDE_TEST(qcharts_test.py)
+PYSIDE_TEST(qcharts_numpy_test.py)
diff --git a/sources/pyside6/tests/QtCharts/QtCharts.pyproject b/sources/pyside6/tests/QtCharts/QtCharts.pyproject
new file mode 100644
index 000000000..6f2bd66f2
--- /dev/null
+++ b/sources/pyside6/tests/QtCharts/QtCharts.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["qcharts_test.py"]
+}
diff --git a/sources/pyside6/tests/QtCharts/qcharts_numpy_test.py b/sources/pyside6/tests/QtCharts/qcharts_numpy_test.py
new file mode 100644
index 000000000..8154020c0
--- /dev/null
+++ b/sources/pyside6/tests/QtCharts/qcharts_numpy_test.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for QCharts/numpy'''
+
+import os
+import sys
+import unittest
+try:
+ import numpy as np
+ HAVE_NUMPY = True
+except ModuleNotFoundError:
+ HAVE_NUMPY = False
+
+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 QCoreApplication
+from PySide6.QtCharts import QLineSeries
+
+
+class QChartsNumpyTestCase(UsesQApplication):
+ '''Tests related to QCharts/numpy'''
+
+ @unittest.skipUnless(HAVE_NUMPY, "requires numpy")
+ def test(self):
+ """PYSIDE-2313: Verify various types."""
+ line_series = QLineSeries()
+ data_types = [np.short, np.ushort, np.int32, np.uint32,
+ np.int64, np.uint64, np.float32, np.float64]
+ for dt in data_types:
+ print("Testing ", dt)
+ old_size = line_series.count()
+ x_arr = np.array([2], dtype=dt)
+ y_arr = np.array([3], dtype=dt)
+ line_series.appendNp(x_arr, y_arr)
+ size = line_series.count()
+ self.assertEqual(size, old_size + 1)
+ point = line_series.points()[size - 1]
+ self.assertEqual(point.x(), 2)
+ self.assertEqual(point.y(), 3)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCharts/qcharts_test.py b/sources/pyside6/tests/QtCharts/qcharts_test.py
new file mode 100644
index 000000000..8d57c07eb
--- /dev/null
+++ b/sources/pyside6/tests/QtCharts/qcharts_test.py
@@ -0,0 +1,46 @@
+#!/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
+
+'''Test cases for QCharts'''
+
+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 QRect, QSize, QTimer
+from PySide6.QtGui import QGuiApplication, QScreen
+from PySide6.QtCharts import QChart, QChartView, QPieSeries
+
+
+class QChartsTestCase(UsesQApplication):
+ '''Tests related to QCharts'''
+
+ def testCharts(self):
+ self.series = QPieSeries()
+ self.series.append("Jane", 1)
+ self.series.append("Joe", 2)
+ self.series.append("Andy", 3)
+ self.series.append("Barbara", 4)
+ self.series.append("Axel", 5)
+ slice = self.series.slices()[1]
+ slice.setExploded()
+ slice.setLabelVisible()
+ self.chart = QChart()
+ self.chart.addSeries(self.series)
+ chartView = QChartView(self.chart)
+ screenSize = QGuiApplication.primaryScreen().geometry().size()
+ chartView.resize(screenSize / 2)
+ chartView.show()
+ QTimer.singleShot(500, self.app.quit)
+ self.app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtConcurrent/CMakeLists.txt b/sources/pyside6/tests/QtConcurrent/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtConcurrent/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtCore/CMakeLists.txt b/sources/pyside6/tests/QtCore/CMakeLists.txt
new file mode 100644
index 000000000..f0228d943
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/CMakeLists.txt
@@ -0,0 +1,148 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+PYSIDE_TEST(attr_cache_py3k.py)
+PYSIDE_TEST(bug_278_test.py)
+PYSIDE_TEST(bug_300_test.py)
+PYSIDE_TEST(bug_324.py)
+PYSIDE_TEST(bug_332.py)
+PYSIDE_TEST(bug_408.py)
+PYSIDE_TEST(bug_428.py)
+PYSIDE_TEST(bug_462.py)
+PYSIDE_TEST(bug_505.py)
+PYSIDE_TEST(bug_515.py)
+PYSIDE_TEST(bug_606.py)
+PYSIDE_TEST(bug_656.py)
+PYSIDE_TEST(bug_686.py)
+PYSIDE_TEST(bug_699.py)
+PYSIDE_TEST(bug_706.py)
+PYSIDE_TEST(bug_820.py)
+PYSIDE_TEST(bug_826.py)
+PYSIDE_TEST(bug_829.py)
+PYSIDE_TEST(bug_835.py)
+PYSIDE_TEST(bug_920.py)
+PYSIDE_TEST(bug_927.py)
+PYSIDE_TEST(bug_931.py)
+PYSIDE_TEST(bug_938.py)
+PYSIDE_TEST(bug_953.py)
+PYSIDE_TEST(bug_987.py)
+PYSIDE_TEST(bug_994.py)
+PYSIDE_TEST(bug_1019.py)
+PYSIDE_TEST(bug_1063.py)
+PYSIDE_TEST(bug_1069.py)
+PYSIDE_TEST(bug_1313.py)
+PYSIDE_TEST(bug_PYSIDE-41.py)
+PYSIDE_TEST(bug_PYSIDE-42.py)
+PYSIDE_TEST(bug_PYSIDE-164.py)
+PYSIDE_TEST(bug_PYSIDE-2745.py)
+PYSIDE_TEST(blocking_signals_test.py)
+PYSIDE_TEST(classinfo_test.py)
+PYSIDE_TEST(child_event_test.py)
+PYSIDE_TEST(deepcopy_test.py)
+PYSIDE_TEST(deletelater_test.py)
+PYSIDE_TEST(destroysignal_test.py)
+PYSIDE_TEST(duck_punching_test.py)
+PYSIDE_TEST(emoji_string_test.py)
+PYSIDE_TEST(errormessages_with_features_test.py)
+PYSIDE_TEST(feature_with_uic_test.py)
+PYSIDE_TEST(hash_test.py)
+PYSIDE_TEST(inherits_test.py)
+PYSIDE_TEST(max_signals.py)
+PYSIDE_TEST(missing_symbols_test.py)
+PYSIDE_TEST(mockclass_test.py)
+PYSIDE_TEST(multiple_feature_test.py)
+PYSIDE_TEST(python_conversion.py)
+PYSIDE_TEST(qabs_test.py)
+PYSIDE_TEST(qabstractitemmodel_test.py)
+PYSIDE_TEST(qanimationgroup_test.py)
+PYSIDE_TEST(qbitarray_test.py)
+PYSIDE_TEST(qbytearray_concatenation_operator_test.py)
+PYSIDE_TEST(qbytearray_operator_iadd_test.py)
+PYSIDE_TEST(qbytearray_operator_test.py)
+PYSIDE_TEST(qbytearray_test.py)
+PYSIDE_TEST(qcalendar_test.py)
+PYSIDE_TEST(qcbor_test.py)
+PYSIDE_TEST(qcollator_test.py)
+PYSIDE_TEST(qcommandlineparser_test.py)
+PYSIDE_TEST(qcoreapplication_argv_test.py)
+PYSIDE_TEST(qcoreapplication_instance_test.py)
+PYSIDE_TEST(qcoreapplication_test.py)
+PYSIDE_TEST(qdatastream_test.py)
+PYSIDE_TEST(qdatetime_test.py)
+PYSIDE_TEST(qdate_test.py)
+PYSIDE_TEST(qdir_test.py)
+PYSIDE_TEST(qeasingcurve_test.py)
+PYSIDE_TEST(qenum_test.py)
+PYSIDE_TEST(qevent_test.py)
+PYSIDE_TEST(qfileinfo_test.py)
+PYSIDE_TEST(qfile_test.py)
+PYSIDE_TEST(qfileread_test.py)
+PYSIDE_TEST(qflags_test.py)
+PYSIDE_TEST(qinstallmsghandler_test.py)
+PYSIDE_TEST(qjsondocument_test.py)
+PYSIDE_TEST(qlinef_test.py)
+PYSIDE_TEST(qlocale_test.py)
+PYSIDE_TEST(qlockfile_test.py)
+PYSIDE_TEST(qmessageauthenticationcode_test.py)
+PYSIDE_TEST(qmetaobject_test.py)
+PYSIDE_TEST(qmetatype_test.py)
+PYSIDE_TEST(qmimedatabase_test.py)
+PYSIDE_TEST(qmodelindex_internalpointer_test.py)
+PYSIDE_TEST(qobject_children_segfault_test.py)
+PYSIDE_TEST(qobject_connect_notify_test.py)
+PYSIDE_TEST(qobject_destructor.py)
+PYSIDE_TEST(qobject_event_filter_test.py)
+PYSIDE_TEST(qobject_inherits_test.py)
+PYSIDE_TEST(qobject_objectproperty_test.py)
+PYSIDE_TEST(qobject_parent_test.py)
+PYSIDE_TEST(qobject_property_test.py)
+PYSIDE_TEST(qobject_protected_methods_test.py)
+PYSIDE_TEST(qobject_test.py)
+PYSIDE_TEST(qobject_timer_event_test.py)
+PYSIDE_TEST(qobject_tr_as_instance_test.py)
+PYSIDE_TEST(qoperatingsystemversion_test.py)
+PYSIDE_TEST(qpoint_test.py)
+PYSIDE_TEST(qprocess_test.py)
+PYSIDE_TEST(qproperty_decorator.py)
+PYSIDE_TEST(qrect_test.py)
+PYSIDE_TEST(qregularexpression_test.py)
+PYSIDE_TEST(qresource_test.py)
+PYSIDE_TEST(qsettings_test.py)
+PYSIDE_TEST(qsize_test.py)
+PYSIDE_TEST(qslot_object_test.py)
+PYSIDE_TEST(qsocketnotifier_test.py)
+PYSIDE_TEST(qsrand_test.py)
+PYSIDE_TEST(qstandardpaths_test.py)
+PYSIDE_TEST(qstorageinfo_test.py)
+PYSIDE_TEST(qstring_test.py)
+PYSIDE_TEST(qsysinfo_test.py)
+PYSIDE_TEST(qtextstream_test.py)
+PYSIDE_TEST(qthread_prod_cons_test.py)
+PYSIDE_TEST(qthread_signal_test.py)
+PYSIDE_TEST(qthread_test.py)
+PYSIDE_TEST(qtimer_singleshot_test.py)
+PYSIDE_TEST(qtimer_timeout_test.py)
+PYSIDE_TEST(qtimezone_test.py)
+PYSIDE_TEST(qtnamespace_test.py)
+PYSIDE_TEST(qurl_test.py)
+PYSIDE_TEST(qurlquery_test.py)
+PYSIDE_TEST(quuid_test.py)
+PYSIDE_TEST(qversionnumber_test.py)
+PYSIDE_TEST(repr_test.py)
+PYSIDE_TEST(setprop_on_ctor_test.py)
+PYSIDE_TEST(signal_sender.py)
+PYSIDE_TEST(snake_prop_feature_test.py)
+PYSIDE_TEST(staticMetaObject_test.py)
+PYSIDE_TEST(static_method_test.py)
+PYSIDE_TEST(thread_signals_test.py)
+PYSIDE_TEST(tr_noop_test.py)
+PYSIDE_TEST(translation_test.py)
+PYSIDE_TEST(unaryoperator_test.py)
+PYSIDE_TEST(unicode_test.py)
+PYSIDE_TEST(versioninfo_test.py)
+PYSIDE_TEST(loggingcategorymacros_test.py)
+PYSIDE_TEST(qrunnable_test.py)
+
+if(X11)
+ PYSIDE_TEST(qhandle_test.py)
+endif()
diff --git a/sources/pyside6/tests/QtCore/QtCore.pyproject b/sources/pyside6/tests/QtCore/QtCore.pyproject
new file mode 100644
index 000000000..bd5951316
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/QtCore.pyproject
@@ -0,0 +1,148 @@
+{
+ "files": ["attr_cache_py3k.py",
+ "blocking_signals_test.py",
+ "bug_1019.py",
+ "bug_1063.py",
+ "bug_1069.py",
+ "bug_1313.py",
+ "bug_278_test.py",
+ "bug_300_test.py",
+ "bug_324.py",
+ "bug_332.py",
+ "bug_408.py",
+ "bug_428.py",
+ "bug_462.py",
+ "bug_505.py",
+ "bug_515.py",
+ "bug_606.py",
+ "bug_656.py",
+ "bug_686.py",
+ "bug_699.py",
+ "bug_706.py",
+ "bug_820.py",
+ "bug_826.py",
+ "bug_829.py",
+ "bug_835.py",
+ "bug_920.py",
+ "bug_927.py",
+ "bug_931.py",
+ "bug_938.py",
+ "bug_953.py",
+ "bug_987.py",
+ "bug_994.py",
+ "bug_PYSIDE-164.py",
+ "bug_PYSIDE-41.py",
+ "bug_PYSIDE-42.py",
+ "child_event_test.py",
+ "classinfo_test.py",
+ "deepcopy_test.py",
+ "deletelater_test.py",
+ "destroysignal_test.py",
+ "duck_punching_test.py",
+ "emoji_string_test.py",
+ "errormessages_with_features_test.py",
+ "feature_with_uic/window.py",
+ "feature_with_uic/window.ui",
+ "feature_with_uic_test.py",
+ "hash_test.py",
+ "inherits_test.py",
+ "loggingcategorymacros_test.py",
+ "max_signals.py",
+ "missing_symbols_test.py",
+ "mockclass_test.py",
+ "multiple_feature_test.py",
+ "python_conversion.py",
+ "qabs_test.py",
+ "qabstractitemmodel_test.py",
+ "qanimationgroup_test.py",
+ "qbitarray_test.py",
+ "qbytearray_concatenation_operator_test.py",
+ "qbytearray_operator_iadd_test.py",
+ "qbytearray_operator_test.py",
+ "qbytearray_test.py",
+ "qcalendar_test.py",
+ "qcbor_test.py",
+ "qcollator_test.py",
+ "qcommandlineparser_test.py",
+ "qcoreapplication_argv_test.py",
+ "qcoreapplication_instance_test.py",
+ "qcoreapplication_test.py",
+ "qdatastream_test.py",
+ "qdate_test.py",
+ "qdatetime_test.py",
+ "qdir_test.py",
+ "qeasingcurve_test.py",
+ "qenum_test.py",
+ "qevent_test.py",
+ "qfile_test.py",
+ "qfileinfo_test.py",
+ "qfileread_test.py",
+ "qflags_test.py",
+ "qhandle_test.py",
+ "qinstallmsghandler_test.py",
+ "qjsondocument_test.py",
+ "qlinef_test.py",
+ "qlocale_test.py",
+ "qlockfile_test.py",
+ "qmessageauthenticationcode_test.py",
+ "qmetaobject_test.py",
+ "qmetatype_test.py",
+ "qmimedatabase_test.py",
+ "qmodelindex_internalpointer_test.py",
+ "qobject_children_segfault_test.py",
+ "qobject_connect_notify_test.py",
+ "qobject_destructor.py",
+ "qobject_event_filter_test.py",
+ "qobject_inherits_test.py",
+ "qobject_objectproperty_test.py",
+ "qobject_parent_test.py",
+ "qobject_property_test.py",
+ "qobject_protected_methods_test.py",
+ "qobject_test.py",
+ "qobject_timer_event_test.py",
+ "qobject_tr_as_instance_test.py",
+ "qoperatingsystemversion_test.py",
+ "qpoint_test.py",
+ "qprocess_test.py",
+ "qproperty_decorator.py",
+ "qrandomgenerator_test.py",
+ "qrect_test.py",
+ "qregularexpression_test.py",
+ "qresource_test.py",
+ "qsettings_test.py",
+ "qsharedmemory_client.py",
+ "qsharedmemory_test.py",
+ "qsize_test.py",
+ "qslot_object_test.py",
+ "qsocketnotifier_test.py",
+ "qsrand_test.py",
+ "qstandardpaths_test.py",
+ "qstorageinfo_test.py",
+ "qstring_test.py",
+ "qsysinfo_test.py",
+ "qtextstream_test.py",
+ "qthread_prod_cons_test.py",
+ "qthread_signal_test.py",
+ "qthread_test.py",
+ "qtimer_singleshot_test.py",
+ "qtimer_timeout_test.py",
+ "qtimezone_test.py",
+ "qtnamespace_test.py",
+ "qurl_test.py",
+ "qurlquery_test.py",
+ "quuid_test.py",
+ "qversionnumber_test.py",
+ "repr_test.py",
+ "resources.qrc",
+ "resources_mc.py",
+ "setprop_on_ctor_test.py",
+ "snake_prop_feature_test.py",
+ "staticMetaObject_test.py",
+ "static_method_test.py",
+ "thread_signals_test.py",
+ "tr_noop_test.py",
+ "translation_test.py",
+ "unaryoperator_test.py",
+ "unicode_test.py",
+ "versioninfo_test.py"]
+}
diff --git a/sources/pyside6/tests/QtCore/attr_cache_py3k.py b/sources/pyside6/tests/QtCore/attr_cache_py3k.py
new file mode 100644
index 000000000..c82dbbea3
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/attr_cache_py3k.py
@@ -0,0 +1,36 @@
+# 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
+
+'''
+Unit tests for attribute cache in Python 3
+
+This is the original code from the bug report
+https://bugreports.qt.io/browse/PYSIDE-60
+'''
+
+import os
+import sys
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QObject
+
+
+class A(QObject):
+ instance = 1
+
+ @classmethod
+ def test(cls):
+ cls.instance
+ cls.instance = cls()
+ assert "<__main__.A(0x" in repr(cls.__dict__['instance'])
+ assert "<__main__.A(0x" in repr(cls.instance)
+ assert "<__main__.A(0x" in repr(type.__getattribute__(cls, 'instance'))
+
+
+if __name__ == "__main__":
+ A.test()
diff --git a/sources/pyside6/tests/QtCore/blocking_signals_test.py b/sources/pyside6/tests/QtCore/blocking_signals_test.py
new file mode 100644
index 000000000..493abb071
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/blocking_signals_test.py
@@ -0,0 +1,154 @@
+# 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 case for QObject.signalsBlocked() and blockSignal()'''
+
+import gc
+import os
+import sys
+from tempfile import mkstemp
+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, QFile, QSignalBlocker
+
+
+class Sender(QObject):
+ mysignal = Signal()
+ mysignal_int_int = Signal(int, int)
+
+
+class TestSignalsBlockedBasic(unittest.TestCase):
+ '''Basic test case for signalsBlocked'''
+
+ def testBasic(self):
+ '''QObject.signalsBlocked() and blockSignals()
+ The signals aren't blocked by default.
+ blockSignals returns the previous value'''
+ obj = QObject()
+ self.assertTrue(not obj.signalsBlocked())
+ self.assertTrue(not obj.blockSignals(True))
+ self.assertTrue(obj.signalsBlocked())
+ self.assertTrue(obj.blockSignals(False))
+ blocker = QSignalBlocker(obj)
+ self.assertTrue(obj.signalsBlocked())
+ blocker.unblock()
+ self.assertTrue(not obj.signalsBlocked())
+ blocker.reblock()
+ self.assertTrue(obj.signalsBlocked())
+ del blocker
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertTrue(not obj.signalsBlocked())
+
+ def testContext(self):
+ obj = QObject()
+ self.assertTrue(not obj.signalsBlocked())
+ with QSignalBlocker(obj):
+ self.assertTrue(obj.signalsBlocked())
+ self.assertTrue(not obj.signalsBlocked())
+
+ def testContextWithAs(self):
+ obj = QObject()
+ self.assertTrue(not obj.signalsBlocked())
+ with QSignalBlocker(obj) as blocker:
+ self.assertTrue(obj.signalsBlocked())
+ self.assertEqual(type(blocker), QSignalBlocker)
+ self.assertTrue(not obj.signalsBlocked())
+
+
+class TestSignalsBlocked(unittest.TestCase):
+ '''Test case to check if the signals are really blocked'''
+
+ def setUp(self):
+ # Set up the basic resources needed
+ self.obj = Sender()
+ self.args = tuple()
+ self.called = False
+
+ def tearDown(self):
+ # Delete used resources
+ del self.obj
+ del self.args
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def callback(self, *args):
+ # Default callback
+ if args == self.args:
+ self.called = True
+ else:
+ raise TypeError("Invalid arguments")
+
+ def testShortCircuitSignals(self):
+ # Blocking of Python short-circuit signals
+ self.obj.mysignal.connect(self.callback)
+
+ self.obj.mysignal.emit()
+ self.assertTrue(self.called)
+
+ self.called = False
+ self.obj.blockSignals(True)
+ self.obj.mysignal.emit()
+ self.assertTrue(not self.called)
+
+ def testPythonSignals(self):
+ # Blocking of Python typed signals
+
+ self.obj.mysignal_int_int.connect(self.callback)
+ self.args = (1, 3)
+
+ self.obj.mysignal_int_int.emit(*self.args)
+ self.assertTrue(self.called)
+
+ self.called = False
+ self.obj.blockSignals(True)
+ self.obj.mysignal_int_int.emit(*self.args)
+ self.assertTrue(not self.called)
+
+
+class TestQFileSignalBlocking(unittest.TestCase):
+ '''Test case for blocking the signal QIODevice.aboutToClose()'''
+
+ def setUp(self):
+ # Set up the needed resources - A temp file and a QFile
+ self.called = False
+ handle, self.filename = mkstemp()
+ os.close(handle)
+
+ self.qfile = QFile(self.filename)
+
+ def tearDown(self):
+ # Release acquired resources
+ os.remove(self.filename)
+ del self.qfile
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def callback(self):
+ # Default callback
+ self.called = True
+
+ def testAboutToCloseBlocking(self):
+ # QIODevice.aboutToClose() blocking
+
+ self.qfile.aboutToClose.connect(self.callback)
+
+ self.assertTrue(self.qfile.open(QFile.ReadOnly))
+ self.qfile.close()
+ self.assertTrue(self.called)
+
+ self.called = False
+ self.qfile.blockSignals(True)
+
+ self.assertTrue(self.qfile.open(QFile.ReadOnly))
+ self.qfile.close()
+ self.assertTrue(not self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_1019.py b/sources/pyside6/tests/QtCore/bug_1019.py
new file mode 100644
index 000000000..4a35956b1
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_1019.py
@@ -0,0 +1,48 @@
+# 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 QCoreApplication, QTimer, Slot
+
+
+class MyTimer (QTimer):
+ def __init__(self):
+ super().__init__()
+ self.startCalled = False
+
+ @Slot()
+ def slotUsedToIncreaseMethodOffset(self):
+ pass
+
+
+class MyTimer2 (MyTimer):
+
+ @Slot()
+ def slotUsedToIncreaseMethodOffset2(self):
+ pass
+
+ def start(self):
+ """ 'Overrides' non-virtual slot QTimer.start()."""
+ self.startCalled = True
+ QCoreApplication.instance().quit()
+
+
+class TestBug1019 (unittest.TestCase):
+ def testIt(self):
+ app = QCoreApplication([])
+ t = MyTimer2()
+ QTimer.singleShot(0, t.start)
+ app.exec()
+ self.assertTrue(t.startCalled)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_1063.py b/sources/pyside6/tests/QtCore/bug_1063.py
new file mode 100644
index 000000000..88c4bb51e
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_1063.py
@@ -0,0 +1,41 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+''' unit test for BUG #1063 '''
+
+import os
+import sys
+import tempfile
+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 QFile, QIODevice, QTextStream
+
+
+class QTextStreamTestCase(unittest.TestCase):
+ def setUp(self):
+ self.temp_file = tempfile.NamedTemporaryFile(delete=False)
+ self.temp_file.close()
+ self.f = QFile(self.temp_file.name)
+ self.f.open(QIODevice.WriteOnly)
+ self.strings = ('foo', 'bar')
+ self.stream = QTextStream(self.f)
+
+ def testIt(self):
+ for s in self.strings:
+ self.stream << s
+
+ self.f.close()
+
+ # make sure we didn't get an empty file
+ self.assertNotEqual(QFile(self.temp_file.name).size(), 0)
+
+ os.unlink(self.temp_file.name)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_1069.py b/sources/pyside6/tests/QtCore/bug_1069.py
new file mode 100644
index 000000000..760918cd9
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_1069.py
@@ -0,0 +1,35 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+''' unit test for BUG #1069 '''
+
+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 QByteArray, QDataStream, QIODevice
+
+
+class QDataStreamOpOverloadTestCase(unittest.TestCase):
+ def setUp(self):
+ self.ba = QByteArray()
+ self.stream = QDataStream(self.ba, QIODevice.WriteOnly)
+
+ def testIt(self):
+ self.stream << "hello"
+ ok = False
+ for c in self.ba:
+ if c != b'\x00':
+ ok = True
+ break
+
+ self.assertEqual(ok, True)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_1313.py b/sources/pyside6/tests/QtCore/bug_1313.py
new file mode 100644
index 000000000..ecc22c43b
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_1313.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
+
+''' unit test for BUG #1313 '''
+
+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
+
+
+class MyQObject(QObject):
+ sig = Signal()
+
+
+demo_coroutine_definition_code = """
+async def demo_coroutine():
+ my_qobject = MyQObject()
+ my_qobject.sig.connect(lambda: None)
+"""
+
+
+exec(demo_coroutine_definition_code)
+
+
+class CoroutineRaisesStopIterationTestCase(unittest.TestCase):
+ def setUp(self):
+ self.coroutine = demo_coroutine()
+
+ def testCoroutine(self):
+ with self.assertRaises(StopIteration):
+ self.coroutine.send(None)
+
+
+def demo_generator():
+ my_qobject = MyQObject()
+ my_qobject.sig.connect(lambda: None)
+ return
+ yield # to make it a generator
+
+
+class GeneratorRaisesStopIterationTestCase(unittest.TestCase):
+ def setUp(self):
+ self.generator = demo_generator()
+
+ def testGenerator(self):
+ with self.assertRaises(StopIteration):
+ self.generator.send(None)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_278_test.py b/sources/pyside6/tests/QtCore/bug_278_test.py
new file mode 100644
index 000000000..8d2f4b47e
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_278_test.py
@@ -0,0 +1,34 @@
+#!/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.QtCore import QObject
+
+
+def setValue(o):
+ values = ['Name']
+ o.setProperty('test1', values)
+
+
+class QQtVersionTest(unittest.TestCase):
+ '''Tests for QVariant conversion of QStringList'''
+
+ def testGet(self):
+ o = QObject()
+ setValue(o)
+ self.assertEqual(o.property('test1'), ['Name'])
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
diff --git a/sources/pyside6/tests/QtCore/bug_300_test.py b/sources/pyside6/tests/QtCore/bug_300_test.py
new file mode 100644
index 000000000..b9768bf9d
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_300_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)
+
+from PySide6.QtCore import QModelIndex, QStringListModel
+
+
+class TestQAbstractItemModelSignals(unittest.TestCase):
+ def sigCallback(self, index, r, c):
+ self._called = True
+
+ def testSignals(self):
+ self._called = False
+ m = QStringListModel()
+ m.rowsAboutToBeInserted[QModelIndex, int, int].connect(self.sigCallback)
+ m.insertRows(0, 3)
+ self.assertTrue(self._called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_324.py b/sources/pyside6/tests/QtCore/bug_324.py
new file mode 100644
index 000000000..0aa17c465
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_324.py
@@ -0,0 +1,43 @@
+# 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 bug 324: http://bugs.openbossa.org/show_bug.cgi?id=324'''
+
+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 QCoreApplication, QObject, Signal
+
+
+class QBug(QObject):
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+
+ def check(self):
+ self.done.emit("abc")
+
+ done = Signal(str)
+
+
+class Bug324(unittest.TestCase):
+
+ def on_done(self, val):
+ self.value = val
+
+ def testBug(self):
+ app = QCoreApplication([])
+ bug = QBug()
+ self.value = ''
+ bug.done.connect(self.on_done)
+ bug.check()
+ self.assertEqual(self.value, 'abc')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_332.py b/sources/pyside6/tests/QtCore/bug_332.py
new file mode 100644
index 000000000..8d55bc87f
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_332.py
@@ -0,0 +1,30 @@
+#!/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.QtCore import QMutex
+
+
+class Lock(QMutex):
+ def tryLock(self, timeout=10):
+ return QMutex.tryLock(self, timeout)
+
+
+class TestBug(unittest.TestCase):
+
+ def testCase(self):
+ l = Lock()
+ l.tryLock() # this cause a assertion
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_408.py b/sources/pyside6/tests/QtCore/bug_408.py
new file mode 100644
index 000000000..30459172c
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_408.py
@@ -0,0 +1,41 @@
+# 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 QIODevice, QTextStream
+
+
+class MyDevice(QIODevice):
+ def __init__(self, txt):
+ super().__init__()
+ self.txt = txt
+ self.ptr = 0
+
+ def readData(self, size):
+ size = min(len(self.txt) - self.ptr, size)
+ retval = self.txt[self.ptr:size]
+ self.ptr += size
+ return retval
+
+
+class QIODeviceTest(unittest.TestCase):
+
+ def testIt(self):
+ device = MyDevice("hello world\nhello again")
+ device.open(QIODevice.ReadOnly)
+
+ s = QTextStream(device)
+ self.assertEqual(s.readLine(), "hello world")
+ self.assertEqual(s.readLine(), "hello again")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_428.py b/sources/pyside6/tests/QtCore/bug_428.py
new file mode 100644
index 000000000..8fb5d4827
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_428.py
@@ -0,0 +1,31 @@
+# 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
+
+
+class MyBaseObject(QObject):
+ def __init__(self, number):
+ self.myMember = 'myMember' + number
+ super().__init__()
+
+
+class QObjectConstructorTest(unittest.TestCase):
+ def testBug(self):
+ for i in range(10):
+ number = str(i)
+ obj = MyBaseObject(number)
+ self.assertEqual(obj.myMember, 'myMember' + number)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_462.py b/sources/pyside6/tests/QtCore/bug_462.py
new file mode 100644
index 000000000..04a42fe08
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_462.py
@@ -0,0 +1,59 @@
+# 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, QCoreApplication, QEvent, QThread
+
+
+class MyEvent(QEvent):
+ def __init__(self, i):
+ print("TYPE:", type(QEvent.User))
+ super().__init__(QEvent.Type(QEvent.User))
+ self.i = i
+
+
+class MyThread (QThread):
+ def __init__(self, owner):
+ super().__init__()
+ self.owner = owner
+
+ def run(self):
+ for i in range(3):
+ e = MyEvent(i)
+ QCoreApplication.postEvent(self.owner, e)
+
+
+class MyBaseObject(QObject):
+ def __init__(self):
+ super().__init__()
+ self.events = []
+ self.t = MyThread(self)
+ self.t.start()
+
+ def customEvent(self, event):
+ self.events.append(event)
+ if len(self.events) == 3:
+ self.t.wait()
+ self.app.quit()
+
+
+class CheckForEventsTypes(unittest.TestCase):
+ def testTypes(self):
+ o = MyBaseObject()
+ o.app = QCoreApplication(sys.argv)
+ o.app.exec()
+ for e in o.events:
+ self.assertTrue(isinstance(e, MyEvent))
+ o.app = None
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_505.py b/sources/pyside6/tests/QtCore/bug_505.py
new file mode 100644
index 000000000..e8655a84e
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_505.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 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
+
+
+class MyBaseObject(QObject):
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+ self.setObjectName("PySide")
+
+ def __del__(self):
+ if self.objectName() != "PySide":
+ raise NameError('Fail')
+
+
+class CheckForEventsTypes(unittest.TestCase):
+ def testDelObject(self):
+ p = MyBaseObject()
+ o = MyBaseObject(p)
+ del o
+ del p
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_515.py b/sources/pyside6/tests/QtCore/bug_515.py
new file mode 100644
index 000000000..4e270a441
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_515.py
@@ -0,0 +1,35 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+""" Unittest for bug #515 """
+""" http://bugs.openbossa.org/show_bug.cgi?id=515 """
+
+import os
+import sys
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QCoreApplication, qAddPostRoutine
+
+
+callCleanup = False
+
+
+def _cleanup():
+ global callCleanup
+ callCleanup = True
+
+
+def _checkCleanup():
+ global callCleanup
+ assert (callCleanup)
+
+
+app = QCoreApplication([])
+qAddPostRoutine(_cleanup)
+qAddPostRoutine(_checkCleanup)
+del app
diff --git a/sources/pyside6/tests/QtCore/bug_606.py b/sources/pyside6/tests/QtCore/bug_606.py
new file mode 100644
index 000000000..4fed16b6e
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_606.py
@@ -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
+
+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.QtCore import QPoint, QPointF
+from PySide6.QtCore import QLine, QLineF
+from PySide6.QtCore import QSize, QSizeF
+
+
+class testCases(unittest.TestCase):
+ def testQPointToTuple(self):
+ p = QPoint(1, 2)
+ self.assertEqual((1, 2), p.toTuple())
+
+ def testQPointFToTuple(self):
+ p = QPointF(1, 2)
+ self.assertEqual((1, 2), p.toTuple())
+
+ def testQLineToTuple(self):
+ l = QLine(1, 2, 3, 4)
+ self.assertEqual((1, 2, 3, 4), l.toTuple())
+
+ def testQLineFToTuple(self):
+ l = QLineF(1, 2, 3, 4)
+ self.assertEqual((1, 2, 3, 4), l.toTuple())
+
+ def testQSizeToTuple(self):
+ s = QSize(1, 2)
+ self.assertEqual((1, 2), s.toTuple())
+
+ def testQSizeFToTuple(self):
+ s = QSizeF(1, 2)
+ self.assertEqual((1, 2), s.toTuple())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_656.py b/sources/pyside6/tests/QtCore/bug_656.py
new file mode 100644
index 000000000..066dc1a02
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_656.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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QCoreApplication
+
+
+class CoreApp(QCoreApplication):
+ def __init__(self, *args):
+ super().__init__(*args)
+ # It shouldn't crash after the __init__ call
+
+
+import sys
+app = CoreApp(sys.argv)
diff --git a/sources/pyside6/tests/QtCore/bug_686.py b/sources/pyside6/tests/QtCore/bug_686.py
new file mode 100644
index 000000000..6425a4b86
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_686.py
@@ -0,0 +1,118 @@
+# 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 (QMutex, QMutexLocker, QReadLocker, QReadWriteLock,
+ QThread, QWriteLocker)
+
+
+class MyWriteThread(QThread):
+ def __init__(self, lock):
+ super().__init__()
+ self.lock = lock
+ self.started = False
+ self.canQuit = False
+
+ def run(self):
+ self.started = True
+ while not self.lock.tryLockForWrite():
+ pass
+ self.canQuit = True
+ self.lock.unlock()
+
+
+class MyReadThread(QThread):
+ def __init__(self, lock):
+ super().__init__()
+ self.lock = lock
+ self.started = False
+ self.canQuit = False
+
+ def run(self):
+ self.started = True
+ while not self.lock.tryLockForRead():
+ pass
+ self.canQuit = True
+ self.lock.unlock()
+
+
+class MyMutexedThread(QThread):
+ def __init__(self, mutex):
+ super().__init__()
+ self.mutex = mutex
+ self.started = False
+ self.canQuit = False
+
+ def run(self):
+ self.started = True
+ while not self.mutex.tryLock():
+ pass
+ self.mutex.unlock()
+ self.canQuit = True
+
+
+class TestQMutex (unittest.TestCase):
+
+ def testReadLocker(self):
+ lock = QReadWriteLock()
+ thread = MyWriteThread(lock)
+
+ with QReadLocker(lock):
+ thread.start()
+ while not thread.started:
+ QThread.msleep(10)
+ self.assertFalse(thread.canQuit)
+
+ self.assertTrue(thread.wait(2000))
+ self.assertTrue(thread.canQuit)
+
+ def testWriteLocker(self):
+ lock = QReadWriteLock()
+ thread = MyReadThread(lock)
+
+ with QWriteLocker(lock):
+ thread.start()
+ while not thread.started:
+ QThread.msleep(10)
+ self.assertFalse(thread.canQuit)
+
+ self.assertTrue(thread.wait(2000))
+ self.assertTrue(thread.canQuit)
+
+ def testMutexLocker(self):
+ mutex = QMutex()
+ thread = MyMutexedThread(mutex)
+
+ with QMutexLocker(mutex):
+ thread.start()
+ while not thread.started:
+ QThread.msleep(10)
+ self.assertFalse(thread.canQuit)
+
+ self.assertTrue(thread.wait(2000))
+ self.assertTrue(thread.canQuit)
+
+ def testWithAsLocker(self):
+ lock = QReadWriteLock()
+ with QReadLocker(lock) as locker:
+ self.assertTrue(isinstance(locker, QReadLocker))
+ with QWriteLocker(lock) as locker:
+ self.assertTrue(isinstance(locker, QWriteLocker))
+ mutex = QMutex()
+ with QMutexLocker(mutex) as locker:
+ self.assertTrue(isinstance(locker, QMutexLocker))
+ with self.assertRaises(TypeError):
+ with QMutexLocker(lock) as locker:
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_699.py b/sources/pyside6/tests/QtCore/bug_699.py
new file mode 100644
index 000000000..02da46ff1
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_699.py
@@ -0,0 +1,30 @@
+# 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, Property
+
+
+class TestBug699 (unittest.TestCase):
+
+ def defClass(self):
+ class Foo (QObject):
+ def foo(self):
+ pass
+
+ prop = Property(foo, foo)
+
+ def testIt(self):
+ self.assertRaises(TypeError, self.defClass)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_706.py b/sources/pyside6/tests/QtCore/bug_706.py
new file mode 100644
index 000000000..7db773240
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_706.py
@@ -0,0 +1,40 @@
+# 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 QAbstractListModel, QCoreApplication, QModelIndex
+
+
+class MyModel (QAbstractListModel):
+ def rowCount(self, parent=None):
+ return 3
+
+
+class TestBug706(unittest.TestCase):
+
+ def mySlot(self, idx, start, end):
+ self.start = start
+ self.end = end
+
+ def testIt(self):
+ self.start = None
+ self.end = None
+
+ app = QCoreApplication([])
+ model = MyModel()
+ model.columnsAboutToBeInserted.connect(self.mySlot)
+ model.columnsAboutToBeInserted.emit(QModelIndex(), 0, 1)
+ self.assertEqual(self.start, 0)
+ self.assertEqual(self.end, 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_820.py b/sources/pyside6/tests/QtCore/bug_820.py
new file mode 100644
index 000000000..ba0d33068
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_820.py
@@ -0,0 +1,82 @@
+# 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 functools
+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, Slot, Signal, SIGNAL
+
+
+def log_exception():
+ def log_exception_decorator(func):
+ @functools.wraps(func)
+ def wrapper(*args, **kwds):
+ try:
+ return func(*args, **kwds)
+ except Exception:
+ raise
+
+ return wrapper
+
+ return log_exception_decorator
+
+
+def log_exception2():
+ def log_exception_decorator(func):
+ def wrapper(*args, **kwds):
+ try:
+ return func(*args, **kwds)
+ except Exception:
+ raise
+
+ return wrapper
+
+ return log_exception_decorator
+
+
+class MyObject(QObject):
+
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+ self._mySlotcalled = False
+ self._mySlot2called = False
+
+ @Slot()
+ @log_exception()
+ def mySlot(self):
+ self._mySlotcalled = True
+
+ @Slot(name="mySlot2")
+ @log_exception2()
+ def mySlot2(self):
+ self._mySlot2called = True
+
+ def poke(self):
+ self.events.emit()
+
+ events = Signal()
+
+
+class SlotWithDecoratorTest(unittest.TestCase):
+ def testSlots(self):
+ o = MyObject()
+ self.assertTrue(o.metaObject().indexOfSlot("mySlot()") > 0)
+ self.assertTrue(o.metaObject().indexOfSlot("mySlot2()") > 0)
+
+ o.events.connect(o.mySlot)
+ o.events.connect(o.mySlot2)
+ o.poke()
+ self.assertTrue(o._mySlotcalled)
+ self.assertTrue(o._mySlot2called)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/bug_826.py b/sources/pyside6/tests/QtCore/bug_826.py
new file mode 100644
index 000000000..95edc0a7c
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_826.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)
+
+from PySide6.QtCore import QEvent, Qt
+import PySide6
+
+
+TEST_EVENT_TYPE = QEvent.Type(QEvent.registerEventType())
+
+
+class TestEvent(QEvent):
+ TestEventType = QEvent.Type(TEST_EVENT_TYPE)
+
+ def __init__(self, rand=0):
+ super().__init__(TestEvent.TestEventType)
+ self._rand = rand
+
+ def getRand(self):
+ return self._rand
+
+
+class TestEnums(unittest.TestCase):
+ def testUserTypesValues(self):
+ self.assertTrue(QEvent.User <= TestEvent.TestEventType <= QEvent.MaxUser)
+ self.assertTrue(QEvent.User <= TEST_EVENT_TYPE <= QEvent.MaxUser)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_829.py b/sources/pyside6/tests/QtCore/bug_829.py
new file mode 100644
index 000000000..9a57e0399
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_829.py
@@ -0,0 +1,54 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2011 Thomas Perl <thp.io/about>
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+# Test case for PySide bug 829
+
+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 QDir, QSettings, QTemporaryFile
+
+
+class QVariantConversions(unittest.TestCase):
+
+ _confFileName = None
+
+ def testDictionary(self):
+ confFile = QTemporaryFile(QDir.tempPath() + '/pysidebug829_XXXXXX.ini')
+ confFile.setAutoRemove(False)
+ self.assertTrue(confFile.open())
+ confFile.close()
+ self._confFileName = confFile.fileName()
+ del confFile
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ s = QSettings(self._confFileName, QSettings.IniFormat)
+ self.assertEqual(s.status(), QSettings.NoError)
+ # Save value
+ s.setValue('x', {1: 'a'})
+ s.sync()
+ self.assertEqual(s.status(), QSettings.NoError)
+ del s
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ # Restore value
+ s = QSettings(self._confFileName, QSettings.IniFormat)
+ self.assertEqual(s.status(), QSettings.NoError)
+ self.assertEqual(s.value('x'), {1: 'a'})
+
+ def __del__(self):
+ if self._confFileName is not None:
+ os.unlink(QDir.toNativeSeparators(self._confFileName))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_835.py b/sources/pyside6/tests/QtCore/bug_835.py
new file mode 100644
index 000000000..6d91b6e0a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_835.py
@@ -0,0 +1,80 @@
+# 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
+
+
+get_counter = 0
+set_counter = 0
+
+
+class Descriptor(object):
+ def __get__(self, obj, owner):
+ global get_counter
+
+ if not obj:
+ return self
+
+ get_counter += 1
+ return obj.var
+
+ def __set__(self, obj, value):
+ global set_counter
+
+ set_counter += 1
+ obj.var = value
+
+
+class FooBar(QObject):
+ test = Descriptor()
+ var = 0
+
+
+class SetAndGetTestCases(unittest.TestCase):
+ def setUp(self):
+ global get_counter
+ global set_counter
+
+ get_counter = 0
+ set_counter = 0
+
+ def testSetMethod(self):
+ global get_counter
+ global set_counter
+
+ f = FooBar()
+
+ f.test = 1
+ self.assertEqual(get_counter, 0)
+ self.assertEqual(set_counter, 1)
+
+ get_counter = 0
+ set_counter = 0
+
+ def testGetMethod(self):
+ global get_counter
+ global set_counter
+
+ f = FooBar()
+ f.test = 1
+ set_counter = 0
+
+ ret = f.test
+ self.assertEqual(get_counter, 1)
+ self.assertEqual(set_counter, 0)
+
+ get_counter = 0
+ set_counter = 0
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_920.py b/sources/pyside6/tests/QtCore/bug_920.py
new file mode 100644
index 000000000..23c8d6201
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_920.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env 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)
+
+import PySide6.QtCore as QtCore
+
+
+class Signaller(QtCore.QObject):
+ s1 = QtCore.Signal()
+ s2 = QtCore.Signal()
+
+
+class TestBug920(unittest.TestCase):
+
+ def testIt(self):
+ s = Signaller()
+ s.s1.connect(self.onSignal)
+ s.s2.connect(self.onSignal)
+ self.assertTrue(s.s1.disconnect(self.onSignal))
+ self.assertTrue(s.s2.disconnect(self.onSignal))
+
+ def onSignal(self):
+ pass
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_927.py b/sources/pyside6/tests/QtCore/bug_927.py
new file mode 100644
index 000000000..c15a7014b
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_927.py
@@ -0,0 +1,50 @@
+# 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 time
+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 QRunnable, QThread, QThreadPool
+
+
+thread_function_called = False
+
+
+class thread_function():
+ global thread_function_called
+ thread_function_called = True
+
+
+class Task(QRunnable):
+ def run(self):
+ QThread.msleep(100)
+
+
+class QThreadPoolTest(unittest.TestCase):
+ def testSlowJobs(self):
+ '''This used to cause a segfault due the ownership control on
+ globalInstance function'''
+ for i in range(3):
+ task = Task()
+ QThreadPool.globalInstance().start(task)
+ time.sleep(0.05)
+
+ self.assertTrue(QThreadPool.globalInstance().waitForDone())
+
+ def testCallable(self):
+ global thread_function_called
+ tp = QThreadPool.globalInstance()
+ tp.start(thread_function)
+ self.assertTrue(tp.waitForDone())
+ self.assertTrue(thread_function_called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_931.py b/sources/pyside6/tests/QtCore/bug_931.py
new file mode 100644
index 000000000..f233c2a26
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_931.py
@@ -0,0 +1,35 @@
+# 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, Signal
+o = QObject()
+
+
+class MyObject(QObject):
+ s = Signal(int)
+
+
+class CheckSignalType(unittest.TestCase):
+ def testSignal(self):
+ self.assertTrue(isinstance(QObject.destroyed, Signal))
+ self.assertEqual(type(QObject.destroyed), Signal)
+
+ self.assertEqual(type(o.destroyed).__name__, "SignalInstance")
+ self.assertNotEqual(type(o.destroyed), Signal)
+
+ self.assertTrue(isinstance(o.destroyed, Signal))
+ self.assertTrue(isinstance(MyObject.s, Signal))
+ self.assertFalse(isinstance(int, Signal))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_938.py b/sources/pyside6/tests/QtCore/bug_938.py
new file mode 100644
index 000000000..3aca25947
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_938.py
@@ -0,0 +1,27 @@
+# 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 QBuffer
+
+
+class TestBug938 (unittest.TestCase):
+
+ def testIt(self):
+ b = QBuffer()
+ b.open(QBuffer.WriteOnly)
+ b.write(bytes("\x0023\x005", "UTF-8"))
+ b.close()
+ self.assertEqual(b.buffer().size(), 5)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_953.py b/sources/pyside6/tests/QtCore/bug_953.py
new file mode 100644
index 000000000..a9cacc97e
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_953.py
@@ -0,0 +1,35 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QCoreApplication, QObject, QTimer
+
+
+class Dispatcher(QObject):
+ _me = None
+
+ def __init__(self):
+ super().__init__()
+ self._me = self
+ QTimer.singleShot(0, self._finish)
+
+ def _finish(self):
+ del self._me # It can't crash here!
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ QTimer.singleShot(10, QCoreApplication.instance().quit)
+
+
+if __name__ == '__main__':
+ app = QCoreApplication([])
+ Dispatcher()
+ app.exec()
diff --git a/sources/pyside6/tests/QtCore/bug_987.py b/sources/pyside6/tests/QtCore/bug_987.py
new file mode 100644
index 000000000..a8c9799e0
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_987.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(False)
+
+from PySide6.QtCore import QObject
+
+
+class TestBug987(unittest.TestCase):
+ def callback(self):
+ pass
+
+ def testInvalidDisconnection(self):
+ o = QObject()
+ self.assertFalse(o.destroyed.disconnect(self.callback))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_994.py b/sources/pyside6/tests/QtCore/bug_994.py
new file mode 100644
index 000000000..464fe3120
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_994.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)
+
+from PySide6.QtCore import QIODevice, QTextStream
+
+
+class MyIODevice (QIODevice):
+ def readData(self, amount):
+ return bytes("\0a" * int(amount / 2), "UTF-8")
+
+ def readLineData(self, maxSize):
+ return bytes("\0b" * 4, "UTF-8")
+
+ def atEnd(self):
+ return False
+
+
+class TestBug944 (unittest.TestCase):
+
+ def testIt(self):
+ device = MyIODevice()
+ device.open(QIODevice.ReadOnly)
+ s = QTextStream(device)
+ self.assertEqual(s.read(4), "\0a\0a")
+ self.assertEqual(device.readLine(), "\0b\0b\0b\0b")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_PYSIDE-164.py b/sources/pyside6/tests/QtCore/bug_PYSIDE-164.py
new file mode 100644
index 000000000..84859af84
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_PYSIDE-164.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 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 QCoreApplication, QEventLoop, QObject, Qt, QThread, Signal
+
+
+class Emitter(QThread):
+
+ signal = Signal(int)
+
+ def __init__(self):
+ super().__init__()
+
+ def run(self):
+ print("Before emit.")
+ self.signal.emit(0)
+ print("After emit.")
+
+
+class Receiver(QObject):
+ def __init__(self, eventloop):
+ super().__init__()
+ self.eventloop = eventloop
+
+ def receive(self, number):
+ print(f"Received number: {number}")
+ self.eventloop.exit(0)
+
+
+class TestBugPYSIDE164(unittest.TestCase):
+
+ def testBlockingSignal(self):
+ app = QCoreApplication.instance() or QCoreApplication([]) # noqa: F841
+ eventloop = QEventLoop()
+ emitter = Emitter()
+ receiver = Receiver(eventloop)
+ emitter.signal.connect(receiver.receive, Qt.BlockingQueuedConnection)
+ emitter.start()
+ retval = eventloop.exec()
+ emitter.wait(2000)
+ self.assertEqual(retval, 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_PYSIDE-2745.py b/sources/pyside6/tests/QtCore/bug_PYSIDE-2745.py
new file mode 100644
index 000000000..3d6c603b7
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_PYSIDE-2745.py
@@ -0,0 +1,37 @@
+# Copyright (C) 2024 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 QTimer
+
+from helper.usesqapplication import UsesQApplication
+
+
+class TestBugPYSIDE2745(UsesQApplication):
+
+ def setUp(self):
+ UsesQApplication.setUp(self)
+ self.counter = 0
+
+ def fail(self):
+ self.counter += 1
+ raise Exception()
+
+ def test_fail(self):
+ QTimer.singleShot(0, self.fail)
+ QTimer.singleShot(0, self.fail)
+ QTimer.singleShot(1, self.app.quit)
+ self.app.exec()
+ self.assertEqual(self.counter, 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_PYSIDE-41.py b/sources/pyside6/tests/QtCore/bug_PYSIDE-41.py
new file mode 100644
index 000000000..2830f8050
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_PYSIDE-41.py
@@ -0,0 +1,49 @@
+# 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 QPersistentModelIndex, QStringListModel
+
+
+class TestBugPYSIDE41(unittest.TestCase):
+
+ def testIt(self):
+
+ # list of single-character strings
+ strings = list('abcdefghijklmnopqrstuvwxyz')
+
+ model = QStringListModel(strings)
+
+ # Test hashing of both QModelIndex and QPersistentModelIndex
+ indexFunctions = []
+ indexFunctions.append(model.index)
+ indexFunctions.append(lambda i: QPersistentModelIndex(model.index(i)))
+
+ for indexFunction in indexFunctions:
+
+ # If two objects compare equal, their hashes MUST also be equal. (The
+ # reverse is not a requirement.)
+ for i, _ in enumerate(strings):
+ index1 = indexFunction(i)
+ index2 = indexFunction(i)
+ self.assertEqual(index1, index2)
+ self.assertEqual(hash(index1), hash(index2))
+
+ # Adding the full set of indexes to itself is a no-op.
+ allIndexes1 = set(indexFunction(i) for i, _ in enumerate(strings))
+ allIndexes2 = set(indexFunction(i) for i, _ in enumerate(strings))
+ allIndexesCombined = allIndexes1 & allIndexes2
+ self.assertEqual(allIndexes1, allIndexesCombined)
+ self.assertEqual(allIndexes2, allIndexesCombined)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/bug_PYSIDE-42.py b/sources/pyside6/tests/QtCore/bug_PYSIDE-42.py
new file mode 100644
index 000000000..b602b7569
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/bug_PYSIDE-42.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)
+
+from PySide6.QtCore import QFile, QObject
+
+
+class TestBugPYSIDE42 (unittest.TestCase):
+
+ def testIt(self):
+ obj1 = QFile()
+ obj2 = QObject()
+ hash1 = hash(obj1)
+ hash2 = hash(obj2)
+
+ self.assertNotEqual(hash1, hash2)
+ self.assertEqual(hash1, hash(obj1))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/child_event_test.py b/sources/pyside6/tests/QtCore/child_event_test.py
new file mode 100644
index 000000000..6b17ddc93
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/child_event_test.py
@@ -0,0 +1,64 @@
+#!/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
+
+'''Test case for QObject.childEvent and QTimer.childEvent overloading'''
+
+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, QTimer, QCoreApplication
+from helper.usesqapplication import UsesQApplication
+
+
+class ExtQObject(QObject):
+ def __init__(self):
+ super().__init__()
+ self.child_event_received = False
+
+ def childEvent(self, event):
+ QObject.childEvent(self, event)
+ self.child_event_received = True
+
+
+class ExtQTimer(QTimer):
+ def __init__(self):
+ super().__init__()
+ self.child_event_received = False
+
+ def childEvent(self, event):
+ QTimer.childEvent(self, event)
+ self.child_event_received = True
+
+
+class TestChildEvent(UsesQApplication):
+ '''Test case for QObject::childEvent and QTimer::childEvent'''
+
+ def setUp(self):
+ UsesQApplication.setUp(self)
+
+ def tearDown(self):
+ UsesQApplication.tearDown(self)
+
+ def testQObject(self):
+ parent = ExtQObject()
+ child = QObject()
+ child.setParent(parent)
+ self.assertTrue(parent.child_event_received)
+
+ def testQTimer(self):
+ parent = ExtQTimer()
+ child = QObject()
+ child.setParent(parent)
+ self.assertTrue(parent.child_event_received)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/classinfo_test.py b/sources/pyside6/tests/QtCore/classinfo_test.py
new file mode 100644
index 000000000..0b0a0b4b6
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/classinfo_test.py
@@ -0,0 +1,114 @@
+# 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 sys
+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, QCoreApplication, ClassInfo
+
+
+class TestClassInfo(unittest.TestCase):
+ def test_metadata(self):
+ @ClassInfo(author='pyside', url='http://www.pyside.org')
+ class MyObject(QObject):
+ pass
+
+ o = MyObject()
+ mo = o.metaObject()
+ self.assertEqual(mo.classInfoCount(), 2)
+
+ ci = mo.classInfo(0) # author
+ self.assertEqual(ci.name(), 'author')
+ self.assertEqual(ci.value(), 'pyside')
+
+ ci = mo.classInfo(1) # url
+ self.assertEqual(ci.name(), 'url')
+ self.assertEqual(ci.value(), 'http://www.pyside.org')
+
+ def test_dictionary(self):
+ @ClassInfo({'author': 'pyside', 'author company': 'The Qt Company'})
+ class MyObject(QObject):
+ pass
+
+ o = MyObject()
+ mo = o.metaObject()
+ self.assertEqual(mo.classInfoCount(), 2)
+
+ ci = mo.classInfo(0) # author
+ self.assertEqual(ci.name(), 'author')
+ self.assertEqual(ci.value(), 'pyside')
+
+ ci = mo.classInfo(1) # url
+ self.assertEqual(ci.name(), 'author company')
+ self.assertEqual(ci.value(), 'The Qt Company')
+
+ def test_verify_metadata_types(self):
+ valid_dict = {'123': '456'}
+
+ invalid_dict_1 = {'123': 456}
+ invalid_dict_2 = {123: 456}
+ invalid_dict_3 = {123: '456'}
+
+ ClassInfo(**valid_dict)
+
+ self.assertRaises(TypeError, ClassInfo, **invalid_dict_1)
+
+ # assertRaises only allows for string keywords, so a `try` must be used here.
+ try:
+ ClassInfo(**invalid_dict_2)
+ self.fail('ClassInfo() accepted invalid_dict_2!')
+ except TypeError:
+ pass
+
+ try:
+ ClassInfo(**invalid_dict_3)
+ self.fail('ClassInfo() accepted invalid_dict_3!')
+ except TypeError:
+ pass
+
+ def test_can_not_use_instance_twice(self):
+ decorator = ClassInfo(author='pyside', url='http://www.pyside.org')
+
+ @decorator
+ class MyObject1(QObject):
+ pass
+
+ class MyObject2(QObject):
+ pass
+
+ self.assertRaises(TypeError, decorator, MyObject2)
+
+ def test_can_only_be_used_on_qobjects(self):
+ def make_info():
+ return ClassInfo(author='pyside')
+
+ def test_function():
+ pass
+ self.assertRaises(TypeError, make_info(), test_function)
+
+ class NotAQObject(object):
+ pass
+ self.assertRaises(TypeError, make_info(), NotAQObject)
+
+ class QObjectSubclass(QObject):
+ pass
+ make_info()(QObjectSubclass)
+
+ class SubclassOfNativeQObjectSubclass(QCoreApplication):
+ pass
+ make_info()(SubclassOfNativeQObjectSubclass)
+
+ class SubclassOfPythonQObjectSubclass(QObjectSubclass):
+ pass
+ make_info()(SubclassOfPythonQObjectSubclass)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/deepcopy_test.py b/sources/pyside6/tests/QtCore/deepcopy_test.py
new file mode 100644
index 000000000..e130628e3
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/deepcopy_test.py
@@ -0,0 +1,102 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+from copy import deepcopy
+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 QByteArray, QDate, QDateTime, QTime, QLine, QLineF
+from PySide6.QtCore import Qt, QSize, QSizeF, QRect, QRectF, QDir, QPoint, QPointF
+try:
+ from PySide6.QtCore import QUuid
+ HAVE_Q = True
+except ImportError:
+ HAVE_Q = False
+
+
+class DeepCopyHelper:
+ def testCopy(self):
+ copy = deepcopy([self.original])[0]
+ self.assertTrue(copy is not self.original)
+ self.assertEqual(copy, self.original)
+
+
+class QByteArrayDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QByteArray(bytes('the quick brown fox jumps over the lazy dog', "UTF-8"))
+
+
+class QDateDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QDate(2010, 11, 22)
+
+
+class QTimeDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QTime(11, 37, 55, 692)
+
+
+class QDateTimeDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QDateTime(2010, 5, 18, 10, 24, 45, 223, Qt.LocalTime)
+
+
+class QSizeDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QSize(42, 190)
+
+
+class QSizeFDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QSizeF(42.7, 190.2)
+
+
+class QRectDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QRect(100, 200, 300, 400)
+
+
+class QRectFDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QRectF(100.33, 200.254, 300.321, 400.123)
+
+
+class QLineDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QLine(1, 2, 3, 4)
+
+
+class QLineFDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QLineF(1.1, 2.2, 3.3, 4.4)
+
+
+class QPointDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QPoint(1, 2)
+
+
+class QPointFDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QPointF(1.1, 2.2)
+
+
+class QDirDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QDir("./")
+
+
+class QUuiCopy(DeepCopyHelper, unittest.TestCase):
+ @unittest.skipUnless(HAVE_Q, "QUuid is currently not supported on this platform.")
+ def setUp(self):
+ self.original = QUuid("67C8770B-44F1-410A-AB9A-F9B5446F13EE")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/deletelater_test.py b/sources/pyside6/tests/QtCore/deletelater_test.py
new file mode 100644
index 000000000..0ee078428
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/deletelater_test.py
@@ -0,0 +1,36 @@
+#!/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
+
+'''Test cases for QTimer.singleShot'''
+
+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, QTimer, QCoreApplication, SIGNAL
+from helper.usesqapplication import UsesQApplication
+
+
+class TestDeleteLater(UsesQApplication):
+ '''Test case for function DeleteLater'''
+
+ def testCase(self):
+ o = QObject()
+ o.deleteLater()
+ del o
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ QTimer.singleShot(100, self.app.quit)
+ self.app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/destroysignal_test.py b/sources/pyside6/tests/QtCore/destroysignal_test.py
new file mode 100644
index 000000000..ad087b489
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/destroysignal_test.py
@@ -0,0 +1,78 @@
+# 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 QTimer, QObject, Signal
+
+
+class TestDestroySignal(unittest.TestCase):
+ def onObjectDestroyed(self, timer):
+ self.assertTrue(isinstance(timer, QObject))
+ self._destroyed = True
+
+ def testSignal(self):
+ self._destroyed = False
+ t = QTimer()
+ t.destroyed[QObject].connect(self.onObjectDestroyed)
+ del t
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ # PYSIDE-535: Why do I need to do it twice, here?
+ gc.collect()
+ self.assertTrue(self._destroyed)
+
+ def testWithParent(self):
+ self._destroyed = False
+ p = QTimer()
+ t = QTimer(p)
+ t.destroyed[QObject].connect(self.onObjectDestroyed)
+ del p
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ # PYSIDE-535: Why do I need to do it twice, here?
+ gc.collect()
+ self.assertTrue(self._destroyed)
+
+
+class Foo(QObject):
+ s = Signal(int)
+
+ def __init__(self):
+ QObject.__init__(self)
+ sys.stderr.write(f"__init__ {id(self):x}\n")
+
+ def __del__(self):
+ sys.stderr.write(f"__del__ {id(self):x}\n")
+
+ def send(self, i):
+ self.s.emit(i)
+
+
+# PYSIDE-2201/2328: This crashed until we introduced a weak reference.
+class TestDestroyNoConnect(unittest.TestCase):
+
+ def testSignalDestroyedMissingReference(self):
+ # This works since it has one reference more to Foo
+ Foo().send(43)
+ # This crashed because we have no reference in the signal.
+ with self.assertRaises(RuntimeError):
+ Foo().s.emit(44)
+
+ def testSignalDestroyedinConnect(self):
+ # PYSIDE-2328: Connect to signal of temporary
+ with self.assertRaises(RuntimeError):
+ Foo().s.connect(None)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/duck_punching_test.py b/sources/pyside6/tests/QtCore/duck_punching_test.py
new file mode 100644
index 000000000..145863c3e
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/duck_punching_test.py
@@ -0,0 +1,89 @@
+#!/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
+
+'''Test case for duck punching new implementations of C++ virtual methods into object instances.'''
+
+import gc
+import os
+import sys
+import types
+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
+from helper.usesqapplication import UsesQApplication
+
+
+def MethodType(func, instance, instanceType):
+ return types.MethodType(func, instance)
+
+
+class Duck(QObject):
+ def __init__(self):
+ super().__init__()
+
+ def childEvent(self, event):
+ QObject.childEvent(self, event)
+
+
+class TestDuckPunchingOnQObjectInstance(UsesQApplication):
+ '''Test case for duck punching new implementations of C++ virtual methods into object instances.'''
+
+ def setUp(self):
+ # Acquire resources
+ self.duck_childEvent_called = False
+ UsesQApplication.setUp(self)
+
+ def tearDown(self):
+ # Release resources
+ del self.duck_childEvent_called
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ UsesQApplication.tearDown(self)
+
+ def testChildEventMonkeyPatch(self):
+ # Test if the new childEvent injected on QObject instance is called from C++
+ parent = QObject()
+
+ def childEvent(obj, event):
+ self.duck_childEvent_called = True
+ parent.childEvent = MethodType(childEvent, parent, QObject)
+ child = QObject()
+ child.setParent(parent)
+ self.assertTrue(self.duck_childEvent_called)
+ # This is done to decrease the refcount of the vm object
+ # allowing the object wrapper to be deleted before the
+ # BindingManager. This is useful when compiling Shiboken
+ # for debug, since the BindingManager destructor has an
+ # assert that checks if the wrapper mapper is empty.
+ parent.childEvent = None
+
+ def testChildEventMonkeyPatchWithInheritance(self):
+ # Test if the new childEvent injected on a QObject's extension class instance is called from C++
+ parent = Duck()
+
+ def childEvent(obj, event):
+ QObject.childEvent(obj, event)
+ self.duck_childEvent_called = True
+ child = QObject()
+ child.setParent(parent)
+ parent.childEvent = MethodType(childEvent, parent, QObject)
+ child = QObject()
+ child.setParent(parent)
+ self.assertTrue(self.duck_childEvent_called)
+ # This is done to decrease the refcount of the vm object
+ # allowing the object wrapper to be deleted before the
+ # BindingManager. This is useful when compiling Shiboken
+ # for debug, since the BindingManager destructor has an
+ # assert that checks if the wrapper mapper is empty.
+ parent.childEvent = None
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/emoji_string_test.py b/sources/pyside6/tests/QtCore/emoji_string_test.py
new file mode 100644
index 000000000..78dee1893
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/emoji_string_test.py
@@ -0,0 +1,51 @@
+# 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
+
+"""
+emoji-string-test.py
+
+This is the original code from the bug report
+https://bugreports.qt.io/browse/PYSIDE-336
+
+The only changes are the emoji constant creation which avoids unicode in the
+source itself, utf8 encoding in line 1 and a short plausibility test to make
+it safely fail.
+"""
+
+import os
+import sys
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QObject, Signal
+
+
+emoji_str = u'\U0001f632' + u' ' # "😲 "
+
+
+class TestStuff(QObject):
+ testsig = Signal(str)
+
+ def a_nop(self, sendMeAnEmoji):
+ print(sendMeAnEmoji)
+ return
+
+ def __init__(self):
+ super().__init__()
+ self.testsig.connect(self.a_nop)
+ self.testsig.emit(emoji_str)
+
+ def plausi(self):
+ # Python 2 may be built with UCS-2 or UCS-4 support.
+ # UCS-2 creates 2 surrogate code points. See
+ # https://stackoverflow.com/questions/30775689/python-length-of-unicode-string-confusion
+ assert len(emoji_str) == 2 if sys.maxunicode > 0xffff else 3
+
+
+if __name__ == "__main__":
+ mything = TestStuff()
+ mything.plausi()
diff --git a/sources/pyside6/tests/QtCore/errormessages_with_features_test.py b/sources/pyside6/tests/QtCore/errormessages_with_features_test.py
new file mode 100644
index 000000000..97c4f942e
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/errormessages_with_features_test.py
@@ -0,0 +1,102 @@
+# 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 PySide6 import QtCore
+from PySide6.QtWidgets import QApplication, QLabel
+
+is_pypy = hasattr(sys, "pypy_version_info")
+if not is_pypy:
+ from PySide6.support import feature
+
+import inspect
+
+"""
+errormessages_with_features_test.py
+-----------------------------------
+
+When errors occur while features are switched, we must always produce a
+valid error message.
+
+This test is in its own file because combining it with
+"snake_prop_feature_test" gave strange interactions with the other tests.
+"""
+
+
+@unittest.skipIf(is_pypy, "__feature__ cannot yet be used with PyPy")
+class ErrormessagesWithFeatures(unittest.TestCase):
+ probe = "called with wrong argument types"
+
+ def setUp(self):
+ qApp or QApplication()
+ feature.reset()
+
+ def tearDown(self):
+ feature.reset()
+ qApp.shutdown()
+
+ def testCorrectErrorMessagesPlain(self):
+ with self.assertRaises(TypeError) as cm:
+ QLabel().setFont(42)
+ print("\n\n" + cm.exception.args[0])
+ self.assertTrue(self.probe in cm.exception.args[0])
+
+ def testCorrectErrorMessagesSnake(self):
+ from __feature__ import snake_case
+ with self.assertRaises(TypeError) as cm:
+ QLabel().set_font(42)
+ print("\n\n" + cm.exception.args[0])
+ self.assertTrue(self.probe in cm.exception.args[0])
+
+ def testCorrectErrorMessagesProp(self):
+ from __feature__ import true_property
+ with self.assertRaises(TypeError) as cm:
+ QLabel().font = 42
+ print("\n\n" + cm.exception.args[0])
+ self.assertTrue(self.probe in cm.exception.args[0])
+
+ def testCorrectErrorMessagesSnakeProp(self):
+ from __feature__ import snake_case, true_property
+ with self.assertRaises(TypeError) as cm:
+ QLabel().font = 42
+ print("\n\n" + cm.exception.args[0])
+ self.assertTrue(self.probe in cm.exception.args[0])
+
+ def testCorrectErrorMessagesClassProp(self):
+ from __feature__ import true_property
+ with self.assertRaises(TypeError) as cm:
+ QApplication.quitOnLastWindowClosed = object
+ print("\n\n" + cm.exception.args[0])
+ self.assertTrue(self.probe in cm.exception.args[0])
+ with self.assertRaises(TypeError) as cm:
+ qApp.quitOnLastWindowClosed = object
+ self.assertTrue(self.probe in cm.exception.args[0])
+
+ def testCorrectErrorMessagesClassSnakeProp(self):
+ from __feature__ import snake_case, true_property
+ with self.assertRaises(TypeError) as cm:
+ QApplication.quit_on_last_window_closed = object
+ print("\n\n" + cm.exception.args[0])
+ self.assertTrue(self.probe in cm.exception.args[0])
+ with self.assertRaises(TypeError) as cm:
+ qApp.quit_on_last_window_closed = object
+ self.assertTrue(self.probe in cm.exception.args[0])
+
+ def testDocIsWorking(self):
+ """
+ make sure that it does not crash when touched
+ """
+ inspect.getdoc(QApplication)
+ inspect.getdoc(QtCore)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/feature_with_uic/window.py b/sources/pyside6/tests/QtCore/feature_with_uic/window.py
new file mode 100644
index 000000000..c55bcaf92
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/feature_with_uic/window.py
@@ -0,0 +1,52 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+ QMetaObject, QObject, QPoint, QRect,
+ QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+ QFont, QFontDatabase, QGradient, QIcon,
+ QImage, QKeySequence, QLinearGradient, QPainter,
+ QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QHBoxLayout, QMainWindow, QMenuBar,
+ QPushButton, QSizePolicy, QStatusBar, QVBoxLayout,
+ QWidget)
+
+class Ui_MainWindow(object):
+ def setupUi(self, MainWindow):
+ if not MainWindow.objectName():
+ MainWindow.setObjectName(u"MainWindow")
+ MainWindow.resize(263, 196)
+ self.centralwidget = QWidget(MainWindow)
+ self.centralwidget.setObjectName(u"centralwidget")
+ self.horizontalLayout = QHBoxLayout(self.centralwidget)
+ self.horizontalLayout.setObjectName(u"horizontalLayout")
+ self.verticalLayout = QVBoxLayout()
+ self.verticalLayout.setObjectName(u"verticalLayout")
+ self.pushButton = QPushButton(self.centralwidget)
+ self.pushButton.setObjectName(u"pushButton")
+
+ self.verticalLayout.addWidget(self.pushButton)
+
+ self.horizontalLayout.addLayout(self.verticalLayout)
+
+ MainWindow.setCentralWidget(self.centralwidget)
+ self.menubar = QMenuBar(MainWindow)
+ self.menubar.setObjectName(u"menubar")
+ self.menubar.setGeometry(QRect(0, 0, 263, 23))
+ MainWindow.setMenuBar(self.menubar)
+ self.statusbar = QStatusBar(MainWindow)
+ self.statusbar.setObjectName(u"statusbar")
+ MainWindow.setStatusBar(self.statusbar)
+
+ self.retranslateUi(MainWindow)
+ self.pushButton.clicked.connect(MainWindow.close)
+
+ QMetaObject.connectSlotsByName(MainWindow)
+ # setupUi
+
+ def retranslateUi(self, MainWindow):
+ MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
+ self.pushButton.setText(QCoreApplication.translate("MainWindow", u"PushButton", None))
+ # retranslateUi
+
diff --git a/sources/pyside6/tests/QtCore/feature_with_uic/window.ui b/sources/pyside6/tests/QtCore/feature_with_uic/window.ui
new file mode 100644
index 000000000..0b85824ea
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/feature_with_uic/window.ui
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>263</width>
+ <height>196</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QPushButton" name="pushButton">
+ <property name="text">
+ <string>PushButton</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>263</width>
+ <height>23</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>pushButton</sender>
+ <signal>clicked()</signal>
+ <receiver>MainWindow</receiver>
+ <slot>close()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>131</x>
+ <y>97</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>131</x>
+ <y>97</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/sources/pyside6/tests/QtCore/feature_with_uic_test.py b/sources/pyside6/tests/QtCore/feature_with_uic_test.py
new file mode 100644
index 000000000..2ffc9970e
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/feature_with_uic_test.py
@@ -0,0 +1,59 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""
+feature_with_uic_test.py
+------------------------
+
+Check if feature switching works with a normal UIC file.
+This crashed due to callbacks into QApplication.
+
+PYSIDE-1626: Switch early in `BindingManager::getOverride`.
+"""
+
+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 QCoreApplication, QLibraryInfo, qVersion
+from PySide6.QtWidgets import QApplication, QMainWindow
+
+# PYSIDE-535: We cannot use __feature__ in PyPy, yet
+try:
+ from __feature__ import snake_case
+
+ from feature_with_uic.window import Ui_MainWindow
+ have_feature = True
+except ImportError:
+ Ui_MainWindow = object
+ have_feature = False
+
+
+class MainWindow(QMainWindow, Ui_MainWindow):
+
+ def __init__(self) -> None:
+ super().__init__()
+ self.setupUi(self)
+
+
+@unittest.skipIf(hasattr(sys, "pypy_version_info"),
+ "__feature__ cannot yet be used with PyPy")
+class FeatureTest(UsesQApplication):
+
+ def testFeaturesWorkWithUIC(self):
+ window = MainWindow()
+ window.set_window_title(qVersion())
+ window.show()
+ while not window.window_handle().is_exposed():
+ QCoreApplication.process_events()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/hash_test.py b/sources/pyside6/tests/QtCore/hash_test.py
new file mode 100644
index 000000000..aee2f516c
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/hash_test.py
@@ -0,0 +1,101 @@
+#!/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.QtCore import QDate, QDateTime, QTime, QUrl
+from PySide6.QtCore import QLine, QPoint, QRect, QSize
+
+
+URL = "https://qt.io/"
+
+
+class HashTest(unittest.TestCase):
+ def testInsert(self):
+ myHash = {}
+ qdate = QDate.currentDate()
+ qdatetime = QDateTime.currentDateTime()
+ qtime = QTime.currentTime()
+ qurl = QUrl(URL)
+ self.assertTrue(qurl.isValid())
+ qpoint = QPoint(12, 42)
+
+ myHash[qdate] = "QDate"
+ myHash[qdatetime] = "QDateTime"
+ myHash[qtime] = "QTime"
+ myHash[qurl] = "QUrl"
+ myHash[qpoint] = "QPoint"
+
+ self.assertEqual(myHash[qdate], "QDate")
+ self.assertEqual(myHash[qdatetime], "QDateTime")
+ self.assertEqual(myHash[qtime], "QTime")
+ self.assertEqual(myHash[qurl], "QUrl")
+ self.assertEqual(myHash[qpoint], "QPoint")
+
+ def testQPointHash(self):
+ p1 = QPoint(12, 34)
+ p2 = QPoint(12, 34)
+ self.assertFalse(p1 is p2)
+ self.assertEqual(p1, p2)
+ self.assertEqual(hash(p1), hash(p2))
+
+ def testQSizeHash(self):
+ s1 = QSize(12, 34)
+ s2 = QSize(12, 34)
+ self.assertFalse(s1 is s2)
+ self.assertEqual(s1, s2)
+ self.assertEqual(hash(s1), hash(s2))
+
+ def testQRectHash(self):
+ r1 = QRect(12, 34, 56, 78)
+ r2 = QRect(12, 34, 56, 78)
+ self.assertFalse(r1 is r2)
+ self.assertEqual(r1, r2)
+ self.assertEqual(hash(r1), hash(r2))
+
+ def testQLineHash(self):
+ l1 = QLine(12, 34, 56, 78)
+ l2 = QLine(12, 34, 56, 78)
+ self.assertFalse(l1 is l2)
+ self.assertEqual(l1, l2)
+ self.assertEqual(hash(l1), hash(l2))
+
+ def testQTimeHash(self):
+ t1 = QTime(5, 5, 5)
+ t2 = QTime(5, 5, 5)
+ self.assertFalse(t1 is t2)
+ self.assertEqual(t1, t2)
+ self.assertEqual(hash(t1), hash(t2))
+
+ def testQDateHash(self):
+ d1 = QDate(1968, 3, 9)
+ d2 = QDate(1968, 3, 9)
+ self.assertFalse(d1 is d2)
+ self.assertEqual(d1, d2)
+ self.assertEqual(hash(d1), hash(d2))
+
+ def testQDateTimeHash(self):
+ d1 = QDateTime(QDate(1968, 3, 9), QTime(5, 5, 5))
+ d2 = QDateTime(QDate(1968, 3, 9), QTime(5, 5, 5))
+ self.assertFalse(d1 is d2)
+ self.assertEqual(d1, d2)
+ self.assertEqual(hash(d1), hash(d2))
+
+ def testQUrlHash(self):
+ u1 = QUrl(URL)
+ u2 = QUrl(URL)
+ self.assertFalse(u1 is u2)
+ self.assertEqual(u1, u2)
+ self.assertEqual(hash(u1), hash(u2))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/inherits_test.py b/sources/pyside6/tests/QtCore/inherits_test.py
new file mode 100644
index 000000000..1422616d8
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/inherits_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)
+
+from PySide6.QtCore import QObject
+
+
+class MyObject(QObject):
+ pass
+
+
+class MainTest(unittest.TestCase):
+ def testInherits(self):
+ o = MyObject()
+ mo = o.metaObject()
+ self.assertEqual(mo.className(), 'MyObject')
+ self.assertTrue(o.inherits('MyObject'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/loggingcategorymacros_test.py b/sources/pyside6/tests/QtCore/loggingcategorymacros_test.py
new file mode 100644
index 000000000..a808f0c3d
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/loggingcategorymacros_test.py
@@ -0,0 +1,84 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+"""Tests for category logging macros qCDebug, qCInfo, qCWarning, qCCritical"""
+
+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 (QLoggingCategory, QtMsgType, qCDebug, qCWarning, qCInfo,
+ qCCritical, qInstallMessageHandler)
+
+param = None
+
+
+def handler(msgt, ctx, msg):
+ global param
+ param = ctx.category + ": " + msg.strip()
+
+
+class TestQLoggingCategory(unittest.TestCase):
+ def setUp(self) -> None:
+ super().setUp()
+ self.defaultCategory = QLoggingCategory("default")
+ self.debugCategory = QLoggingCategory("debug.log", QtMsgType.QtDebugMsg)
+ self.infoCategory = QLoggingCategory("info.log", QtMsgType.QtInfoMsg)
+ self.warningCategory = QLoggingCategory("warning.log", QtMsgType.QtWarningMsg)
+ self.criticalCategory = QLoggingCategory("critical.log", QtMsgType.QtCriticalMsg)
+ qInstallMessageHandler(handler)
+ self.no_devices = 2
+
+ def test_qCDebug(self):
+ qCDebug(self.defaultCategory, "no device")
+ self.assertEqual(param, "default: no device")
+ qCDebug(self.debugCategory, f"devices: {self.no_devices}")
+ self.assertEqual(param, "debug.log: devices: 2")
+
+ # not updated because category is Info which is above Debug
+ # nothing will be printed here
+ qCDebug(self.infoCategory, f"devices: {self.no_devices}")
+ self.assertEqual(param, "debug.log: devices: 2")
+
+ def test_qCInfo(self):
+ qCInfo(self.defaultCategory, "no device")
+ self.assertEqual(param, "default: no device")
+ qCInfo(self.debugCategory, f"devices: {self.no_devices}")
+ self.assertEqual(param, "debug.log: devices: 2")
+ qCInfo(self.infoCategory, f"devices: {self.no_devices}")
+ self.assertEqual(param, "info.log: devices: 2")
+
+ # not updated because category is Warning which is above Info
+ # nothing will be printed here
+ qCInfo(self.warningCategory, f"devices: {self.no_devices}")
+ self.assertEqual(param, "info.log: devices: 2")
+
+ def test_qCWarning(self):
+ qCWarning(self.defaultCategory, "no device")
+ self.assertEqual(param, "default: no device")
+ qCWarning(self.debugCategory, f"devices: {self.no_devices}")
+ self.assertEqual(param, "debug.log: devices: 2")
+ qCWarning(self.warningCategory, f"devices: {self.no_devices}")
+ self.assertEqual(param, "warning.log: devices: 2")
+
+ # not updated because category is Critical which is above Warning
+ # nothing will be printed here
+ qCWarning(self.criticalCategory, f"devices: {self.no_devices}")
+ self.assertEqual(param, "warning.log: devices: 2")
+
+ def test_qCritical(self):
+ qCCritical(self.defaultCategory, "no device")
+ self.assertEqual(param, "default: no device")
+ qCCritical(self.warningCategory, f"devices: {self.no_devices}")
+ self.assertEqual(param, "warning.log: devices: 2")
+ qCCritical(self.criticalCategory, f"devices: {self.no_devices}")
+ self.assertEqual(param, "critical.log: devices: 2")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/max_signals.py b/sources/pyside6/tests/QtCore/max_signals.py
new file mode 100644
index 000000000..95952dfbf
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/max_signals.py
@@ -0,0 +1,48 @@
+# 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, SIGNAL
+
+
+class MyObject(QObject):
+ pass
+
+
+class TestSignalLimitless(unittest.TestCase):
+ SIGNAL_MAX = 100
+
+ def test100DynamicSignals(self):
+
+ self.count = 0
+
+ def onSignal():
+ self.count += 1
+
+ # create 100 dynamic signals
+ o = MyObject()
+ for i in range(self.SIGNAL_MAX):
+ o.connect(SIGNAL(f'sig{i}()'), onSignal)
+
+ # check if the signals are valid
+ m = o.metaObject()
+ for i in range(self.SIGNAL_MAX):
+ self.assertTrue(m.indexOfSignal(f'sig{i}()') > 0)
+
+ # emit all 100 signals
+ for i in range(self.SIGNAL_MAX):
+ o.emit(SIGNAL(f'sig{i}()'))
+
+ self.assertEqual(self.count, self.SIGNAL_MAX)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/missing_symbols_test.py b/sources/pyside6/tests/QtCore/missing_symbols_test.py
new file mode 100644
index 000000000..7cf6d3e3e
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/missing_symbols_test.py
@@ -0,0 +1,28 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''(Very) Simple test case for missing names from QtCore'''
+
+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 QtCore
+
+
+class MissingClasses(unittest.TestCase):
+
+ def testQSettings(self): # Bug 232
+ getattr(QtCore, 'QSettings')
+
+ def testQtTrNoop(self): # Bug 220
+ getattr(QtCore, 'QT_TR_NOOP')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/mockclass_test.py b/sources/pyside6/tests/QtCore/mockclass_test.py
new file mode 100644
index 000000000..c7e465b24
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/mockclass_test.py
@@ -0,0 +1,40 @@
+# 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 case for PySide bug 634
+# http://bugs.pyside.org/show_bug.cgi?id=634
+# Marcus Lindblom <macke@yar.nu>; 2011-02-16
+
+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 QCoreApplication
+
+
+class Mock(object):
+ def __init__(self):
+ self.called = False
+ self.return_value = None
+
+ def __call__(self, *args, **kwargs):
+ self.called = True
+ return self.return_value
+
+
+class MockClassTest(unittest.TestCase):
+ def testMockQCoreApplication(self):
+ mock = Mock()
+ setattr(QCoreApplication, 'instance', mock)
+ QCoreApplication.instance()
+ self.assertTrue(mock.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/multiple_feature_test.py b/sources/pyside6/tests/QtCore/multiple_feature_test.py
new file mode 100644
index 000000000..0f51ace6b
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/multiple_feature_test.py
@@ -0,0 +1,116 @@
+# 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 PySide6.QtCore import QCborArray, QObject
+
+is_pypy = hasattr(sys, "pypy_version_info")
+if not is_pypy:
+ from PySide6.support import feature
+
+from textwrap import dedent
+
+"""
+multiple_feature_test.py
+------------------------
+
+This tests the selectable features in PySide.
+
+The first feature is `snake_case` instead of `camelCase`.
+There is much more to come.
+"""
+
+MethodDescriptorType = type(str.split)
+
+
+def xprint(*args, **kw):
+ if "-v" in sys.argv:
+ print(*args, **kw)
+
+
+@unittest.skipIf(is_pypy, "__feature__ cannot yet be used with PyPy")
+class FeaturesTest(unittest.TestCase):
+
+ def testAllFeatureCombinations(self):
+ """
+ Test for all 256 possible combinations of `__feature__` imports.
+ """
+
+ def tst_bit0(flag, self, bits):
+ if flag == 0:
+ QCborArray.isEmpty
+ QCborArray.__dict__["isEmpty"]
+ with self.assertRaises(AttributeError):
+ QCborArray.is_empty
+ with self.assertRaises(KeyError):
+ QCborArray.__dict__["is_empty"]
+ else:
+ QCborArray.is_empty
+ QCborArray.__dict__["is_empty"]
+ with self.assertRaises(AttributeError):
+ QCborArray.isEmpty
+ with self.assertRaises(KeyError):
+ QCborArray.__dict__["isEmpty"]
+
+ def tst_bit1(flag, self, bits):
+ getter_name = "object_name" if bits & 1 else "objectName"
+ setter_name = "set_object_name" if bits & 1 else "setObjectName"
+ thing = getattr(QObject, getter_name)
+ if flag:
+ self.assertEqual(type(thing), property)
+ with self.assertRaises(AttributeError):
+ getattr(QObject, setter_name)
+ else:
+ self.assertEqual(type(thing), MethodDescriptorType)
+ getattr(QObject, setter_name)
+
+ edict = {}
+ for bit in range(2, 8):
+ # We are cheating here, since the functions are in the globals.
+
+ bit_pow = 1 << bit
+ eval(compile(dedent(f"""
+
+ def tst_bit{bit}(flag, self, bits):
+ if flag == 0:
+ with self.assertRaises(AttributeError):
+ QCborArray.fake_feature_{bit_pow:02x}
+ with self.assertRaises(KeyError):
+ QCborArray.__dict__["fake_feature_{bit_pow:02x}"]
+ else:
+ QCborArray.fake_feature_{bit_pow:02x}
+ QCborArray.__dict__["fake_feature_{bit_pow:02x}"]
+
+ """), "<string>", "exec"), globals(), edict)
+ globals().update(edict)
+ feature_list = feature._really_all_feature_names
+ func_list = [tst_bit0, tst_bit1, tst_bit2, tst_bit3,
+ tst_bit4, tst_bit5, tst_bit6, tst_bit7]
+
+ for idx in range(0x100):
+ feature.reset()
+ config = f"feature_{idx:02x}"
+ xprint()
+ xprint(f"--- Feature Test Config `{config}` ---")
+ xprint("Imports:")
+ for bit in range(8):
+ if idx & 1 << bit:
+ cur_feature = feature_list[bit]
+ text = f"from __feature__ import {cur_feature}"
+ xprint(text)
+ eval(compile(text, "<string>", "exec"), globals(), edict)
+ for bit in range(8):
+ value = idx & 1 << bit
+ func_list[bit](value, self=self, bits=idx)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/python_conversion.py b/sources/pyside6/tests/QtCore/python_conversion.py
new file mode 100644
index 000000000..28a271b61
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/python_conversion.py
@@ -0,0 +1,77 @@
+#!/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
+
+'''Test cases for QLineF'''
+
+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 datetime
+
+from PySide6.QtCore import QTime, QDateTime, QDate
+
+
+class TestDateTimeConversions (unittest.TestCase):
+ def testQDate(self):
+ date = datetime.date(2010, 4, 23)
+ other = QDate(date)
+ self.assertEqual(date.year, other.year())
+ self.assertEqual(date.month, other.month())
+ self.assertEqual(date.day, other.day())
+
+ self.assertEqual(date, other.toPython())
+
+ def testQTime(self):
+ time = datetime.time(11, 14, 0, 1000)
+ other = QTime(time)
+ self.assertEqual(time.hour, other.hour())
+ self.assertEqual(time.minute, other.minute())
+ self.assertEqual(time.second, other.second())
+ self.assertEqual(time.microsecond / 1000, other.msec())
+
+ self.assertEqual(time, other.toPython())
+
+ def testQDateTime(self):
+ dateTime = datetime.datetime(2010, 4, 23, 11, 14, 0, 1000)
+ other = QDateTime(dateTime)
+
+ otherDate = other.date()
+ self.assertEqual(dateTime.year, otherDate.year())
+ self.assertEqual(dateTime.month, otherDate.month())
+ self.assertEqual(dateTime.day, otherDate.day())
+
+ otherTime = other.time()
+ self.assertEqual(dateTime.hour, otherTime.hour())
+ self.assertEqual(dateTime.minute, otherTime.minute())
+ self.assertEqual(dateTime.second, otherTime.second())
+ self.assertEqual(dateTime.microsecond / 1000, otherTime.msec())
+
+ self.assertEqual(dateTime, other.toPython())
+
+ def testQDateTime6arg(self):
+ dateTime = datetime.datetime(2010, 4, 23, 11, 14, 7)
+ other = QDateTime(dateTime)
+
+ otherDate = other.date()
+ self.assertEqual(dateTime.year, otherDate.year())
+ self.assertEqual(dateTime.month, otherDate.month())
+ self.assertEqual(dateTime.day, otherDate.day())
+
+ otherTime = other.time()
+ self.assertEqual(dateTime.hour, otherTime.hour())
+ self.assertEqual(dateTime.minute, otherTime.minute())
+ self.assertEqual(dateTime.second, otherTime.second())
+ self.assertEqual(dateTime.microsecond / 1000, otherTime.msec())
+
+ self.assertEqual(dateTime, other.toPython())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qabs_test.py b/sources/pyside6/tests/QtCore/qabs_test.py
new file mode 100644
index 000000000..2b22b1e17
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qabs_test.py
@@ -0,0 +1,31 @@
+# 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 qAbs
+
+
+class QAbsTest(unittest.TestCase):
+ '''Tests for qAbs'''
+
+ def testBasic(self):
+ def check(x):
+ self.assertEqual(qAbs(x), abs(x))
+
+ check(0)
+ check(-10)
+ check(10)
+ check(10.5)
+ check(-10.5)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qabstractitemmodel_test.py b/sources/pyside6/tests/QtCore/qabstractitemmodel_test.py
new file mode 100644
index 000000000..bb9a2222a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qabstractitemmodel_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(False)
+
+from PySide6.QtCore import (QAbstractItemModel, QAbstractListModel,
+ QIdentityProxyModel, QObject, QPersistentModelIndex,
+ QStringListModel, Qt)
+
+
+class MyModel (QAbstractListModel):
+ pass
+
+
+class TestQModelIndexInternalPointer(unittest.TestCase):
+
+ def testInternalPointer(self):
+ m = MyModel()
+ foo = QObject()
+ idx = m.createIndex(0, 0, foo)
+ check = m.checkIndex(idx, QAbstractItemModel.CheckIndexOption.IndexIsValid
+ | QAbstractItemModel.CheckIndexOption.DoNotUseParent
+ | QAbstractItemModel.CheckIndexOption.ParentIsInvalid)
+ self.assertTrue(check)
+
+ def testPassQPersistentModelIndexAsQModelIndex(self):
+ # Related to bug #716
+ m = MyModel()
+ idx = QPersistentModelIndex()
+ m.span(idx)
+
+ def testQIdentityProxyModel(self):
+ sourceModel = QStringListModel(['item1', 'item2'])
+ sourceIndex = sourceModel.index(0, 0)
+ sourceData = str(sourceModel.data(sourceIndex, Qt.DisplayRole))
+ proxyModel = QIdentityProxyModel()
+ proxyModel.setSourceModel(sourceModel)
+ proxyIndex = proxyModel.mapFromSource(sourceIndex)
+ proxyData = str(proxyModel.data(proxyIndex, Qt.DisplayRole))
+ self.assertEqual(sourceData, proxyData)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/qanimationgroup_test.py b/sources/pyside6/tests/QtCore/qanimationgroup_test.py
new file mode 100644
index 000000000..9b9b0e622
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qanimationgroup_test.py
@@ -0,0 +1,37 @@
+#!/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.QtCore import QCoreApplication, QParallelAnimationGroup, QSequentialAnimationGroup, QTimer
+
+
+class QAnimationGroupTest(unittest.TestCase):
+
+ def testBasic(self):
+ app = QCoreApplication([])
+
+ panim = QParallelAnimationGroup()
+ sanim = QSequentialAnimationGroup()
+ panim.addAnimation(sanim)
+
+ self.assertEqual(sanim.parent(), panim)
+
+ panim.clear()
+
+ self.assertRaises(RuntimeError, lambda: sanim.parent())
+
+ QTimer.singleShot(100, app.quit)
+ app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qbitarray_test.py b/sources/pyside6/tests/QtCore/qbitarray_test.py
new file mode 100644
index 000000000..70452eab1
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qbitarray_test.py
@@ -0,0 +1,134 @@
+#!/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
+
+'''Tests if QBitArray class is iterable and also '~' (__invert__) and bitwise operators'''
+
+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 QBitArray
+
+
+def bool_list_from_qbitarray(qbitarray):
+ '''This function is used instead of a list comprehension because
+ the QBitArray is being tested also to check if it is providing
+ the iterable protocol.
+ '''
+ qbitarray_values = []
+ for i in range(qbitarray.size()):
+ qbitarray_values.append(qbitarray.at(i))
+ return qbitarray_values
+
+
+class QBitArrayIsIterableTest(unittest.TestCase):
+ '''Tests if QBitArray class is iterable and also '~' (__invert__) and bitwise operators'''
+
+ def setUp(self):
+ # Acquire resources
+ self.qbitarray = QBitArray(3)
+ self.qbitarray_values = [True, False, False]
+ # WARNING: do not pythonify the following loop
+ for i in range(len(self.qbitarray_values)):
+ self.qbitarray.setBit(i, self.qbitarray_values[i])
+
+ self.inverted_qbitarray_values = [not bit for bit in self.qbitarray_values]
+
+ self.other_qbitarray = QBitArray(3)
+ self.other_qbitarray_values = [True, True, False]
+ # WARNING: do not pythonify the following loop
+ for i in range(len(self.other_qbitarray_values)):
+ self.other_qbitarray.setBit(i, self.other_qbitarray_values[i])
+
+ def tearDown(self):
+ # Release resources
+ del self.qbitarray
+ del self.other_qbitarray
+ del self.qbitarray_values
+ del self.other_qbitarray_values
+ del self.inverted_qbitarray_values
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testQBitArrayIsIterable(self):
+ # Tests if QBitArray class is iterable
+ qbitarray_is_iterable = True
+ try:
+ bitarray = [bit for bit in self.qbitarray]
+ except:
+ qbitarray_is_iterable = False
+ self.assertTrue(qbitarray_is_iterable)
+
+ def testQBitArrayInvertOperator(self):
+ # Tests QBitArray '~' (__invert__) operator
+ inverted_qbitarray = ~self.qbitarray
+ # WARNING: do not pythonify the following loop, the
+ # iterability of QBitArray class is tested in another place
+ inverted_qbitarray_values = bool_list_from_qbitarray(inverted_qbitarray)
+ self.assertEqual(self.inverted_qbitarray_values, inverted_qbitarray_values)
+
+ def testQBitArrayOrBitwiseOperator(self):
+ # Tests QBitArray '|' (or) operator
+ has_or_bitwise_operator = True
+ ored_qbitarray, ored_bool_list = None, None
+ try:
+ ored_qbitarray = self.qbitarray | self.other_qbitarray
+ ored_bool_list = [b1 | b2 for b1, b2 in zip(self.qbitarray_values, self.other_qbitarray_values)]
+ except:
+ has_or_bitwise_operator = False
+ self.assertTrue(has_or_bitwise_operator)
+ self.assertEqual(bool_list_from_qbitarray(ored_qbitarray), ored_bool_list)
+
+ def testQBitArrayAndBitwiseOperator(self):
+ # Tests QBitArray '&' (and) operator
+ has_and_bitwise_operator = True
+ anded_qbitarray, anded_bool_list = None, None
+ try:
+ anded_qbitarray = self.qbitarray | self.other_qbitarray
+ anded_bool_list = [b1 | b2 for b1, b2 in zip(self.qbitarray_values, self.other_qbitarray_values)]
+ except:
+ has_and_bitwise_operator = False
+ self.assertTrue(has_and_bitwise_operator)
+ self.assertEqual(bool_list_from_qbitarray(anded_qbitarray), anded_bool_list)
+
+ def testQBitArrayXorBitwiseOperator(self):
+ # Tests QBitArray '^' (xor) operator
+ has_xor_bitwise_operator = True
+ xored_qbitarray, xored_bool_list = None, None
+ try:
+ xored_qbitarray = self.qbitarray | self.other_qbitarray
+ xored_bool_list = [b1 | b2 for b1, b2 in zip(self.qbitarray_values, self.other_qbitarray_values)]
+ except:
+ has_xor_bitwise_operator = False
+ self.assertTrue(has_xor_bitwise_operator)
+ self.assertEqual(bool_list_from_qbitarray(xored_qbitarray), xored_bool_list)
+
+
+class QBitArrayGetItemTest(unittest.TestCase):
+ '''Test case for []/__getitem__ operator'''
+
+ def create_bitarray(self, values):
+ '''helper function to create a bit array'''
+ obj = QBitArray(len(values))
+ for i, value in enumerate(values):
+ obj.setBit(i, value)
+ return obj
+
+ def testSequenceProtocol(self):
+ '''QBitArray sequence protocol'''
+ data = [True, False, True]
+ obj = self.create_bitarray(data)
+ for reference, value in zip(data, obj):
+ self.assertEqual(reference, value)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/qbytearray_concatenation_operator_test.py b/sources/pyside6/tests/QtCore/qbytearray_concatenation_operator_test.py
new file mode 100644
index 000000000..aea9778d7
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qbytearray_concatenation_operator_test.py
@@ -0,0 +1,40 @@
+#!/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
+
+'''Test cases for QByteArray concatenation with '+' operator'''
+
+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 QByteArray
+
+
+class QByteArrayConcatenationOperatorTest(unittest.TestCase):
+ '''Test cases for QByteArray concatenation with '+' operator'''
+
+ def testConcatQByteArrayAndPythonString(self):
+ # Test concatenation of a QByteArray with a Python bytes, in this order
+ qba = QByteArray(bytes('foo', "UTF-8"))
+ result = qba + bytes('\x00bar', "UTF-8")
+ self.assertEqual(type(result), QByteArray)
+ self.assertEqual(result, bytes('foo\x00bar', "UTF-8"))
+
+ def testConcatPythonStringAndQByteArray(self):
+ # Test concatenation of a Python bytes with a QByteArray, in this order
+ concat_python_string_add_qbytearray_worked = True
+ qba = QByteArray(bytes('foo', "UTF-8"))
+ result = bytes('bar\x00', "UTF-8") + qba
+ self.assertEqual(type(result), QByteArray)
+ self.assertEqual(result, bytes('bar\x00foo', "UTF-8"))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/qbytearray_operator_iadd_test.py b/sources/pyside6/tests/QtCore/qbytearray_operator_iadd_test.py
new file mode 100644
index 000000000..a2201a716
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qbytearray_operator_iadd_test.py
@@ -0,0 +1,70 @@
+# 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 QByteArray
+from helper.docmodifier import DocModifier
+
+
+class BaseQByteArrayOperatorIAdd(object):
+ '''Base class for QByteArray += operator tests.
+
+ Implementing classes should inherit from unittest.TestCase and implement
+ setUp, setting self.obj and self.orig_obj to the target QByteArray and original
+ one, respectively'''
+
+ __metaclass__ = DocModifier
+
+ def testSingleString(self):
+ '''QByteArray += bytes of size 1'''
+ s = bytes('0', "UTF-8")
+ self.obj += s
+ self.assertEqual(self.obj, self.orig_obj + s)
+ self.assertEqual(self.obj.size(), self.orig_obj.size() + len(s))
+
+ def testString(self):
+ '''QByteArray += bytes of size > 1'''
+ s = bytearray(bytes('dummy', "UTF-8"))
+ self.obj += s # XXx iadd support abytearray
+ self.assertEqual(self.obj, self.orig_obj + s)
+ self.assertEqual(self.obj.size(), self.orig_obj.size() + len(s))
+
+ def testQByteArray(self):
+ '''QByteArray += QByteArray'''
+ s = QByteArray(bytes('array', "UTF-8"))
+ self.obj += s
+ self.assertEqual(self.obj, self.orig_obj + s)
+
+
+class NullQByteArrayOperatorIAdd(unittest.TestCase, BaseQByteArrayOperatorIAdd):
+ '''Test case for operator QByteArray += on null QByteArrays'''
+
+ doc_prefix = 'Null object'
+ doc_filter = lambda x: x.startswith('test')
+
+ def setUp(self):
+ self.obj = QByteArray()
+ self.orig_obj = QByteArray()
+
+
+class ValidQByteArrayOperatorIAdd(unittest.TestCase, BaseQByteArrayOperatorIAdd):
+ '''Test case for operator QByteArray += on valid QByteArrays'''
+
+ doc_prefix = 'Valid object'
+ doc_filter = lambda x: x.startswith('test')
+
+ def setUp(self):
+ self.obj = QByteArray(bytes('some byte array', "UTF-8"))
+ self.orig_obj = QByteArray(bytes('some byte array', "UTF-8"))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qbytearray_operator_test.py b/sources/pyside6/tests/QtCore/qbytearray_operator_test.py
new file mode 100644
index 000000000..0064e4dd6
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qbytearray_operator_test.py
@@ -0,0 +1,92 @@
+#!/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
+
+'''Test cases for QByteArray operators'''
+
+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 QByteArray
+
+
+class QByteArrayOperatorEqual(unittest.TestCase):
+ '''TestCase for operator QByteArray == QByteArray'''
+
+ def testDefault(self):
+ # QByteArray() == QByteArray()
+ obj1 = QByteArray()
+ obj2 = QByteArray()
+ self.assertEqual(obj1, obj2)
+
+ def testSimple(self):
+ # QByteArray(some_string) == QByteArray(some_string)
+ string = bytes('egg snakes', "UTF-8")
+ self.assertEqual(QByteArray(string), QByteArray(string))
+
+ def testPyString(self):
+ # QByteArray(string) == string
+ string = bytes('my test string', "UTF-8")
+ self.assertEqual(QByteArray(string), string)
+
+
+class QByteArrayOperatorAt(unittest.TestCase):
+ '''TestCase for operator QByteArray[]'''
+
+ def testInRange(self):
+ # QByteArray[x] where x is a valid index
+ string = 'abcdefgh'
+ obj = QByteArray(bytes(string, "UTF-8"))
+
+ for i in range(len(string)):
+ self.assertEqual(obj[i], bytes(string[i], "UTF-8"))
+
+ def testInRangeReverse(self):
+ # QByteArray[x] where x is a valid index (reverse order)
+ string = 'abcdefgh'
+ obj = QByteArray(bytes(string, "UTF-8"))
+
+ for i in range(len(string) - 1, 0, -1):
+ self.assertEqual(obj[i], bytes(string[i], "UTF-8"))
+
+ def testOutOfRange(self):
+ # QByteArray[x] where x is out of index
+ string = bytes('1234567', "UTF-8")
+ obj = QByteArray(string)
+ self.assertRaises(IndexError, lambda: obj[len(string)])
+
+ def testNullStrings(self):
+ ba = QByteArray(bytes('\x00', "UTF-8"))
+ self.assertEqual(ba.at(0), '\x00')
+ self.assertEqual(ba[0], bytes('\x00', "UTF-8"))
+
+
+class QByteArrayOperatorLen(unittest.TestCase):
+ '''Test case for __len__ operator of QByteArray'''
+
+ def testBasic(self):
+ '''QByteArray __len__'''
+ self.assertEqual(len(QByteArray()), 0)
+ self.assertEqual(len(QByteArray(bytes('', "UTF-8"))), 0)
+ self.assertEqual(len(QByteArray(bytes(' ', "UTF-8"))), 1)
+ self.assertEqual(len(QByteArray(bytes('yabadaba', "UTF-8"))), 8)
+
+
+class QByteArrayOperatorStr(unittest.TestCase):
+ '''Test case for __str__ operator of QByteArray'''
+
+ def testBasic(self):
+ '''QByteArray __str__'''
+ self.assertEqual(QByteArray().__str__(), str(b''))
+ self.assertEqual(QByteArray(bytes('', "UTF-8")).__str__(), str(b''))
+ self.assertEqual(QByteArray(bytes('aaa', "UTF-8")).__str__(), str(b'aaa'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qbytearray_test.py b/sources/pyside6/tests/QtCore/qbytearray_test.py
new file mode 100644
index 000000000..cb8f9a431
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qbytearray_test.py
@@ -0,0 +1,290 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Unit tests for QByteArray'''
+
+import ctypes
+import os
+import pickle
+import struct
+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 (QByteArray, QSettings, QObject, QDataStream,
+ QIODevice, qCompress, qUncompress)
+
+
+class QByteArrayTestToNumber(unittest.TestCase):
+ def testToNumberInt(self):
+ obj = QByteArray(bytes('37', "UTF8"))
+ self.assertEqual((37, True), obj.toInt())
+
+ def testToNumberUShort(self):
+ obj = QByteArray(bytes('37', "UTF8"))
+ self.assertEqual((37, True), obj.toUShort())
+
+ def testToNumberFloat(self):
+ obj = QByteArray(bytes('37.109', "UTF8"))
+ self.assertEqual((ctypes.c_float(37.109).value, True),
+ obj.toFloat())
+
+ def testToNumberDouble(self):
+ obj = QByteArray(bytes('37.109', "UTF8"))
+ self.assertEqual((ctypes.c_double(37.109).value, True),
+ obj.toDouble())
+
+ def testSetNum(self):
+ b = QByteArray()
+ b.setNum(int(-124124))
+ self.assertEqual(b, "-124124")
+ b = QByteArray()
+ b.setNum(-124124)
+ self.assertEqual(b, "-124124")
+ b = QByteArray()
+ b.setNum(-0.5)
+ self.assertEqual(b, "-0.5")
+
+ def testNumber(self):
+ b = QByteArray.number(int(-124124))
+ self.assertEqual(b, "-124124")
+ b = QByteArray.number(-124124)
+ self.assertEqual(b, "-124124")
+ b = QByteArray.number(-0.5)
+ self.assertEqual(b, "-0.5")
+
+ def testAppend(self):
+ b = QByteArray()
+ b.append(bytes("A", "UTF8"))
+ self.assertEqual(b.size(), 1)
+ b.append(bytes("AB", "UTF8"))
+ self.assertEqual(b.size(), 3)
+
+
+class QByteArraySplit(unittest.TestCase):
+ '''Test case for QByteArray.split'''
+
+ def testPathSeparator(self):
+ # QByteArray.split('/')
+ obj = QByteArray(bytes(unittest.__file__, "UTF8"))
+ self.assertEqual(obj.split('/'), unittest.__file__.split('/'))
+
+
+class QByteArrayData(unittest.TestCase):
+
+ '''Test case for QByteArray.data'''
+
+ def testData(self):
+ url = QByteArray(bytes("http://pyside.org", "UTF8"))
+ self.assertEqual(url.data(), bytes("http://pyside.org", "UTF8"))
+
+ def testDataWithZeros(self):
+ s1 = bytes("123\000321", "UTF8")
+ ba = QByteArray(s1)
+ s2 = ba.data()
+ self.assertEqual(s1, s2)
+ self.assertEqual(s1, ba)
+
+
+class QByteArrayOperatorAtSetter(unittest.TestCase):
+ '''Test case for operator QByteArray[] - __setitem__'''
+
+ def testSetterString(self):
+ '''QByteArray[x] = pythonstring'''
+ obj = QByteArray(bytes('123456', "UTF8"))
+ obj[1] = bytes('0', "UTF8")
+ self.assertEqual(obj, QByteArray(bytes('103456', "UTF8")))
+
+
+class QByteArrayOnQDataStream(unittest.TestCase):
+ '''
+ Bug PYSIDE-232
+ '''
+ def testIt(self):
+ a = QByteArray()
+ b = QDataStream(a, QIODevice.WriteOnly)
+ b.writeUInt16(5000)
+ # The __repr__ not suppose to crash anymore
+ self.assertNotEqual(repr(b), None)
+
+
+class TestBug664(unittest.TestCase):
+ '''
+ QByteArray.data() should return correct data
+ '''
+ def testIt(self):
+ a = QByteArray(bytes('hi 猫', "UTF-8"))
+ self.assertEqual(repr(a), "PySide6.QtCore.QByteArray(b'hi \\xe7\\x8c\\xab')")
+
+
+class QByteArrayOnQVariant(unittest.TestCase):
+ def testQByteArrayOnQVariant(self):
+ a = QSettings().value("some_prop", QByteArray())
+ self.assertEqual(type(a), QByteArray)
+
+
+class TestBug567(unittest.TestCase):
+ '''
+ QByteArray should support slices
+ '''
+ def testIt(self):
+ ba = QByteArray(bytes('1234567890', "UTF8"))
+ self.assertEqual(ba[2:4], '34')
+ self.assertEqual(ba[:4], '1234')
+ self.assertEqual(ba[4:], '567890')
+ self.assertEqual(len(ba[4:1]), 0)
+ self.assertEqual(ba[::-1], '0987654321')
+ self.assertEqual(ba[::2], '13579')
+ self.assertEqual(ba[::-2], '08642')
+ self.assertEqual(ba[2:8:3], '36')
+
+
+class TestPickler(unittest.TestCase):
+ def testIt(self):
+ ba = QByteArray(bytes("321\x00123", "UTF8"))
+ output = pickle.dumps(str(ba))
+ ba2 = pickle.loads(output)
+ self.assertEqual(str(ba), str(ba2))
+
+
+class QByteArrayBug720(unittest.TestCase):
+ def testIt(self):
+ ba = QByteArray(bytes("32\"1\x00123", "UTF8"))
+ self.assertEqual(str(ba), str(bytes("32\"1\x00123", "UTF-8")))
+ self.assertEqual(repr(ba), "PySide6.QtCore.QByteArray(b'32\"1\\x00123')")
+
+
+class QByteArrayImplicitConvert(unittest.TestCase):
+ def testString(self):
+ # No implicit conversions from QByteArray to python string
+ ba = QByteArray(bytes("object name", "UTF8"))
+ obj = QObject()
+ self.assertRaises(TypeError, obj.setObjectName, ba)
+
+
+class QByteArraySliceAssignment(unittest.TestCase):
+ def testIndexAssignment(self):
+ a = QByteArray(bytes('abc', "UTF8"))
+ a[0] = bytes('x', "UTF8")
+ self.assertEqual(a[0], bytes('x', "UTF8"))
+
+ def test_1():
+ a[0] = bytes('xy', "UTF8")
+ self.assertRaises(ValueError, test_1)
+
+ def testSliceAssignmentBytes(self):
+ b = QByteArray(bytes('0123456789', "UTF8"))
+ b[2:8] = bytes('abcdef', "UTF8")
+ self.assertEqual(b[2:8], bytes('abcdef', "UTF8"))
+ # Delete behavior
+ b[2:8] = None
+ self.assertEqual(b, bytes('0189', "UTF8"))
+
+ # number of slots and number of values doesn't match
+ def test_2():
+ b[2:8:2] = bytes('', "UTF8")
+ self.assertRaises(ValueError, test_2)
+ b = QByteArray(bytes('0123456789', "UTF8"))
+ # reverse slice
+ b[5:2:-1] = bytes('ABC', "UTF8")
+ self.assertEqual(b, bytes('012CBA6789', "UTF8"))
+ # step is not 1
+ b[2:9:3] = bytes('XYZ', "UTF8")
+ self.assertEqual(b, bytes('01XCBY67Z9', "UTF8"))
+ b = QByteArray(bytes('0123456789', "UTF8"))
+ b[9:2:-3] = bytes('XYZ', "UTF8")
+ self.assertEqual(b, bytes('012Z45Y78X', "UTF8"))
+
+ def testSliceAssignmentQByteArray(self):
+ b = QByteArray(bytes('0123456789', "UTF8"))
+ b[2:8] = QByteArray(bytes('abcdef', "UTF8"))
+ self.assertEqual(b[2:8], bytes('abcdef', "UTF8"))
+ # shrink
+ b[2:8] = QByteArray(bytes('aaa', "UTF8"))
+ self.assertEqual(b, bytes('01aaa89', "UTF8"))
+ # expand
+ b[2:5] = QByteArray(bytes('uvwxyz', "UTF8"))
+ self.assertEqual(b, bytes('01uvwxyz89', "UTF8"))
+ # Delete behavior
+ b[2:8] = QByteArray()
+ self.assertEqual(b, bytes('0189', "UTF8"))
+
+ b = QByteArray(bytes('0123456789', "UTF8"))
+ # reverse assignment
+ b[5:2:-1] = QByteArray(bytes('ABC', "UTF8"))
+ self.assertEqual(b, bytes('012CBA6789', "UTF8"))
+ # step is not 1
+ b[2:9:3] = QByteArray(bytes('XYZ', "UTF8"))
+ self.assertEqual(b, bytes('01XCBY67Z9', "UTF8"))
+ b = QByteArray(bytes('0123456789', "UTF8"))
+ b[9:2:-3] = QByteArray(bytes('XYZ', "UTF8"))
+ self.assertEqual(b, bytes('012Z45Y78X', "UTF8"))
+
+ def testSliceAssignmentByteArray(self):
+ b = QByteArray(bytes('0123456789', "UTF8"))
+ # replace
+ b[2:8] = bytearray(bytes('abcdef', "UTF8"))
+ self.assertEqual(b[2:8], bytes('abcdef', "UTF8"))
+ # shrink
+ b[2:8] = bytearray(bytes('aaa', "UTF8"))
+ self.assertEqual(b, bytes('01aaa89', "UTF8"))
+ # expand
+ b[2:5] = bytearray(bytes('uvwxyz', "UTF8"))
+ self.assertEqual(b, bytes('01uvwxyz89', "UTF8"))
+ # Delete behavior
+ b[2:8] = bytearray(bytes('', "UTF8"))
+ self.assertEqual(b, bytes('0189', "UTF8"))
+
+ b = QByteArray(bytes('0123456789', "UTF8"))
+ # reverse assignment
+ b[5:2:-1] = bytearray(bytes('ABC', "UTF8"))
+ self.assertEqual(b, bytes('012CBA6789', "UTF8"))
+ # step is not 1
+ b[2:9:3] = bytearray(bytes('XYZ', "UTF8"))
+ self.assertEqual(b, bytes('01XCBY67Z9', "UTF8"))
+ b = QByteArray(bytes('0123456789', "UTF8"))
+ b[9:2:-3] = bytearray(bytes('XYZ', "UTF8"))
+ self.assertEqual(b, bytes('012Z45Y78X', "UTF8"))
+
+ def testBufferProtocol(self):
+ orig_bytes = bytes('0123456789', "UTF8")
+ byte_array = QByteArray(orig_bytes)
+ actual_bytes = bytes(byte_array)
+ self.assertEqual(orig_bytes, actual_bytes)
+
+ def testUnpack(self):
+ b = QByteArray(b'\x19\x00\x00\x00\xc4\t\x00\x00')
+ t = struct.unpack('<ii', b)
+ self.assertEqual(len(t), 2)
+ self.assertEqual(t[0], 25)
+ self.assertEqual(t[1], 2500)
+
+
+class QCompressTest(unittest.TestCase):
+ def testQByteArrayCompression(self):
+ """Compress/uncompress a QByteArray."""
+ data = bytes(10 * 'long redundant sentence bla bla', "UTF8")
+ ba = QByteArray(data)
+ compressed = qCompress(ba)
+ self.assertTrue(len(compressed) < len(data))
+ uncompressed = qUncompress(compressed)
+ self.assertEqual(uncompressed, data)
+
+ def testBufferCompression(self):
+ """Compress/uncompress portions of bytes without converting to
+ QByteArray."""
+ data = bytes(10 * 'long redundant sentence bla bla', "UTF8")
+ used_len = int(len(data) / 2)
+ compressed = qCompress(data, used_len, -1)
+ self.assertTrue(len(compressed) < used_len)
+ uncompressed = qUncompress(compressed.data(), len(compressed))
+ self.assertEqual(uncompressed, data[:used_len])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qcalendar_test.py b/sources/pyside6/tests/QtCore/qcalendar_test.py
new file mode 100644
index 000000000..0137677f3
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qcalendar_test.py
@@ -0,0 +1,29 @@
+#!/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
+
+'''Test cases for QCalendar (5.14)'''
+
+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 QCalendar
+
+
+class TestQCalendar (unittest.TestCase):
+ def testCalendar(self):
+ calendar = QCalendar(QCalendar.System.Gregorian)
+ self.assertTrue(calendar.isGregorian())
+ self.assertEqual(calendar.name(), 'Gregorian')
+ self.assertFalse(calendar.hasYearZero())
+ self.assertEqual(calendar.monthsInYear(2019), 12)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qcbor_test.py b/sources/pyside6/tests/QtCore/qcbor_test.py
new file mode 100644
index 000000000..312c9e5c7
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qcbor_test.py
@@ -0,0 +1,62 @@
+#!/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
+
+'''Test cases for QCbor'''
+
+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 (QByteArray, QCborStreamReader, QCborStreamWriter,
+ QCborTag, QCborValue)
+
+
+class TestCbor(unittest.TestCase):
+ def testReader(self):
+ ba = QByteArray()
+ writer = QCborStreamWriter(ba)
+ writer.append(42)
+ del writer
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertTrue(not ba.isEmpty())
+ reader = QCborStreamReader(ba)
+ self.assertTrue(reader.hasNext())
+ value = reader.toInteger()
+ self.assertEqual(value, 42)
+
+ def testReader(self):
+ ba = QByteArray()
+ writer = QCborStreamWriter(ba)
+ writer.append("hello")
+ del writer
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertTrue(not ba.isEmpty())
+ reader = QCborStreamReader(ba)
+ self.assertTrue(reader.hasNext())
+ if (reader.isByteArray()): # Python 2
+ value = reader.readByteArray()
+ self.assertTrue(value)
+ self.assertEqual(value.data, "hello")
+ else:
+ self.assertTrue(reader.isString())
+ value = reader.readString()
+ self.assertTrue(value)
+ self.assertEqual(value.data, "hello")
+
+ def testValue(self):
+ value = QCborValue('hello')
+ self.assertTrue(value.isString())
+ self.assertEqual(value.toString(), 'hello')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qcollator_test.py b/sources/pyside6/tests/QtCore/qcollator_test.py
new file mode 100644
index 000000000..9d1052b24
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qcollator_test.py
@@ -0,0 +1,43 @@
+#!/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
+
+'''Unit tests for QCollator'''
+
+import ctypes
+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 QCollator, QLocale, Qt
+
+
+class QCollatorTest(unittest.TestCase):
+ def testState(self):
+ c = QCollator()
+ c.setCaseSensitivity(Qt.CaseInsensitive)
+ c.setLocale(QLocale.German)
+
+ print("compare a and b:", c.compare("a", "b"))
+
+ self.assertEqual(c.caseSensitivity(), Qt.CaseInsensitive)
+ self.assertEqual(c.locale(), QLocale(QLocale.German))
+
+ c.setLocale(QLocale.French)
+ c.setNumericMode(True)
+ c.setIgnorePunctuation(True)
+ c.setLocale(QLocale.NorwegianBokmal)
+
+ self.assertEqual(c.caseSensitivity(), Qt.CaseInsensitive)
+ self.assertEqual(c.numericMode(), True)
+ self.assertEqual(c.ignorePunctuation(), True)
+ self.assertEqual(c.locale(), QLocale(QLocale.NorwegianBokmal))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qcommandlineparser_test.py b/sources/pyside6/tests/QtCore/qcommandlineparser_test.py
new file mode 100644
index 000000000..c562065ae
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qcommandlineparser_test.py
@@ -0,0 +1,38 @@
+#!/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
+
+'''Unit tests for QCommandLineParser and QCommandLineOption'''
+
+import ctypes
+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 QCoreApplication, QCommandLineOption, QCommandLineParser
+
+
+class QCommandLineParserTest(unittest.TestCase):
+ def testParser(self):
+ app = QCoreApplication([])
+
+ parser1 = QCommandLineParser()
+ self.assertEqual(parser1.parse(["QtCore_qcommandlineparser_test", "file.txt"]), True)
+ self.assertEqual(parser1.positionalArguments(), ["file.txt"])
+
+ parser2 = QCommandLineParser()
+ self.assertEqual(parser2.addOption(QCommandLineOption("b")), True)
+ self.assertEqual(parser2.parse(["QtCore_qcommandlineparser_test", "-b"]), True)
+ self.assertEqual(parser2.optionNames(), ["b"])
+ self.assertEqual(parser2.isSet("b"), True)
+ self.assertEqual(parser2.values("b"), [])
+ self.assertEqual(parser2.positionalArguments(), [])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qcoreapplication_argv_test.py b/sources/pyside6/tests/QtCore/qcoreapplication_argv_test.py
new file mode 100644
index 000000000..3c8500923
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qcoreapplication_argv_test.py
@@ -0,0 +1,25 @@
+# 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 QCoreApplication
+
+
+class TestQCoreApplication(unittest.TestCase):
+ def testConsoleEncoding(self):
+ """PYSIDE-1425, console encoding on Windows."""
+ arg0 = "Üllrich Ümläut"
+ app = QCoreApplication([arg0])
+ self.assertEqual(app.arguments()[0], arg0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qcoreapplication_instance_test.py b/sources/pyside6/tests/QtCore/qcoreapplication_instance_test.py
new file mode 100644
index 000000000..968765020
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qcoreapplication_instance_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
+
+'''Test cases for QCoreApplication.instance static method'''
+
+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 QCoreApplication
+
+
+class QCoreApplicationInstanceTest(unittest.TestCase):
+ '''Test cases for QCoreApplication.instance static method'''
+
+ def testQCoreApplicationInstance(self):
+ # Tests QCoreApplication.instance()
+ self.assertEqual(QCoreApplication.instance(), None)
+ app = QCoreApplication([])
+ self.assertEqual(QCoreApplication.instance(), app)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/qcoreapplication_test.py b/sources/pyside6/tests/QtCore/qcoreapplication_test.py
new file mode 100644
index 000000000..edd4dc8e2
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qcoreapplication_test.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)
+
+from PySide6.QtCore import QCoreApplication
+
+
+class TestQCoreApplication(unittest.TestCase):
+ def testNoArguments(self):
+ app = QCoreApplication()
+ self.assertIsInstance(app, QCoreApplication)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qdatastream_test.py b/sources/pyside6/tests/QtCore/qdatastream_test.py
new file mode 100644
index 000000000..517f466aa
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qdatastream_test.py
@@ -0,0 +1,326 @@
+#!/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
+
+'''Unit tests for QDataStream'''
+
+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 QBitArray, QByteArray, QIODevice, QDataStream, QDate, QTime, QDateTime
+
+
+def create_bitarray(string):
+ array = QBitArray(len(string))
+ for i, char in enumerate(string):
+ array.setBit(i, char != '0')
+ return array
+
+
+def serialize_bitarray(bit_array):
+ buffer = QByteArray()
+ stream = QDataStream(buffer, QIODevice.WriteOnly)
+ stream << bit_array
+ return buffer
+
+
+class QDataStreamWrite(unittest.TestCase):
+ '''Test case for QDatastream write* functions'''
+
+ def setUp(self):
+ self.ba = QByteArray()
+ self.read = QDataStream(self.ba, QIODevice.ReadOnly)
+ self.write = QDataStream(self.ba, QIODevice.WriteOnly)
+
+ def testWriteUInt8(self):
+ '''QDataStream.writeUInt8 (accepting str of size 1)'''
+ x = 0xFF
+ self.write.writeUInt8(x)
+ y = self.read.readUInt8()
+ self.assertEqual(x, y)
+
+ self.assertRaises(TypeError, self.write.writeUInt8, 'aaaaa')
+
+ def testWriteInt8(self):
+ '''QDataStream.writeInt8 (accepting str of size 1)'''
+ x = 65
+ self.write.writeInt8(chr(x))
+ y = self.read.readInt8()
+ self.assertEqual(x, y)
+
+ self.assertRaises(TypeError, self.write.writeInt8, 'aaaaa')
+
+ def testWriteUInt8Int(self):
+ '''QDataStream.writeUInt8 (accepting integer)'''
+ x = 0xFF
+ self.write.writeUInt8(x)
+ y = self.read.readUInt8()
+ self.assertEqual(x, y)
+
+ def testWriteInt8Int(self):
+ '''QDataStream.writeInt8 (accepting integer)'''
+ x = 65
+ self.write.writeInt8(x)
+ y = self.read.readInt8()
+ self.assertEqual(x, y)
+
+ def testWriteUInt16(self):
+ '''QDataStream.writeUInt16'''
+ x = 0x4423
+ self.write.writeUInt16(x)
+ y = int(self.read.readUInt16())
+ self.assertEqual(x, y)
+
+ def testWriteUInt32(self):
+ '''QDataStream.writeUInt32'''
+ x = 0xdeadbeef
+ self.write.writeUInt32(x)
+ y = int(self.read.readUInt32())
+ self.assertEqual(x, y)
+
+
+class QDataStreamShift(unittest.TestCase):
+ '''Test case for << and >> operators'''
+
+ def setUp(self):
+ self.ba = QByteArray()
+ self.stream = QDataStream(self.ba, QIODevice.WriteOnly)
+ self.read_stream = QDataStream(self.ba, QIODevice.ReadOnly)
+
+ def testQCharValid(self):
+ '''QDataStream <<>> QChar - valid'''
+ self.stream.writeQChar(42)
+
+ res = self.read_stream.readQChar()
+ self.assertEqual(res, chr(42))
+
+ def testQCharNull(self):
+ '''QDataStream <<>> QChar - null'''
+ self.stream.writeQChar(None)
+
+ res = self.read_stream.readQChar()
+ self.assertEqual(res, '\x00')
+
+ def testQByteArrayValid(self):
+ '''QDataStream <<>> QByteArray - valid'''
+ self.stream << QByteArray(bytes("hello", "UTF-8"))
+
+ res = QByteArray()
+
+ self.read_stream >> res
+ self.assertEqual(res, QByteArray(bytes("hello", "UTF-8")))
+
+ def testQByteArrayEmpty(self):
+ '''QDataStream <<>> QByteArray - empty'''
+ self.stream << QByteArray(bytes("", "UTF-8"))
+
+ res = QByteArray()
+
+ self.read_stream >> res
+ self.assertEqual(res, QByteArray(bytes("", "UTF-8")))
+ self.assertTrue(res.isEmpty())
+ self.assertFalse(res.isNull())
+
+ def testQByteArrayNull(self):
+ '''QDataStream <<>> QByteArray - null'''
+ self.stream << QByteArray()
+
+ res = QByteArray()
+
+ self.read_stream >> res
+ self.assertEqual(res, QByteArray())
+ self.assertTrue(res.isEmpty())
+ self.assertTrue(res.isNull())
+
+ def testQStringValid(self):
+ '''QDataStream <<>> QString - valid'''
+ self.stream.writeQString('Ka-boom')
+
+ res = self.read_stream.readQString()
+ self.assertEqual(res, 'Ka-boom')
+
+ def testQStringEmpty(self):
+ '''QDataStream <<>> QString - empty'''
+ self.stream.writeQString('')
+
+ res = self.read_stream.readQString()
+ self.assertEqual(res, '')
+
+ def testQStringNull(self):
+ '''QDataStream <<>> QString - null'''
+ self.stream.writeQString(None)
+
+ res = self.read_stream.readQString()
+ self.assertEqual(res, '')
+
+ def testQBitArrayNull(self):
+ '''QDataStream <<>> QBitArray - null'''
+ self.stream << QBitArray()
+
+ res = QBitArray()
+
+ self.read_stream >> res
+ self.assertEqual(res, QBitArray())
+
+ def testQBitArrayValid(self):
+ '''QDataStream <<>> QBitArray - valid'''
+ self.stream << create_bitarray('01010101')
+
+ res = QBitArray()
+
+ self.read_stream >> res
+ self.assertEqual(res, create_bitarray('01010101'))
+
+ def testQDateNull(self):
+ '''QDataStream <<>> QDate - null'''
+ self.stream << QDate()
+
+ res = QDate()
+
+ self.read_stream >> res
+ self.assertEqual(res, QDate())
+ self.assertFalse(res.isValid())
+ self.assertTrue(res.isNull())
+
+ def testQDateValid(self):
+ '''QDataStream <<>> QDate - valid'''
+ self.stream << QDate(2012, 12, 21)
+
+ res = QDate()
+
+ self.read_stream >> res
+ self.assertEqual(res, QDate(2012, 12, 21))
+ self.assertTrue(res.isValid())
+ self.assertFalse(res.isNull())
+
+ def testQTimeNull(self):
+ '''QDataStream <<>> QTime - null'''
+ self.stream << QTime()
+
+ res = QTime()
+
+ self.read_stream >> res
+ self.assertEqual(res, QTime())
+ self.assertFalse(res.isValid())
+ self.assertTrue(res.isNull())
+
+ def testQTimeValid(self):
+ '''QDataStream <<>> QTime - valid'''
+ self.stream << QTime(12, 12, 21)
+
+ res = QTime()
+
+ self.read_stream >> res
+ self.assertEqual(res, QTime(12, 12, 21))
+ self.assertTrue(res.isValid())
+ self.assertFalse(res.isNull())
+
+ def testQDateTimeNull(self):
+ '''QDataStream <<>> QDateTime - null'''
+
+ self.stream << QDateTime()
+
+ res = QDateTime()
+
+ self.read_stream >> res
+ self.assertEqual(res, QDateTime())
+ self.assertFalse(res.isValid())
+ self.assertTrue(res.isNull())
+
+ def testQDateTimeValid(self):
+ '''QDataStream <<>> QDateTime - valid'''
+ time = QTime(23, 23, 23)
+ date = QDate(2009, 1, 1)
+
+ self.stream << QDateTime(date, time)
+
+ res = QDateTime()
+
+ self.read_stream >> res
+ self.assertEqual(res, QDateTime(date, time))
+ self.assertTrue(res.isValid())
+ self.assertFalse(res.isNull())
+
+
+class QDataStreamShiftBitArray(unittest.TestCase):
+ def _check_bitarray(self, data_set):
+ '''Check the >> operator for the given data set'''
+
+ for data, expectedStatus, expectedString in data_set:
+ stream = QDataStream(data, QIODevice.ReadOnly)
+ string = QBitArray()
+ stream >> string
+
+ self.assertEqual(stream.status(), expectedStatus)
+ self.assertEqual(string.size(), expectedString.size())
+ self.assertEqual(string, expectedString)
+
+ def testOk(self):
+ '''QDataStream with valid QBitArray'''
+ test_set = [QBitArray()]
+ for i in range(1, 7):
+ test_set.append(create_bitarray(i * '1'))
+ for s in ['0111111', '0000000', '1001110']:
+ test_set.append(create_bitarray(s))
+
+ data = []
+ for expected in test_set:
+ data.append((serialize_bitarray(expected), QDataStream.Ok, expected))
+ self._check_bitarray(data)
+
+ def testPastEnd(self):
+ '''QDataStream >> QBitArray reading past the end of the data'''
+ serialized = serialize_bitarray(create_bitarray('1001110'))
+ serialized.resize(serialized.size() - 2)
+ self._check_bitarray([(serialized, QDataStream.ReadPastEnd, QBitArray())])
+
+
+class QDataStreamBuffer(unittest.TestCase):
+ def testRawData(self):
+ data = QDataStream()
+ self.assertEqual(data.readRawData(4), None)
+
+ ba = QByteArray()
+ data = QDataStream(ba, QIODevice.WriteOnly)
+ data.writeRawData('AB\x00C')
+ self.assertEqual(ba.data(), bytes('AB\x00C', "UTF-8"))
+
+ data = QDataStream(ba)
+ self.assertEqual(data.readRawData(4), bytes('AB\x00C', "UTF-8"))
+
+ def testRawDataBytes(self):
+ test_data = b'AB\0'
+ data = QDataStream()
+ ba = QByteArray()
+ data = QDataStream(ba, QIODevice.WriteOnly)
+ data.writeRawData(test_data)
+ self.assertEqual(ba.data(), test_data)
+ data = QDataStream(ba)
+ self.assertEqual(data.readRawData(3), test_data)
+
+ def testBytes(self):
+ dataOne = QDataStream()
+ self.assertEqual(dataOne.readBytes(4), None)
+
+ ba = QByteArray()
+ data = QDataStream(ba, QIODevice.WriteOnly)
+ # writeBytes() writes a quint32 containing the length of the data,
+ # followed by the data.
+ data.writeBytes(bytes('AB\x00C', 'UTF-8'))
+ self.assertEqual(ba.data(), bytes('\x00\x00\x00\x04AB\x00C', 'UTF-8'))
+
+ data = QDataStream(ba)
+ buffer = data.readBytes(4)
+ self.assertEqual(buffer, bytes('AB\x00C', 'UTF-8'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qdate_test.py b/sources/pyside6/tests/QtCore/qdate_test.py
new file mode 100644
index 000000000..611292227
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qdate_test.py
@@ -0,0 +1,45 @@
+#!/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
+
+'''Test cases for QDate'''
+
+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 QDate
+
+
+class TestQDate (unittest.TestCase):
+ def testGetDate(self):
+ date = QDate(2009, 22, 9)
+ tuple_ = date.getDate()
+ self.assertEqual(tuple, tuple_.__class__)
+ (y, m, d) = tuple_
+ self.assertEqual(date.year(), y)
+ self.assertEqual(date.month(), m)
+ self.assertEqual(date.day(), d)
+
+ def testGetWeekNumber(self):
+ date = QDate(2000, 1, 1)
+ tuple_ = date.weekNumber()
+ self.assertEqual(tuple, tuple_.__class__)
+ (week, yearNumber) = tuple_
+ self.assertEqual(week, 52)
+ self.assertEqual(yearNumber, 1999)
+
+ def testBooleanCast(self):
+ today = QDate.currentDate()
+ self.assertTrue(today)
+ nodate = QDate()
+ self.assertFalse(nodate)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qdatetime_test.py b/sources/pyside6/tests/QtCore/qdatetime_test.py
new file mode 100644
index 000000000..96e353112
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qdatetime_test.py
@@ -0,0 +1,35 @@
+# 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 datetime
+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 QDateTime, QDate, QTime
+
+
+class TestQDate (unittest.TestCase):
+ def testDateConversion(self):
+ dateTime = QDateTime(QDate(2011, 5, 17), QTime(11, 1, 14, 15))
+ dateTimePy = QDateTime(datetime.date(2011, 5, 17), datetime.time(11, 1, 14, 15000))
+ self.assertEqual(dateTime, dateTimePy)
+
+ def testDateTimeConversion(self):
+ dateTime = QDateTime(QDate(2011, 5, 17), QTime(11, 1, 14, 15))
+ dateTimePy = QDateTime(datetime.datetime(2011, 5, 17, 11, 1, 14, 15000))
+ self.assertEqual(dateTime, dateTimePy)
+
+ def testDateTimeNow(self):
+ py = datetime.datetime.now()
+ qt = QDateTime(py)
+ self.assertEqual(qt, py)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qdir_test.py b/sources/pyside6/tests/QtCore/qdir_test.py
new file mode 100644
index 000000000..702c7f13a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qdir_test.py
@@ -0,0 +1,39 @@
+# 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 QDir
+
+
+class QDirTest(unittest.TestCase):
+ '''Test case for QDir'''
+
+ def testConstructor(self):
+ # Optional case without arguments is equivalent to the constructor
+ # QDir(const QString &path = QString())
+ a = QDir()
+
+ self.assertTrue(a.isReadable())
+ self.assertTrue(a.isRelative())
+
+ # Empty string
+ b = QDir("")
+ self.assertEqual(a, b)
+
+ # Empty Path
+ c = QDir(Path())
+ self.assertEqual(a, c)
+
+ self.assertEqual(b, c)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qeasingcurve_test.py b/sources/pyside6/tests/QtCore/qeasingcurve_test.py
new file mode 100644
index 000000000..b202dbefb
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qeasingcurve_test.py
@@ -0,0 +1,42 @@
+# 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
+import gc
+
+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 QEasingCurve
+
+
+def myFunction(progress):
+ if progress == 1.0:
+ return 100.0
+ else:
+ return -100.0
+
+
+class TestQEasingCurve(unittest.TestCase):
+ def testCustomType(self):
+ ec = QEasingCurve()
+ ec.setCustomType(myFunction)
+ self.assertEqual(ec.valueForProgress(1.0), 100.0)
+ self.assertEqual(ec.valueForProgress(0.5), -100.0)
+
+ def testObjectCleanup(self):
+ for i in range(100):
+ ec = QEasingCurve()
+ ec.setCustomType(myFunction)
+ self.assertEqual(ec.valueForProgress(1.0), 100.0)
+ self.assertEqual(ec.valueForProgress(0.5), -100.0)
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qenum_test.py b/sources/pyside6/tests/QtCore/qenum_test.py
new file mode 100644
index 000000000..45a8e9124
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qenum_test.py
@@ -0,0 +1,202 @@
+#!/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
+
+'''Test cases for QEnum and QFlags'''
+
+import gc
+import os
+import sys
+import pickle
+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 Qt, QIODevice, QObject, QEnum, QFlag
+
+
+class TestEnum(unittest.TestCase):
+ def testOperations(self):
+ k = Qt.Key.Key_1
+
+ # Integers
+ self.assertEqual(k + 2, 2 + k)
+ self.assertEqual(k - 2, -(2 - k))
+ self.assertEqual(k * 2, 2 * k)
+
+ @unittest.skipUnless(getattr(sys, "getobjects", None), "requires --with-trace-refs")
+ @unittest.skipUnless(getattr(sys, "gettotalrefcount", None), "requires --with-pydebug")
+ def testEnumNew_NoLeak(self):
+ gc.collect()
+ total = sys.gettotalrefcount()
+ for idx in range(1000):
+ ret = Qt.Key(42)
+
+ gc.collect()
+ delta = sys.gettotalrefcount() - total
+ print("delta total refcount =", delta)
+ if abs(delta) >= 10:
+ all = [(sys.getrefcount(x), x) for x in sys.getobjects(0)]
+ all.sort(key=lambda x: x[0], reverse=True)
+ for ob in all[:10]:
+ print(ob)
+ self.assertTrue(abs(delta) < 10)
+
+
+class TestQFlags(unittest.TestCase):
+
+ def testToItn(self):
+ om = QIODevice.NotOpen
+ omcmp = om.value
+
+ self.assertEqual(om, QIODevice.NotOpen)
+ self.assertTrue(omcmp == 0)
+
+ self.assertTrue(omcmp != QIODevice.ReadOnly)
+ self.assertTrue(omcmp != 1)
+
+ def testToIntInFunction(self):
+ om = QIODevice.WriteOnly
+ self.assertEqual(int(om.value), 2)
+
+ def testNonExtensibleEnums(self):
+ try:
+ om = QIODevice.OpenMode(QIODevice.WriteOnly)
+ self.assertFail()
+ except:
+ pass
+
+
+# PYSIDE-15: Pickling of enums
+class TestEnumPickling(unittest.TestCase):
+ def testPickleEnum(self):
+
+ # Pickling of enums with different depth works.
+ ret = pickle.loads(pickle.dumps(QIODevice.Append))
+ self.assertEqual(ret, QIODevice.Append)
+
+ ret = pickle.loads(pickle.dumps(Qt.Key.Key_Asterisk))
+ self.assertEqual(ret, Qt.Key.Key_Asterisk)
+ self.assertEqual(ret, Qt.Key(42))
+
+ # We can also pickle the whole enum class (built in):
+ ret = pickle.loads(pickle.dumps(QIODevice))
+
+ # This works also with nested classes for Python 3, after we
+ # introduced the correct __qualname__ attribute.
+
+ # Note: For Python 2, we would need quite strange patches.
+ func = lambda: pickle.loads(pickle.dumps(Qt.Key))
+ func()
+
+# PYSIDE-957: The QEnum macro
+
+
+try:
+ import enum
+ HAVE_ENUM = True
+except ImportError:
+ HAVE_ENUM = False
+ QEnum = QFlag = lambda x: x
+ import types
+
+ class Enum:
+ pass
+ enum = types.ModuleType("enum")
+ enum.Enum = enum.Flag = enum.IntEnum = enum.IntFlag = Enum
+ Enum.__module__ = "enum"
+ Enum.__members__ = {}
+ del Enum
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ enum.auto = lambda: 42
+
+HAVE_FLAG = hasattr(enum, "Flag")
+
+
+@QEnum
+class OuterEnum(enum.Enum):
+ A = 1
+ B = 2
+
+
+class SomeClass(QObject):
+
+ @QEnum
+ class SomeEnum(enum.Enum):
+ A = 1
+ B = 2
+ C = 3
+
+ @QEnum
+ class OtherEnum(enum.IntEnum):
+ A = 1
+ B = 2
+ C = 3
+
+ class InnerClass(QObject):
+
+ @QEnum
+ class InnerEnum(enum.Enum):
+ X = 42
+
+ class SomeEnum(enum.Enum):
+ A = 4
+ B = 5
+ C = 6
+
+ QEnum(SomeEnum) # works even without the decorator assignment
+
+
+class TestQEnumMacro(unittest.TestCase):
+ meta_name = "EnumType" if sys.version_info[:2] >= (3, 11) else "EnumMeta"
+
+ def testTopLevel(self):
+ self.assertEqual(type(OuterEnum).__name__, self.meta_name)
+ self.assertEqual(len(OuterEnum.__members__), 2)
+
+ def testSomeClass(self):
+ self.assertEqual(type(SomeClass.SomeEnum).__name__, self.meta_name)
+ self.assertEqual(len(SomeClass.SomeEnum.__members__), 3)
+ with self.assertRaises(TypeError):
+ int(SomeClass.SomeEnum.C) == 6
+ self.assertEqual(SomeClass.OtherEnum.C, 3)
+
+ @unittest.skipIf(sys.version_info[0] < 3, "we cannot support nested classes in Python 2")
+ def testInnerClass(self):
+ self.assertEqual(SomeClass.InnerClass.InnerEnum.__qualname__,
+ "SomeClass.InnerClass.InnerEnum")
+ with self.assertRaises(TypeError):
+ int(SomeClass.InnerClass.InnerEnum.X) == 42
+
+ @unittest.skipUnless(HAVE_FLAG, "some older Python versions have no 'Flag'")
+ def testEnumFlag(self):
+ with self.assertRaises(TypeError):
+ class WrongFlagForEnum(QObject):
+ @QEnum
+ class Bad(enum.Flag):
+ pass
+ with self.assertRaises(TypeError):
+ class WrongEnuForFlag(QObject):
+ @QFlag
+ class Bad(enum.Enum):
+ pass
+
+ def testIsRegistered(self):
+ mo = SomeClass.staticMetaObject
+ self.assertEqual(mo.enumeratorCount(), 2)
+ self.assertEqual(mo.enumerator(0).name(), "OtherEnum")
+ self.assertEqual(mo.enumerator(0).scope(), "SomeClass")
+ self.assertEqual(mo.enumerator(1).name(), "SomeEnum")
+ moi = SomeClass.InnerClass.staticMetaObject
+ self.assertEqual(moi.enumerator(0).name(), "InnerEnum")
+ ## Question: Should that scope not better be "SomeClass.InnerClass"?
+ ## But we have __qualname__ already:
+ self.assertEqual(moi.enumerator(0).scope(), "InnerClass")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qevent_test.py b/sources/pyside6/tests/QtCore/qevent_test.py
new file mode 100644
index 000000000..244a14f13
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qevent_test.py
@@ -0,0 +1,36 @@
+#!/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
+
+'''Test cases for QtCore.QEvent'''
+
+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 QEvent
+
+
+class QEventTypeFlag(unittest.TestCase):
+ '''Test case for usage of QEvent.Type flags'''
+
+ def testFlagAccess(self):
+ # QEvent.Type flags usage
+
+ event = QEvent(QEvent.Timer)
+ self.assertEqual(event.type(), QEvent.Timer)
+
+ event = QEvent(QEvent.Close)
+ self.assertEqual(event.type(), QEvent.Close)
+
+ event = QEvent(QEvent.IconTextChange)
+ self.assertEqual(event.type(), QEvent.IconTextChange)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qfile_test.py b/sources/pyside6/tests/QtCore/qfile_test.py
new file mode 100644
index 000000000..0af5c2650
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qfile_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 tempfile
+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 QDir, QFile, QIODevice, QSaveFile, QTemporaryDir
+
+
+class GetCharTest(unittest.TestCase):
+ '''Test case for QIODevice.getChar in QFile'''
+
+ def setUp(self):
+ '''Acquire resources'''
+ handle, self.filename = tempfile.mkstemp()
+ os.write(handle, bytes('a', "UTF-8"))
+ os.close(handle)
+
+ def tearDown(self):
+ '''release resources'''
+ os.remove(self.filename)
+
+ def testBasic(self):
+ '''QFile.getChar'''
+ obj = QFile(self.filename)
+ obj.open(QIODevice.ReadOnly)
+ try:
+ self.assertEqual(obj.getChar(), (True, 'a'))
+ self.assertFalse(obj.getChar()[0])
+ finally:
+ obj.close()
+
+ def testBug721(self):
+ obj = QFile(self.filename)
+ obj.open(QIODevice.ReadOnly)
+ try:
+ memory = obj.map(0, 1)
+ self.assertEqual(len(memory), 1)
+ self.assertEqual(memory[0], ord('a'))
+ # now memory points to wild bytes... :-)
+ # uncommenting this must cause a segfault.
+ # self.assertEqual(memory[0], 'a')
+ finally:
+ obj.unmap(memory)
+ obj.close()
+
+ def testQSaveFile(self):
+ dir = QTemporaryDir(QDir.tempPath() + "/XXXXXX.dir")
+ self.assertTrue(dir.isValid())
+ saveFile = QSaveFile(dir.path() + "/test.dat")
+ self.assertTrue(saveFile.open(QIODevice.WriteOnly))
+ saveFile.write(bytes("Test", "UTF-8"))
+ self.assertTrue(saveFile.commit())
+ self.assertTrue(os.path.exists(QDir.toNativeSeparators(saveFile.fileName())))
+
+
+class GetCharTestPath(GetCharTest):
+ # PYSIDE-1499: Do the same with Path objects
+
+ def setUp(self):
+ '''Acquire resources'''
+ handle, filename = tempfile.mkstemp()
+ self.filename = Path(filename)
+ os.write(handle, bytes('a', "UTF-8"))
+ os.close(handle)
+
+
+class DirPath(unittest.TestCase):
+ # PYSIDE-1499: Test QDir with Path objects
+ def testQDirPath(self):
+ test_path = Path("some") / "dir"
+ qdir1 = QDir(os.fspath(test_path))
+ qdir2 = QDir(test_path)
+ self.assertEqual(qdir1, qdir2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qfileinfo_test.py b/sources/pyside6/tests/QtCore/qfileinfo_test.py
new file mode 100644
index 000000000..dfdfd7fa2
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qfileinfo_test.py
@@ -0,0 +1,33 @@
+# 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 tempfile
+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 QFile, QFileInfo
+
+
+class QFileConstructor(unittest.TestCase):
+ '''QFileInfo constructor with qfile'''
+
+ def testBasic(self):
+ '''QFileInfo(QFile)'''
+ obj = QFileInfo(QFile())
+
+ def testQFileInfoPath(self):
+ # PYSIDE-1499: Test QFileInfo with Path objects
+ test_path = Path("some") / "dir"
+ qinf1 = QFileInfo(os.fspath(test_path))
+ qinf2 = QFileInfo(test_path)
+ self.assertEqual(qinf1, qinf2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qfileread_test.py b/sources/pyside6/tests/QtCore/qfileread_test.py
new file mode 100644
index 000000000..c66a27f8a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qfileread_test.py
@@ -0,0 +1,66 @@
+# 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 QIODevice, QTemporaryFile
+
+
+class FileChild1(QTemporaryFile):
+ pass
+
+
+class FileChild2(QTemporaryFile):
+ def readData(self, maxlen):
+ return super(FileChild2, self).readData(maxlen)
+
+ def readLineData(self, maxlen):
+ return super(FileChild2, self).readLineData(maxlen)
+
+
+class readDataTest(unittest.TestCase):
+ '''Test case for readData and readLineData'''
+
+ def setUp(self):
+ '''Acquire resources'''
+ self.filename1 = FileChild1()
+ self.assertTrue(self.filename1.open())
+ self.filename1.write(bytes('Test text for testing', "UTF-8"))
+
+ self.filename2 = FileChild2()
+ self.assertTrue(self.filename2.open())
+ self.filename2.write(bytes('Test text for testing', "UTF-8"))
+
+ def tearDown(self):
+ '''release resources'''
+ pass
+
+ def testBasic(self):
+ '''QTemporaryFile.read'''
+ self.filename1.seek(0)
+ s1 = self.filename1.read(50)
+ self.assertEqual(s1, 'Test text for testing')
+
+ def testBug40(self):
+ self.filename2.seek(0)
+ s2 = self.filename2.read(50)
+ self.assertEqual(s2, 'Test text for testing')
+
+ self.filename2.seek(0)
+ s2 = self.filename2.readLine(22)
+ self.assertEqual(s2, 'Test text for testing')
+
+ self.filename1.seek(0)
+ s1 = self.filename1.read(50)
+ self.assertEqual(s1, s2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qflags_test.py b/sources/pyside6/tests/QtCore/qflags_test.py
new file mode 100644
index 000000000..2a5306685
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qflags_test.py
@@ -0,0 +1,131 @@
+#!/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
+
+'''Test cases for QFlags'''
+
+import operator
+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 Qt, QTemporaryFile, QFile, QIODevice, QObject
+
+
+class QFlagTest(unittest.TestCase):
+ '''Test case for usage of flags'''
+
+ def testCallFunction(self):
+ f = QTemporaryFile()
+ self.assertTrue(f.open())
+ fileName = f.fileName()
+ f.close()
+
+ f = QFile(fileName)
+ self.assertEqual(f.open(QIODevice.Truncate | QIODevice.Text | QIODevice.ReadWrite), True)
+ om = f.openMode()
+ self.assertEqual(om & QIODevice.Truncate, QIODevice.Truncate)
+ self.assertEqual(om & QIODevice.Text, QIODevice.Text)
+ self.assertEqual(om & QIODevice.ReadWrite, QIODevice.ReadWrite)
+ self.assertTrue(om == QIODevice.Truncate | QIODevice.Text | QIODevice.ReadWrite)
+ f.close()
+
+
+class QFlagOperatorTest(unittest.TestCase):
+ '''Test case for operators in QFlags'''
+
+ def testInvert(self):
+ '''QFlags ~ (invert) operator'''
+ self.assertEqual(type(~QIODevice.ReadOnly), QIODevice.OpenMode)
+
+ def testOr(self):
+ '''QFlags | (or) operator'''
+ self.assertEqual(type(QIODevice.ReadOnly | QIODevice.WriteOnly), QIODevice.OpenMode)
+
+ def testAnd(self):
+ '''QFlags & (and) operator'''
+ self.assertEqual(type(QIODevice.ReadOnly & QIODevice.WriteOnly), QIODevice.OpenMode)
+
+ def testIOr(self):
+ '''QFlags |= (ior) operator'''
+ flag = Qt.WindowFlags()
+ self.assertTrue(Qt.Widget == 0)
+ self.assertFalse(flag & Qt.Widget)
+ result = flag & Qt.Widget
+ self.assertTrue(result == 0)
+ flag |= Qt.WindowMinimizeButtonHint
+ self.assertTrue(flag & Qt.WindowMinimizeButtonHint)
+
+ def testInvertOr(self):
+ '''QFlags ~ (invert) operator over the result of an | (or) operator'''
+ self.assertEqual(type(~(Qt.ItemIsSelectable | Qt.ItemIsEditable)), Qt.ItemFlags)
+
+ def testEqual(self):
+ '''QFlags == operator'''
+ flags = Qt.Window
+ flags |= Qt.WindowMinimizeButtonHint
+ flag_type = (flags & Qt.WindowType_Mask)
+ self.assertEqual(flag_type, Qt.Window)
+
+ self.assertEqual(Qt.KeyboardModifiers(Qt.ControlModifier), Qt.ControlModifier)
+
+ def testOperatorBetweenFlags(self):
+ '''QFlags & QFlags'''
+ flags = Qt.NoItemFlags | Qt.ItemIsUserCheckable
+ newflags = Qt.NoItemFlags | Qt.ItemIsUserCheckable
+ self.assertTrue(flags & newflags)
+
+ def testOperatorDifferentOrder(self):
+ '''Different ordering of arguments'''
+ flags = Qt.NoItemFlags | Qt.ItemIsUserCheckable
+ self.assertEqual(flags | Qt.ItemIsEnabled, Qt.ItemIsEnabled | flags)
+
+ def testEqualNonNumericalObject(self):
+ '''QFlags ==,!= non-numerical object '''
+ flags = Qt.NoItemFlags | Qt.ItemIsUserCheckable
+
+ self.assertTrue(flags != None) # noqa: E711
+ self.assertFalse(flags == None) # noqa: E711
+
+ self.assertTrue(flags != "tomato")
+ self.assertFalse(flags == "tomato")
+
+ with self.assertRaises(TypeError):
+ flags > None
+ with self.assertRaises(TypeError):
+ flags >= None
+ with self.assertRaises(TypeError):
+ flags < None
+ with self.assertRaises(TypeError):
+ flags <= None
+
+
+class QFlagsOnQVariant(unittest.TestCase):
+ def testQFlagsOnQVariant(self):
+ o = QObject()
+ o.setProperty("foo", QIODevice.ReadOnly | QIODevice.WriteOnly)
+ self.assertEqual(type(o.property("foo")), QIODevice.OpenMode)
+
+
+class QEnumFlagDefault(unittest.TestCase):
+ """
+ Check that old flag and enum syntax can be used.
+ The signatures of these surrogate functions intentionally do not exist
+ because people should learn to use the new Enums correctly.
+ """
+ def testOldQFlag(self):
+ self.assertEqual(Qt.AlignmentFlag(), Qt.AlignmentFlag(0))
+ oldFlag = Qt.Alignment()
+ oldEnum = Qt.AlignmentFlag()
+ self.assertEqual(type(oldFlag), Qt.Alignment)
+ self.assertEqual(type(oldEnum), Qt.AlignmentFlag)
+ self.assertEqual(type(oldFlag), type(oldEnum))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qhandle_test.py b/sources/pyside6/tests/QtCore/qhandle_test.py
new file mode 100644
index 000000000..e0f4f3f7a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qhandle_test.py
@@ -0,0 +1,28 @@
+#!/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
+
+'''Test cases for QEnum and QFlags'''
+
+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 QThread, Qt
+
+
+class TestHANDLE(unittest.TestCase):
+ def testIntConversion(self):
+ i = 0
+ h = QThread.currentThreadId()
+ i = 0 + int(h)
+ self.assertEqual(i, int(h))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qinstallmsghandler_test.py b/sources/pyside6/tests/QtCore/qinstallmsghandler_test.py
new file mode 100644
index 000000000..9c5ae4370
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qinstallmsghandler_test.py
@@ -0,0 +1,76 @@
+# 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 cases for qInstallMsgHandler'''
+
+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 (QLibraryInfo, QtMsgType,
+ QMessageLogContext,
+ qCritical, qFormatLogMessage, qDebug,
+ qInstallMessageHandler, qWarning)
+
+
+param = []
+
+
+def handler(msgt, ctx, msg):
+ global param
+ param = [msgt, ctx, msg.strip()]
+
+
+def handleruseless(msgt, ctx, msg):
+ pass
+
+
+class QInstallMsgHandlerTest(unittest.TestCase):
+
+ def tearDown(self):
+ # Ensure that next test will have a clear environment
+ qInstallMessageHandler(None)
+
+ def testNone(self):
+ ret = qInstallMessageHandler(None)
+ self.assertEqual(ret, None)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRet(self):
+ ret = qInstallMessageHandler(None)
+ self.assertEqual(ret, None)
+ refcount = sys.getrefcount(handleruseless)
+ retNone = qInstallMessageHandler(handleruseless)
+ self.assertEqual(sys.getrefcount(handleruseless), refcount + 1)
+ rethandler = qInstallMessageHandler(None)
+ self.assertEqual(rethandler, handleruseless)
+ del rethandler
+ self.assertEqual(sys.getrefcount(handleruseless), refcount)
+
+ def testHandler(self):
+ rethandler = qInstallMessageHandler(handler)
+ if QLibraryInfo.isDebugBuild():
+ qDebug("Test Debug")
+ self.assertEqual(param[0], QtMsgType.QtDebugMsg)
+ self.assertEqual(param[2], "Test Debug")
+ qWarning("Test Warning")
+ self.assertEqual(param[0], QtMsgType.QtWarningMsg)
+ self.assertEqual(param[2], "Test Warning")
+ qCritical("Test Critical")
+ self.assertEqual(param[0], QtMsgType.QtCriticalMsg)
+ self.assertEqual(param[2], "Test Critical")
+
+ def testFormat(self):
+ ctx = QMessageLogContext()
+ s = qFormatLogMessage(QtMsgType.QtInfoMsg, ctx, 'bla')
+ self.assertTrue(s)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/qiodevice_buffered_read_test.py b/sources/pyside6/tests/QtCore/qiodevice_buffered_read_test.py
new file mode 100644
index 000000000..ea735112a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qiodevice_buffered_read_test.py
@@ -0,0 +1,78 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for buffered read methods of QIODevice'''
+
+from PySide6.QtCore import QBuffer
+
+import enum
+import unittest
+
+
+class TestQIODeviceBufferedRead(unittest.TestCase):
+ class TestType(enum.Enum):
+ Read = enum.auto()
+ ReadLine = enum.auto()
+ Peek = enum.auto()
+
+ def setUp(self) -> None:
+ self.buffer = QBuffer()
+ self.text = "Tomato juice\nPotato salad\n"
+
+ self.assertTrue(
+ self.buffer.open(QBuffer.OpenModeFlag.ReadWrite), self.buffer.errorString())
+ self.assertGreaterEqual(
+ self.buffer.write(self.text.encode("utf-8")), 0, self.buffer.errorString())
+
+ self.buffer.seek(0)
+
+ def tearDown(self) -> None:
+ self.buffer.close()
+
+ def test_read(self) -> None:
+ response1 = self.buffer.read(1024).data().decode("utf-8")
+ self.assertEqual(response1, self.text)
+
+ self.buffer.seek(0)
+ response2 = bytearray(1024)
+ bytes_read = self.buffer.read(response2, 1024)
+
+ self.assertGreaterEqual(bytes_read, 0, self.buffer.errorString())
+ self.assertEqual(response2[:bytes_read].decode("utf-8"), response1)
+
+ def test_readLine(self) -> None:
+ response1 = self.buffer.readLine(1024).data().decode("utf-8")
+ # Only read until the first line (including the line break)
+ self.assertEqual(response1, self.text.split("\n", 1)[0] + "\n")
+
+ self.buffer.seek(0)
+ response2 = bytearray(1024)
+ bytes_read = self.buffer.readLine(response2, 1024)
+
+ self.assertGreaterEqual(bytes_read, 0, self.buffer.errorString())
+ self.assertEqual(response2[:bytes_read].decode("utf-8"), response1)
+
+ def test_peek(self) -> None:
+ response1 = self.buffer.peek(1024).data().decode("utf-8")
+ self.assertEqual(response1, self.text)
+
+ # Test that peek has no side effects
+ response_again1 = self.buffer.read(1024).data().decode("utf-8")
+ self.assertEqual(response_again1, response1)
+
+ self.buffer.seek(0)
+ response2 = bytearray(1024)
+ bytes_read = self.buffer.peek(response2, 1024)
+
+ self.assertGreaterEqual(bytes_read, 0, self.buffer.errorString())
+ self.assertEqual(response2[:bytes_read].decode("utf-8"), response1)
+
+ # Test that peek has no side effects
+ response_again2 = bytearray(1024)
+ bytes_read_again2 = self.buffer.read(response_again2, 1024)
+ self.assertEqual(bytes_read, bytes_read_again2)
+ self.assertEqual(response_again2, response2)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qiopipe_test.py b/sources/pyside6/tests/QtCore/qiopipe_test.py
new file mode 100644
index 000000000..53a6ba70a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qiopipe_test.py
@@ -0,0 +1,36 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for the QIOPipe class'''
+
+from PySide6.QtCore import QIODevice, QIOPipe
+
+import unittest
+
+
+class QIOPipeTest(unittest.TestCase):
+ def setUp(self) -> None:
+ self.pipe = QIOPipe()
+ self.pipe.open(QIODevice.OpenModeFlag.ReadWrite)
+ return super().setUp()
+
+ def tearDown(self) -> None:
+ super().tearDown()
+
+ def ready_read_bytes_written(self):
+ received_data = self.pipe.end2().readAll().data()
+ self.assertEqual(received_data, self.data)
+
+ def test_readyRead(self):
+ self.data = b"Hello, World!"
+ self.pipe.end2().readyRead.connect(self.ready_read_bytes_written)
+ self.pipe.end1().write(self.data)
+
+ def test_bytesWritten(self):
+ self.data = b"Hello, World!"
+ self.pipe.end2().bytesWritten.connect(self.ready_read_bytes_written)
+ self.pipe.end1().write(self.data)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qjsondocument_test.py b/sources/pyside6/tests/QtCore/qjsondocument_test.py
new file mode 100644
index 000000000..a50f185ff
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qjsondocument_test.py
@@ -0,0 +1,32 @@
+#!/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
+
+'''Test cases for QJsonDocument/nullptr_t'''
+
+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 QJsonDocument
+
+
+class QJsonDocumentTest(unittest.TestCase):
+
+ def testToVariant(self):
+ a = QJsonDocument.fromJson(b'{"test": null}')
+ self.assertIsInstance(a, QJsonDocument)
+ self.assertEqual(str(a.toVariant()), "{'test': None}")
+
+ b = QJsonDocument.fromJson(b'{"test": [null]}')
+ self.assertIsInstance(b, QJsonDocument)
+ self.assertEqual(str(b.toVariant()), "{'test': [None]}")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qlinef_test.py b/sources/pyside6/tests/QtCore/qlinef_test.py
new file mode 100644
index 000000000..90ae50159
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qlinef_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
+
+'''Test cases for QLineF'''
+
+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 QLineF, QPointF
+
+
+class TestQLineF (unittest.TestCase):
+ def testIntersect(self):
+ l1 = QLineF(0, 0, 1, 0)
+ l2 = QLineF(1, -1, 1, 1)
+ tuple_ = l1.intersects(l2)
+ self.assertEqual(tuple, tuple_.__class__)
+ (value, p) = tuple_
+ self.assertEqual(QLineF.BoundedIntersection, value)
+ self.assertEqual(QPointF(1, 0), p)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qlocale_test.py b/sources/pyside6/tests/QtCore/qlocale_test.py
new file mode 100644
index 000000000..05b0d3219
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qlocale_test.py
@@ -0,0 +1,73 @@
+#!/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
+
+'''Unit tests for QLocale'''
+
+import ctypes
+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 QLocale
+
+
+class QLocaleTestToNumber(unittest.TestCase):
+ def testToNumberInt(self):
+ obj = QLocale(QLocale.C)
+ self.assertEqual((37, True), obj.toInt('37'))
+
+ def testToNumberFloat(self):
+ obj = QLocale(QLocale.C)
+ self.assertEqual((ctypes.c_float(37.109).value, True),
+ obj.toFloat('37.109'))
+
+ def testToNumberDouble(self):
+ obj = QLocale(QLocale.C)
+ self.assertEqual((ctypes.c_double(37.109).value, True),
+ obj.toDouble('37.109'))
+
+ def testToNumberShort(self):
+ obj = QLocale(QLocale.C)
+ self.assertEqual((ctypes.c_short(37).value, True),
+ obj.toShort('37'))
+
+ def testToNumberLong(self):
+ obj = QLocale(QLocale.C)
+ self.assertEqual((ctypes.c_long(37).value, True),
+ obj.toLong('37'))
+
+ def testToNumberULongLong(self):
+ obj = QLocale(QLocale.C)
+ self.assertEqual((ctypes.c_ulonglong(37).value, True),
+ obj.toULongLong('37'))
+
+ def testToNumberULongLongNegative(self):
+ obj = QLocale(QLocale.C)
+ self.assertTrue(not obj.toULongLong('-37')[1])
+
+ def testToCurrencyString(self):
+ """PYSIDE-2133, do not use int overload, dropping decimals."""
+ en_locale = QLocale("en_US")
+ value = en_locale.toCurrencyString(1234.56)
+ self.assertEqual(value, "$1,234.56")
+
+ def testToString(self):
+ """PYSIDE-2168, check negative values"""
+ en_locale = QLocale("en_US")
+ value = en_locale.toString(-4)
+ self.assertEqual(value, "-4")
+ # Verify that large types (long long/double) are used.
+ value = en_locale.toString(3000000000)
+ self.assertEqual(value, "3,000,000,000")
+ value = en_locale.toString(10e40)
+ self.assertEqual(value, "1E+41")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qlockfile_test.py b/sources/pyside6/tests/QtCore/qlockfile_test.py
new file mode 100644
index 000000000..6dca9235c
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qlockfile_test.py
@@ -0,0 +1,42 @@
+#!/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
+
+'''Test cases for QLockFile'''
+
+import os
+import sys
+import unittest
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QDir, QLockFile, QCoreApplication
+
+
+class TestQMessageAuthenticationCode (unittest.TestCase):
+
+ def setUp(self):
+ pid = QCoreApplication.applicationPid()
+ self._fileName = f"{QDir.tempPath()}/pqlockfiletest{pid}.tmp"
+
+ def tearDown(self):
+ if (os.path.exists(self._fileName)):
+ os.remove(self._fileName)
+
+ def test(self):
+ # Merely exercise the API, no locking against another processes.
+ lockFile = QLockFile(self._fileName)
+ self.assertTrue(lockFile.lock())
+ self.assertTrue(lockFile.isLocked())
+ lock_info = lockFile.getLockInfo();
+ self.assertEqual(len(lock_info), 3)
+ self.assertEqual(lock_info[0], os.getpid())
+ lockFile.unlock()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qmessageauthenticationcode_test.py b/sources/pyside6/tests/QtCore/qmessageauthenticationcode_test.py
new file mode 100644
index 000000000..74e6bceb9
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qmessageauthenticationcode_test.py
@@ -0,0 +1,28 @@
+#!/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
+
+'''Test cases for QMessageAuthenticationCode'''
+
+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 QCryptographicHash, QMessageAuthenticationCode
+
+
+class TestQMessageAuthenticationCode (unittest.TestCase):
+ def test(self):
+ code = QMessageAuthenticationCode(QCryptographicHash.Sha1, bytes('bla', "UTF-8"))
+ result = code.result()
+ self.assertTrue(result.size() > 0)
+ print(result.toHex())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qmetaobject_test.py b/sources/pyside6/tests/QtCore/qmetaobject_test.py
new file mode 100644
index 000000000..4b3051711
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qmetaobject_test.py
@@ -0,0 +1,213 @@
+#!/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
+
+'''Tests for static methos conflicts with class methods'''
+
+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 (QCoreApplication, QFile, QMetaMethod, QMetaObject,
+ QObject, QModelIndex, QPoint, QTimer, QSemaphore,
+ QStringListModel, Qt, Signal, Slot,
+ SIGNAL, Q_ARG, Q_RETURN_ARG)
+
+
+class Foo(QFile):
+ pass
+
+
+class DynObject(QObject):
+ def slot(self):
+ pass
+
+
+class InvokeTester(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ @Slot(int, int, result=int)
+ def add(self, a, b):
+ return a + b
+
+ @Slot(str, str, result=str)
+ def concatenate(self, a, b):
+ return a + b
+
+ @Slot(QPoint, result=int)
+ def manhattan_length(self, point):
+ return abs(point.x()) + abs(point.y())
+
+ @Slot(QPoint, QPoint, result=QPoint)
+ def add_points(self, point1, point2):
+ return point1 + point2
+
+ @Slot(QObject, result=str)
+ def object_name(self, o):
+ return o.objectName()
+
+ @Slot(QObject, result=QObject)
+ def first_child(self, o):
+ return o.children()[0]
+
+
+class SemaphoreSender(QObject):
+ signal = Signal(QSemaphore)
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.semaphore = QSemaphore()
+
+ def emitSignal(self):
+ self.signal.emit(self.semaphore)
+
+
+class SemaphoreReceiver(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.semaphore = None
+
+ @Slot(QSemaphore)
+ def receiverSlot(self, semaphore):
+ self.semaphore = semaphore
+
+
+class qmetaobject_test(unittest.TestCase):
+ """
+ def test_QMetaObject(self):
+ qobj = QObject()
+ qobj_metaobj = qobj.metaObject()
+ self.assertEqual(qobj_metaobj.className(), "QObject")
+
+ obj = QFile()
+ m = obj.metaObject()
+ self.assertEqual(m.className(), "QFile")
+ self.assertNotEqual(m.methodCount(), qobj_metaobj.methodCount())
+
+ obj = Foo()
+ m = obj.metaObject()
+ self.assertEqual(m.className(), "Foo")
+ f = QFile()
+ fm = f.metaObject()
+ self.assertEqual(m.methodCount(), fm.methodCount())
+ """
+
+ def test_DynamicSlotSignal(self):
+ o = DynObject()
+ o2 = QObject()
+
+ o.connect(o2, SIGNAL("bars()"), o.slot)
+ self.assertTrue(o2.metaObject().indexOfMethod("bars()") > -1)
+
+ # PYSIDE-784, plain Qt objects should not have intermediary
+ # metaObjects.
+ def test_PlainQObject(self):
+ timer = QTimer()
+ self.assertEqual(timer.metaObject().superClass().className(),
+ "QObject")
+
+ # PYSIDE-1827, slots with non-QObject object types should work
+ # (metatypes are registered)
+ def test_ObjectSlotSignal(self):
+ app = QCoreApplication() # noqa: F841
+ sender = SemaphoreSender()
+ receiver = SemaphoreReceiver()
+ sender.signal.connect(receiver.receiverSlot, Qt.QueuedConnection)
+ sender.emitSignal()
+ while not receiver.semaphore:
+ QCoreApplication.processEvents()
+ self.assertEqual(sender.semaphore, receiver.semaphore)
+
+ # PYSIDE-1898,
+ def test_Invoke(self):
+ tester = InvokeTester()
+
+ # Primitive types
+ sum = QMetaObject.invokeMethod(tester, "add", Q_RETURN_ARG(int),
+ Q_ARG(int, 2), Q_ARG(int, 3))
+ self.assertEqual(sum, 5)
+
+ # Same with QMetaMethod
+ mo = tester.metaObject()
+ method = mo.method(mo.indexOfMethod("add(int,int)"))
+ self.assertTrue(method.isValid())
+ sum = method.invoke(tester, Qt.ConnectionType.AutoConnection,
+ Q_RETURN_ARG(int), Q_ARG(int, 2), Q_ARG(int, 3))
+ self.assertEqual(sum, 5)
+ sum = method.invoke(tester, Q_RETURN_ARG(int), Q_ARG(int, 2),
+ Q_ARG(int, 3))
+ self.assertEqual(sum, 5)
+
+ concatenated = QMetaObject.invokeMethod(tester, "concatenate",
+ Q_RETURN_ARG(str),
+ Q_ARG(str, "bla"),
+ Q_ARG(str, "bla"))
+ self.assertEqual(concatenated, "blabla")
+
+ # Wrapped type as in-parameter
+ point = QPoint(10, 20)
+ len = QMetaObject.invokeMethod(tester, "manhattan_length",
+ Q_RETURN_ARG(int),
+ Q_ARG(QPoint, point))
+ self.assertEqual(len, point.manhattanLength())
+
+ # Wrapped type as result
+ point2 = QPoint(30, 30)
+ point3 = QMetaObject.invokeMethod(tester, "add_points",
+ Q_RETURN_ARG(QPoint),
+ Q_ARG(QPoint, point),
+ Q_ARG(QPoint, point2))
+ self.assertEqual(point + point2, point3)
+
+ # Pass an object
+ o = QObject()
+ o.setObjectName("Foo")
+ name = QMetaObject.invokeMethod(tester, "object_name",
+ Q_RETURN_ARG(str),
+ Q_ARG(QObject, o))
+ self.assertEqual(name, o.objectName())
+
+ # Return an object
+ child = QObject(o)
+ child.setObjectName("Child")
+ c = QMetaObject.invokeMethod(tester, "first_child",
+ Q_RETURN_ARG(QObject),
+ Q_ARG(QObject, o))
+ self.assertTrue(c)
+ self.assertEqual(c, child)
+
+ def test_InvokeTypeString(self):
+ strings = ["item1", "item2"]
+ model = QStringListModel(strings)
+ index = model.index(1, 0)
+ QMetaObject.invokeMethod(model, "setData",
+ Q_ARG(QModelIndex, index),
+ Q_ARG("QVariant", "bla"))
+ self.assertEqual(model.data(index), "bla")
+
+ # Same with QMetaMethod
+ mo = model.metaObject()
+ method = mo.method(mo.indexOfMethod("setData(QModelIndex,QVariant)"))
+ self.assertTrue(method.isValid())
+ method.invoke(model, Qt.ConnectionType.AutoConnection,
+ Q_ARG(QModelIndex, index), Q_ARG("QVariant", "blub"))
+ self.assertEqual(model.data(index), "blub")
+ method.invoke(model, Q_ARG(QModelIndex, index), Q_ARG("QVariant", "blip"))
+ self.assertEqual(model.data(index), "blip")
+
+ def test_QMetaMethod(self):
+ o = QObject()
+ m = QMetaMethod.fromSignal(o.destroyed)
+ self.assertTrue(m.isValid)
+ self.assertEqual(m.methodSignature(), b"destroyed()")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qmetatype_test.py b/sources/pyside6/tests/QtCore/qmetatype_test.py
new file mode 100644
index 000000000..f8e0ba1c0
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qmetatype_test.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python
+# Copyright (C) 2022The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Tests for QMetaType'''
+
+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 (QMetaType, QObject, QPoint)
+
+
+class qmetatype_test(unittest.TestCase):
+ def test_ObjectSlotSignal(self):
+ meta_type = QMetaType(int)
+ self.assertTrue(meta_type.isValid())
+ self.assertEqual(meta_type.name(), "int")
+
+ meta_type = QMetaType(str)
+ self.assertTrue(meta_type.isValid())
+ self.assertEqual(meta_type.name(), "QString")
+
+ meta_type = QMetaType(float)
+ self.assertTrue(meta_type.isValid())
+ self.assertEqual(meta_type.name(), "double")
+
+ meta_type = QMetaType(QPoint)
+ self.assertTrue(meta_type.isValid())
+ self.assertEqual(meta_type.name(), "QPoint")
+
+ meta_type = QMetaType(QObject)
+ self.assertTrue(meta_type.isValid())
+ self.assertEqual(meta_type.name(), "QObject*")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qmimedatabase_test.py b/sources/pyside6/tests/QtCore/qmimedatabase_test.py
new file mode 100644
index 000000000..6a63edb85
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qmimedatabase_test.py
@@ -0,0 +1,59 @@
+#!/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
+
+'''Unit tests for QMimeDatabase'''
+
+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 QMimeDatabase, QLocale
+
+
+class QMimeDatabaseTest(unittest.TestCase):
+ def testMimeTypeForName(self):
+ db = QMimeDatabase()
+
+ s0 = db.mimeTypeForName("application/x-zerosize")
+ self.assertTrue(s0.isValid())
+ self.assertEqual(s0.name(), "application/x-zerosize")
+ self.assertTrue(s0.comment())
+
+ s0Again = db.mimeTypeForName("application/x-zerosize")
+ self.assertEqual(s0Again.name(), s0.name())
+
+ s1 = db.mimeTypeForName("text/plain")
+ self.assertTrue(s1.isValid())
+ self.assertEqual(s1.name(), "text/plain")
+
+ krita = db.mimeTypeForName("application/x-krita")
+ self.assertTrue(krita.isValid())
+
+ rdf = db.mimeTypeForName("application/rdf+xml")
+ self.assertTrue(rdf.isValid())
+ self.assertEqual(rdf.name(), "application/rdf+xml")
+ self.assertTrue(rdf.comment())
+ if "en" in QLocale().name():
+ self.assertEqual(rdf.comment(), "RDF file")
+
+ bzip2 = db.mimeTypeForName("application/x-bzip2")
+ self.assertTrue(bzip2.isValid())
+ self.assertTrue(bzip2.comment())
+
+ defaultMime = db.mimeTypeForName("application/octet-stream")
+ self.assertTrue(defaultMime.isValid())
+ self.assertEqual(defaultMime.name(), "application/octet-stream")
+ self.assertTrue(defaultMime.isDefault())
+
+ doesNotExist = db.mimeTypeForName("foobar/x-doesnot-exist")
+ self.assertTrue(not doesNotExist.isValid())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qmodelindex_internalpointer_test.py b/sources/pyside6/tests/QtCore/qmodelindex_internalpointer_test.py
new file mode 100644
index 000000000..ec37ca6a0
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qmodelindex_internalpointer_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
+
+''' Test case for QAbstractListModel.createIndex and QModelIndex.internalPointer'''
+
+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 QAbstractListModel, QObject
+
+
+class MyModel (QAbstractListModel):
+ pass
+
+
+class TestQModelIndexInternalPointer(unittest.TestCase):
+ ''' Test case for QAbstractListModel.createIndex and QModelIndex.internalPointer'''
+
+ def setUp(self):
+ # Acquire resources
+ self.model = MyModel()
+
+ def tearDown(self):
+ # Release resources
+ del self.model
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testInternalPointer(self):
+ # Test QAbstractListModel.createIndex and
+ # QModelIndex.internalPointer with regular Python objects
+ obj = QObject()
+ idx = self.model.createIndex(0, 0, "Hello")
+ i = idx.internalPointer()
+ self.assertEqual(i, "Hello")
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testReferenceCounting(self):
+ # Test reference counting when retrieving data with
+ # QModelIndex.internalPointer
+ o = [1, 2, 3]
+ o_refcnt = sys.getrefcount(o)
+ idx = self.model.createIndex(0, 0, o)
+ ptr = idx.internalPointer()
+ self.assertEqual(sys.getrefcount(o), o_refcnt + 1)
+
+ def testIndexForDefaultDataArg(self):
+ # Test QAbstractListModel.createIndex with a default
+ # value for data argument
+ idx = self.model.createIndex(0, 0)
+ self.assertEqual(None, idx.internalPointer())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/qobject_children_segfault_test.py b/sources/pyside6/tests/QtCore/qobject_children_segfault_test.py
new file mode 100644
index 000000000..508526cca
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qobject_children_segfault_test.py
@@ -0,0 +1,42 @@
+# 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 cases for parent-child relationship'''
+
+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, QCoreApplication
+
+
+class ChildrenCoreApplication(unittest.TestCase):
+ '''Test case for calling QObject.children after creating a QCoreApp'''
+
+ def testQCoreAppChildren(self):
+ # QObject.children() after creating a QCoreApplication
+ # Minimal test:
+ # 1- Create QCoreApp
+ # 2- Create parent and childrens
+ # 3- While keeping the children alive, call parent.children()
+ # 4- Delete parent
+ app = QCoreApplication([])
+ parent = QObject()
+ children = [QObject(parent) for x in range(25)]
+ # Uncomment the lines below to make the test pass
+ # del children
+ # del child2
+ del parent # XXX Segfaults here
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertTrue(True)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qobject_connect_notify_test.py b/sources/pyside6/tests/QtCore/qobject_connect_notify_test.py
new file mode 100644
index 000000000..b3bfaf007
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qobject_connect_notify_test.py
@@ -0,0 +1,99 @@
+# 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 case for QObject::connectNotify()'''
+
+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, SIGNAL, SLOT
+from helper.usesqapplication import UsesQApplication
+
+
+def cute_slot():
+ pass
+
+
+class Obj(QObject):
+
+ foo = Signal()
+
+ def __init__(self):
+ super().__init__()
+ self.con_notified = False
+ self.dis_notified = False
+ self.signal = ""
+
+ def connectNotify(self, signal):
+ self.con_notified = True
+ self.signal = signal
+
+ def disconnectNotify(self, signal):
+ self.dis_notified = True
+
+ def reset(self):
+ self.con_notified = False
+ self.dis_notified = False
+
+
+class TestQObjectConnectNotify(UsesQApplication):
+ '''Test case for QObject::connectNotify'''
+ def setUp(self):
+ UsesQApplication.setUp(self)
+ self.called = False
+
+ def tearDown(self):
+ UsesQApplication.tearDown(self)
+
+ def testBasic(self):
+ sender = Obj()
+ receiver = QObject()
+ sender.destroyed.connect(receiver.deleteLater)
+ self.assertTrue(sender.con_notified)
+ self.assertEqual(sender.signal.methodSignature(), "destroyed()")
+ self.assertTrue(sender.destroyed.disconnect(receiver.deleteLater))
+ self.assertTrue(sender.dis_notified)
+
+ def testBasicString(self):
+ sender = Obj()
+ receiver = QObject()
+ sender.connect(SIGNAL("destroyed()"), receiver, SLOT("deleteLater()"))
+ self.assertTrue(sender.con_notified)
+ # When connecting to a regular slot, and not a python callback function, QObject::connect
+ # will use the non-cloned method signature, so connecting to destroyed() will actually
+ # connect to destroyed(QObject*).
+ self.assertEqual(sender.signal.methodSignature(), "destroyed(QObject*)")
+ self.assertTrue(sender.disconnect(SIGNAL("destroyed()"), receiver, SLOT("deleteLater()")))
+ self.assertTrue(sender.dis_notified)
+
+ def testPySignal(self):
+ sender = Obj()
+ receiver = QObject()
+ sender.foo.connect(receiver.deleteLater)
+ self.assertTrue(sender.con_notified)
+ self.assertTrue(sender.foo.disconnect(receiver.deleteLater))
+ self.assertTrue(sender.dis_notified)
+
+ def testPySlots(self):
+ sender = Obj()
+ sender.destroyed.connect(cute_slot)
+ self.assertTrue(sender.con_notified)
+ self.assertTrue(sender.destroyed.disconnect(cute_slot))
+ self.assertTrue(sender.dis_notified)
+
+ def testpyAll(self):
+ sender = Obj()
+ sender.foo.connect(cute_slot)
+ self.assertTrue(sender.con_notified)
+ self.assertTrue(sender.foo.disconnect(cute_slot))
+ self.assertTrue(sender.dis_notified)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qobject_destructor.py b/sources/pyside6/tests/QtCore/qobject_destructor.py
new file mode 100644
index 000000000..2b7b40f25
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qobject_destructor.py
@@ -0,0 +1,33 @@
+# 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
+
+
+class MyObject(QObject):
+ def __init__(self, other=None):
+ super().__init__(None)
+ self._o = other
+
+
+class TestDestructor(unittest.TestCase):
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testReference(self):
+ o = QObject()
+ m = MyObject(o)
+ self.assertEqual(sys.getrefcount(o), 3)
+ del m
+ self.assertEqual(sys.getrefcount(o), 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qobject_event_filter_test.py b/sources/pyside6/tests/QtCore/qobject_event_filter_test.py
new file mode 100644
index 000000000..ab7a1b6ad
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qobject_event_filter_test.py
@@ -0,0 +1,150 @@
+# 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 cases for QObject.eventFilter'''
+
+import gc
+import os
+import sys
+import unittest
+import weakref
+
+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, QTimerEvent
+
+from helper.usesqapplication import UsesQApplication
+
+
+class FilterObject(QObject):
+ '''Filter object for the basic test'''
+ def __init__(self, obj=None, event_type=None, *args):
+ # Creates a new filter object
+ QObject.__init__(self, *args)
+ self.obj = obj
+ self.event_type = event_type
+ self.events_handled = 0
+ self.events_bypassed = 0
+
+ def setTargetObject(self, obj):
+ # Sets the object that will be filtered
+ self.obj = obj
+
+ def eventFilter(self, obj, event):
+ '''Just checks if is the correct object and event type
+ incrementing counter until reaching the limit. After that it
+ stops filtering the events for the object.'''
+ if (self.obj == obj):
+ if isinstance(event, self.event_type) and self.events_handled < 5:
+ self.events_handled += 1
+ return True
+ else:
+ self.events_bypassed += 1
+ return False
+ else:
+ return QObject.eventFilter(self, obj, event)
+
+
+class FilteredObject(QObject):
+ '''Class that will be filtered. Quits the app after 5 timer events'''
+ def __init__(self, app, *args):
+ QObject.__init__(self, *args)
+ self.app = app
+ self.times_called = 0
+
+ def timerEvent(self, evt):
+ # Overridden method
+ self.times_called += 1
+
+ if self.times_called == 5:
+ self.app.quit()
+
+
+class PolymorphicIdFilterObject(QObject):
+ """PYSIDE-2675: Check whether QChildEvent.added() is accessible via PolymorphicId"""
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.added = False
+
+ def event(self, event):
+ self.added = event.added()
+ return False
+
+
+class TestQObjectEventFilterPython(UsesQApplication):
+ '''QObject.eventFilter - Reimplemented in python
+ Filters 5 TimerEvents and then bypasses the other events to the
+ timerEvent method. After 5 runs, the timerEvent method will ask
+ the core application to exit'''
+ def setUp(self):
+ # Acquire resources
+ UsesQApplication.setUp(self)
+ self.obj_filter = FilterObject(event_type=QTimerEvent)
+
+ def tearDown(self):
+ # Release resources
+ del self.obj_filter
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ UsesQApplication.tearDown(self)
+
+ def testEventFilter(self):
+ # QObject.eventFilter reimplemented in python
+ filtered = FilteredObject(self.app)
+ filtered.installEventFilter(self.obj_filter)
+ self.obj_filter.setTargetObject(filtered)
+
+ filtered.startTimer(0)
+
+ self.app.exec()
+
+ self.assertEqual(filtered.times_called, 5)
+ self.assertEqual(self.obj_filter.events_handled, 5)
+
+ def testPolymorphicId(self):
+ testObject = PolymorphicIdFilterObject()
+ t2 = QObject(testObject) # noqa: F841
+ self.assertTrue(testObject.added)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testInstallEventFilterRefCountAfterDelete(self):
+ '''Bug 910 - installEventFilter() increments reference count on target object
+ http://bugs.pyside.org/show_bug.cgi?id=910'''
+ obj = QObject()
+ filt = QObject()
+
+ self.assertEqual(sys.getrefcount(obj), 2)
+ self.assertEqual(sys.getrefcount(filt), 2)
+ obj.installEventFilter(filt)
+ self.assertEqual(sys.getrefcount(obj), 2)
+ self.assertEqual(sys.getrefcount(filt), 2)
+
+ wref = weakref.ref(obj)
+ del obj
+ self.assertEqual(wref(), None)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testInstallEventFilterRefCountAfterRemove(self):
+ # Bug 910
+ obj = QObject()
+ filt = QObject()
+
+ self.assertEqual(sys.getrefcount(obj), 2)
+ self.assertEqual(sys.getrefcount(filt), 2)
+ obj.installEventFilter(filt)
+ self.assertEqual(sys.getrefcount(obj), 2)
+ self.assertEqual(sys.getrefcount(filt), 2)
+ obj.removeEventFilter(filt)
+ self.assertEqual(sys.getrefcount(obj), 2)
+ self.assertEqual(sys.getrefcount(filt), 2)
+
+ wref = weakref.ref(obj)
+ del obj
+ self.assertEqual(wref(), None)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qobject_inherits_test.py b/sources/pyside6/tests/QtCore/qobject_inherits_test.py
new file mode 100644
index 000000000..0bd4fba75
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qobject_inherits_test.py
@@ -0,0 +1,115 @@
+# 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 cases for QObject methods'''
+
+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, QTimer
+from PySide6.QtWidgets import QApplication, QLabel, QVBoxLayout
+
+is_alive = None
+
+
+class InheritsCase(unittest.TestCase):
+ '''Test case for QObject.inherits'''
+
+ def testCppInheritance(self):
+ # QObject.inherits() for c++ classes
+ # A class inherits itself
+ self.assertTrue(QObject().inherits('QObject'))
+
+ def testPythonInheritance(self):
+ # QObject.inherits() for python classes
+
+ class Dummy(QObject):
+ # Dummy class
+ pass
+
+ self.assertTrue(Dummy().inherits('QObject'))
+ self.assertTrue(Dummy().inherits('Dummy'))
+ self.assertTrue(not Dummy().inherits('FooBar'))
+
+ def testPythonMultiInheritance(self):
+ # QObject.inherits() for multiple inheritance
+ # QObject.inherits(classname) should fail if classname isn't a
+ # QObject subclass
+
+ class Parent(object):
+ # Dummy parent
+ pass
+
+ class Dummy(QObject, Parent):
+ # Dummy class
+ pass
+
+ self.assertTrue(Dummy().inherits('QObject'))
+ self.assertTrue(not Dummy().inherits('Parent'))
+
+ def testSetAttributeBeforeCallingInitOnQObjectDerived(self):
+ '''Test for bug #428.'''
+ class DerivedObject(QObject):
+ def __init__(self):
+ self.member = 'member'
+ super().__init__()
+ obj0 = DerivedObject()
+ # The second instantiation of DerivedObject will generate an exception
+ # that will not come to surface immediately.
+ obj1 = DerivedObject()
+ # The mere calling of the object method causes
+ # the exception to "reach the surface".
+ obj1.objectName()
+
+ def testMultipleInheritance(self):
+ def declareClass():
+ class Foo(object, QObject):
+ pass
+
+ self.assertRaises(TypeError, declareClass)
+
+ # PYSIDE-11:
+ # The takeOwnership() method was relying that the SbkObject
+ # had a converter, which it's not the case when multiple
+ # inheritance is used.
+ # The deleteLater() method uses the takeOwnership() to give
+ # control of the object to C++, so it can be remove once
+ # the destructor is called.
+ # The solution was to add a default case when the object
+ # is null under the pythonTypeIsValueType() method in shiboken.
+ def testDeleteMultipleInheritance(self):
+ app = QApplication(sys.argv)
+
+ class DerivedLabel(QLabel, QObject):
+ def __del__(self):
+ global is_alive
+ is_alive = False
+
+ global is_alive
+ child = DerivedLabel('Hello')
+ is_alive = True
+ parent = QVBoxLayout()
+ parent.addWidget(child)
+ parent.removeWidget(child)
+ child.deleteLater()
+ self.assertTrue(is_alive)
+ del child
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertTrue(is_alive)
+ QTimer.singleShot(100, app.quit)
+ app.exec()
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertFalse(is_alive)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qobject_objectproperty_test.py b/sources/pyside6/tests/QtCore/qobject_objectproperty_test.py
new file mode 100644
index 000000000..f1a4cb0b5
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qobject_objectproperty_test.py
@@ -0,0 +1,42 @@
+#!/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
+
+'''Test case for the bug #378
+http://bugs.openbossa.org/show_bug.cgi?id=378
+'''
+
+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
+
+
+class ExtQObject(QObject):
+ def __init__(self):
+ # "foobar" will become a object attribute that will not be
+ # listed on the among the type attributes. Thus for bug
+ # condition be correctly triggered the "foobar" attribute
+ # must not previously exist in the parent class.
+ self.foobar = None
+ # The parent __init__ method must be called after the
+ # definition of "self.foobar".
+ super().__init__()
+
+
+class TestBug378(unittest.TestCase):
+ '''Test case for the bug #378'''
+
+ def testBug378(self):
+ obj = ExtQObject()
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/qobject_parent_test.py b/sources/pyside6/tests/QtCore/qobject_parent_test.py
new file mode 100644
index 000000000..6265f77b1
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qobject_parent_test.py
@@ -0,0 +1,335 @@
+# 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 cases for parent-child relationship'''
+
+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, QRegularExpression, QTimer, Qt
+
+
+class TestObject1(QTimer):
+ def __init(self, parent):
+ super().__init__(parent)
+
+
+class TestObject2(TestObject1):
+ def __init(self, parent):
+ super().__init__(parent)
+
+
+class ParentRefCountCase(unittest.TestCase):
+ '''Test case for the refcount changes of setParent'''
+
+ def setUp(self):
+ # Acquire resources
+ self.parent = QObject()
+ self.child = QObject()
+
+ def tearDown(self):
+ # Release resources
+ del self.child
+ del self.parent
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testSetParent(self):
+ # QObject.setParent() refcount changes
+ self.assertEqual(sys.getrefcount(self.child), 2)
+ self.child.setParent(self.parent)
+ self.assertEqual(sys.getrefcount(self.child), 3)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testSetParentTwice(self):
+ self.assertEqual(sys.getrefcount(self.child), 2)
+ self.child.setParent(self.parent)
+ self.assertEqual(sys.getrefcount(self.child), 3)
+ self.child.setParent(self.parent)
+ self.assertEqual(sys.getrefcount(self.child), 3)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testConstructor(self):
+ # QObject(QObject) refcount changes
+ child = QObject(self.parent)
+ self.assertEqual(sys.getrefcount(child), 3)
+
+
+class ParentCase(unittest.TestCase):
+ '''Small collection of tests related to parent-child relationship'''
+
+ def testSetParent(self):
+ # QObject.setParent()
+ parent = QObject()
+ child = QObject()
+ child.setParent(parent)
+
+ self.assertEqual(parent, child.parent())
+
+ def testParentConstructor(self):
+ # QObject(parent)
+ parent = QObject()
+ child = QObject(parent)
+
+ self.assertEqual(parent, child.parent())
+
+ orig_repr = repr(child)
+ del child
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertEqual(orig_repr, repr(parent.children()[0]))
+
+ def testChildren(self):
+ # QObject.children()
+ parent = QObject()
+ children = [QObject(parent) for x in range(25)]
+
+ self.assertEqual(parent.children(), children)
+
+ def testFindChild(self):
+ # QObject.findChild() with all QObject
+ parent = QObject()
+ children = [QObject(parent) for i in range(20)]
+
+ for i, child in enumerate(children):
+ child.setObjectName(f'object{i}')
+
+ for i, child in enumerate(children):
+ self.assertEqual(child, parent.findChild(QObject, f'object{i}'))
+
+ def testFindChildOptions(self):
+ parent = QObject()
+ child = QObject(parent)
+ nested_child_name = 'nestedChild'
+ nested_child = QObject(child)
+ nested_child.setObjectName(nested_child_name)
+
+ search_result = parent.findChild(QObject, nested_child_name)
+ self.assertTrue(search_result)
+ search_result = parent.findChild(QObject, nested_child_name,
+ Qt.FindChildrenRecursively)
+ self.assertTrue(search_result)
+ search_result = parent.findChild(QObject, nested_child_name,
+ Qt.FindDirectChildrenOnly)
+ self.assertFalse(search_result)
+
+ search_results = parent.findChildren(QObject, nested_child_name)
+ self.assertEqual(len(search_results), 1)
+ search_result = parent.findChildren(QObject, nested_child_name,
+ Qt.FindChildrenRecursively)
+ self.assertEqual(len(search_results), 1)
+ search_results = parent.findChildren(QObject, nested_child_name,
+ Qt.FindDirectChildrenOnly)
+ self.assertEqual(len(search_results), 0)
+
+ def testFindChildWithoutName(self):
+ parent = QObject()
+ children = [QObject(parent) for i in range(20)]
+
+ for i, child in enumerate(children):
+ child.setObjectName(f'object{i}')
+
+ child = parent.findChild(QObject)
+ self.assertTrue(isinstance(child, QObject))
+
+ def testFindChildren(self):
+ # QObject.findChildren() with all QObject
+ parent = QObject()
+ target_name = 'foo'
+ children = [QTimer(parent) for i in range(20)]
+ children.extend([QObject(parent) for i in range(20)])
+
+ for i, child in enumerate(children):
+ if i % 5 == 0:
+ child.setObjectName(target_name)
+ else:
+ child.setObjectName(str(i))
+
+ # Emulates findChildren with the intended outcome
+ target_children = [x for x in children if x.objectName() == target_name]
+ test_children = parent.findChildren(QObject, target_name)
+ self.assertEqual(target_children, test_children)
+
+ # test findChildren default value
+ res = parent.findChildren(QTimer)
+ self.assertEqual(len(res), 20)
+
+ # test findChildren with a QRegularExpression
+ res = parent.findChildren(QObject, QRegularExpression("^fo+"))
+ self.assertEqual(res, test_children)
+
+ def testParentEquality(self):
+ # QObject.parent() == parent
+ parent = QObject()
+ child = QObject(parent)
+ self.assertEqual(parent, child.parent())
+
+ def testFindChildByType(self):
+ parent = QObject()
+ expected = TestObject2(parent)
+ actual = parent.findChild(TestObject2)
+ self.assertEqual(actual, expected)
+ actual = parent.findChild(TestObject1)
+ self.assertEqual(actual, expected)
+ actual = parent.findChild(QTimer)
+ self.assertEqual(actual, expected)
+
+ def testFindChildrenByType(self):
+ parent = QObject()
+ expected = [TestObject2(parent)]
+ actual = parent.findChildren(TestObject2)
+ self.assertEqual(actual, expected)
+ actual = parent.findChildren(TestObject1)
+ self.assertEqual(actual, expected)
+ actual = parent.findChildren(QTimer)
+ self.assertEqual(actual, expected)
+
+
+class TestParentOwnership(unittest.TestCase):
+ '''Test case for Parent/Child object ownership'''
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testParentDestructor(self):
+ parent = QObject()
+ self.assertEqual(sys.getrefcount(parent), 2)
+
+ child = QObject(parent)
+ self.assertEqual(sys.getrefcount(child), 3)
+ self.assertEqual(sys.getrefcount(parent), 2)
+
+ del parent
+ self.assertEqual(sys.getrefcount(child), 2)
+
+ # this will fail because parent deleted child cpp object
+ self.assertRaises(RuntimeError, lambda: child.objectName())
+
+ # test parent with multiples children
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testMultipleChildren(self):
+ o = QObject()
+ self.assertEqual(sys.getrefcount(o), 2)
+
+ c = QObject(o)
+ self.assertEqual(sys.getrefcount(c), 3)
+ self.assertEqual(sys.getrefcount(o), 2)
+
+ c2 = QObject(o)
+ self.assertEqual(sys.getrefcount(o), 2)
+ self.assertEqual(sys.getrefcount(c), 3)
+ self.assertEqual(sys.getrefcount(c2), 3)
+
+ del o
+ self.assertEqual(sys.getrefcount(c), 2)
+ self.assertEqual(sys.getrefcount(c2), 2)
+
+ # this will fail because parent deleted child cpp object
+ self.assertRaises(RuntimeError, lambda: c.objectName())
+ self.assertRaises(RuntimeError, lambda: c2.objectName())
+
+ # test recursive parent
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRecursiveParent(self):
+ o = QObject()
+ self.assertEqual(sys.getrefcount(o), 2)
+
+ c = QObject(o)
+ self.assertEqual(sys.getrefcount(c), 3)
+ self.assertEqual(sys.getrefcount(o), 2)
+
+ c2 = QObject(c)
+ self.assertEqual(sys.getrefcount(o), 2)
+ self.assertEqual(sys.getrefcount(c), 3)
+ self.assertEqual(sys.getrefcount(c2), 3)
+
+ del o
+ self.assertEqual(sys.getrefcount(c), 2)
+ self.assertEqual(sys.getrefcount(c2), 2)
+
+ # this will fail because parent deleted child cpp object
+ self.assertRaises(RuntimeError, lambda: c.objectName())
+ self.assertRaises(RuntimeError, lambda: c2.objectName())
+
+ # test parent transfer
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testParentTransfer(self):
+ o = QObject()
+ self.assertEqual(sys.getrefcount(o), 2)
+
+ c = QObject()
+ self.assertEqual(sys.getrefcount(c), 2)
+
+ c.setParent(o)
+ self.assertEqual(sys.getrefcount(c), 3)
+
+ c.setParent(None)
+ self.assertEqual(sys.getrefcount(c), 2)
+
+ del c
+ del o
+
+
+class ExtQObject(QObject):
+ def __init__(self):
+ super().__init__()
+
+
+class ReparentingTest(unittest.TestCase):
+ '''Test cases for reparenting'''
+
+ def testParentedQObjectIdentity(self):
+ object_list = []
+ parent = QObject()
+ for i in range(3):
+ obj = QObject()
+ object_list.append(obj)
+ obj.setParent(parent)
+ for child in parent.children():
+ self.assertTrue(child in object_list)
+
+ def testParentedExtQObjectType(self):
+ object_list = []
+ parent = QObject()
+ for i in range(3):
+ obj = ExtQObject()
+ object_list.append(obj)
+ obj.setParent(parent)
+ for orig, child in zip(object_list, parent.children()):
+ self.assertEqual(type(orig), type(child))
+
+ def testReparentedQObjectIdentity(self):
+ object_list = []
+ old_parent = QObject()
+ new_parent = QObject()
+ for i in range(3):
+ obj = QObject()
+ object_list.append(obj)
+ obj.setParent(old_parent)
+ for obj in object_list:
+ obj.setParent(new_parent)
+ for child in new_parent.children():
+ self.assertTrue(child in object_list)
+
+ def testReparentedExtQObjectType(self):
+ object_list = []
+ old_parent = QObject()
+ new_parent = QObject()
+ for i in range(3):
+ obj = ExtQObject()
+ object_list.append(obj)
+ obj.setParent(old_parent)
+ for obj in object_list:
+ obj.setParent(new_parent)
+ for orig, child in zip(object_list, new_parent.children()):
+ self.assertEqual(type(orig), type(child))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qobject_property_test.py b/sources/pyside6/tests/QtCore/qobject_property_test.py
new file mode 100644
index 000000000..4efb25cb4
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qobject_property_test.py
@@ -0,0 +1,53 @@
+# 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 cases for QObject property and setProperty'''
+
+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, Property, Signal
+
+
+class MyObjectWithNotifyProperty(QObject):
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+ self.p = 0
+
+ def readP(self):
+ return self.p
+
+ def writeP(self, v):
+ self.p = v
+ self.notifyP.emit()
+
+ notifyP = Signal()
+ myProperty = Property(int, readP, fset=writeP, notify=notifyP)
+
+
+class PropertyWithNotify(unittest.TestCase):
+ def called(self):
+ self.called_ = True
+
+ def testNotify(self):
+ self.called_ = False
+ obj = MyObjectWithNotifyProperty()
+ obj.notifyP.connect(self.called)
+ obj.myProperty = 10
+ self.assertTrue(self.called_)
+
+ def testHasProperty(self):
+ o = MyObjectWithNotifyProperty()
+ o.setProperty("myProperty", 10)
+ self.assertEqual(o.myProperty, 10)
+ self.assertEqual(o.property("myProperty"), 10)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qobject_protected_methods_test.py b/sources/pyside6/tests/QtCore/qobject_protected_methods_test.py
new file mode 100644
index 000000000..926698b4b
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qobject_protected_methods_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
+
+'''Test cases for QObject protected methods'''
+
+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, QThread, SIGNAL
+
+
+class Dummy(QObject):
+ '''Dummy class'''
+ pass
+
+
+class QObjectReceivers(unittest.TestCase):
+ '''Test case for QObject.receivers()'''
+
+ def cb(self, *args):
+ # Dummy callback
+ pass
+
+ def testQObjectReceiversExtern(self):
+ # QObject.receivers() - Protected method external access
+
+ obj = Dummy()
+ self.assertEqual(obj.receivers(SIGNAL("destroyed()")), 0)
+
+ obj.destroyed.connect(self.cb)
+ self.assertEqual(obj.receivers(SIGNAL("destroyed()")), 1)
+
+ def testQThreadReceiversExtern(self):
+ # QThread.receivers() - Inherited protected method
+
+ obj = QThread()
+ self.assertEqual(obj.receivers(SIGNAL('destroyed()')), 0)
+ obj.destroyed.connect(self.cb)
+ self.assertEqual(obj.receivers(SIGNAL("destroyed()")), 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qobject_test.py b/sources/pyside6/tests/QtCore/qobject_test.py
new file mode 100644
index 000000000..ecfc3dff0
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qobject_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
+
+'''Test cases for QObject methods'''
+
+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, Qt
+
+
+class Obj(QObject):
+ signal = Signal()
+
+ def empty(self):
+ pass
+
+ def emitSignal(self):
+ self.signal.emit()
+
+
+class Receiver(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._count = 0
+
+ def count(self):
+ return self._count
+
+ @Slot()
+ def testSlot(self):
+ self._count += 1
+
+
+class ObjectNameCase(unittest.TestCase):
+ '''Tests related to QObject object name'''
+
+ def testSimple(self):
+ # QObject.objectName(string)
+ name = 'object1'
+ obj = QObject()
+ obj.setObjectName(name)
+
+ self.assertEqual(name, obj.objectName())
+
+ def testEmpty(self):
+ # QObject.objectName('')
+ name = ''
+ obj = QObject()
+ obj.setObjectName(name)
+
+ self.assertEqual(name, obj.objectName())
+
+ def testDefault(self):
+ # QObject.objectName() default
+ obj = QObject()
+ self.assertEqual('', obj.objectName())
+
+ def testUnicode(self):
+ name = 'não'
+ # FIXME Strange error on upstream when using equal(name, obj)
+ obj = QObject()
+ obj.setObjectName(name)
+ self.assertEqual(obj.objectName(), name)
+
+ def testUniqueConnection(self):
+ obj = Obj()
+ # On first connect, UniqueConnection returns True, and on the second
+ # it must return False, and not a RuntimeError (PYSIDE-34)
+ self.assertTrue(obj.signal.connect(obj.empty, Qt.UniqueConnection))
+ self.assertFalse(obj.signal.connect(obj.empty, Qt.UniqueConnection))
+
+ def testDisconnect(self):
+ obj = Obj()
+ receiver = Receiver()
+ conn_id = obj.signal.connect(receiver.testSlot)
+ self.assertTrue(conn_id)
+
+ obj.emitSignal()
+ self.assertEqual(receiver.count(), 1)
+
+ obj.signal.disconnect(conn_id)
+ obj.emitSignal()
+ self.assertEqual(receiver.count(), 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qobject_timer_event_test.py b/sources/pyside6/tests/QtCore/qobject_timer_event_test.py
new file mode 100644
index 000000000..9e657c27f
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qobject_timer_event_test.py
@@ -0,0 +1,57 @@
+#!/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
+
+'''Test case for QObject.timerEvent overloading'''
+
+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, QCoreApplication
+
+from helper.usesqapplication import UsesQApplication
+
+
+class Dummy(QObject):
+
+ def __init__(self, app):
+ super().__init__()
+ self.times_called = 0
+ self.app = app
+
+ def timerEvent(self, event):
+ QObject.timerEvent(self, event)
+ event.accept()
+ self.times_called += 1
+
+ if self.times_called == 5:
+ self.app.exit(0)
+
+
+class QObjectTimerEvent(UsesQApplication):
+
+ def setUp(self):
+ # Acquire resources
+ super(QObjectTimerEvent, self).setUp()
+
+ def tearDown(self):
+ # Release resources
+ super(QObjectTimerEvent, self).tearDown()
+
+ def testTimerEvent(self):
+ # QObject.timerEvent overloading
+ obj = Dummy(self.app)
+ timer_id = obj.startTimer(200)
+ self.app.exec()
+ obj.killTimer(timer_id)
+ self.assertEqual(obj.times_called, 5)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qobject_tr_as_instance_test.py b/sources/pyside6/tests/QtCore/qobject_tr_as_instance_test.py
new file mode 100644
index 000000000..9123c5155
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qobject_tr_as_instance_test.py
@@ -0,0 +1,54 @@
+#!/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
+
+'''Unit tests for QObject's tr static methods.'''
+
+import gc
+import os
+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
+
+#from helper.usesqapplication import UsesQApplication
+
+
+class QObjectTrTest(unittest.TestCase):
+ '''Test case to check if QObject tr static methods could be treated as instance methods.'''
+
+ def setUp(self):
+ self.obj = QObject()
+
+ def tearDown(self):
+ del self.obj
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testTrCommonCase(self):
+ # Test common case for QObject.tr
+ invar1 = 'test1'
+ outvar1 = self.obj.tr(invar1)
+ invar2 = 'test2'
+ outvar2 = self.obj.tr(invar2, 'test comment')
+ self.assertEqual((invar1, invar2), (outvar1, outvar2))
+
+ def testTrAsInstanceMethod(self):
+ # Test QObject.tr as instance.
+ # PYSIDE-1252: This works now as a class method!
+ invar1 = 'test1'
+ outvar1 = QObject.tr(invar1)
+ invar2 = 'test2'
+ outvar2 = QObject.tr(invar2, 'test comment')
+ self.assertEqual((invar1, invar2), (outvar1, outvar2))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/qoperatingsystemversion_test.py b/sources/pyside6/tests/QtCore/qoperatingsystemversion_test.py
new file mode 100644
index 000000000..d887029ac
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qoperatingsystemversion_test.py
@@ -0,0 +1,24 @@
+# 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 QOperatingSystemVersion
+
+
+class TestQOperatingSystemVersion(unittest.TestCase):
+ def test(self):
+ ov = QOperatingSystemVersion.current()
+ name = f"{ov.name()} v{ov.majorVersion()}.{ov.minorVersion()}.{ov.microVersion()}"
+ print(name)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qpoint_test.py b/sources/pyside6/tests/QtCore/qpoint_test.py
new file mode 100644
index 000000000..b9d5afa37
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qpoint_test.py
@@ -0,0 +1,32 @@
+# 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 cases for QPoint and QPointF'''
+
+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 QPoint, QPointF
+
+
+class QPointTest(unittest.TestCase):
+
+ def testQPointCtor(self):
+ point = QPoint(QPoint(10, 20))
+
+
+class QPointFTest(unittest.TestCase):
+
+ def testQPointFCtor(self):
+ pointf = QPointF(QPoint(10, 20))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/qprocess_test.py b/sources/pyside6/tests/QtCore/qprocess_test.py
new file mode 100644
index 000000000..ba4d29102
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qprocess_test.py
@@ -0,0 +1,40 @@
+#!/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
+
+'''Test cases for QProcess'''
+
+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 QProcess
+
+
+class TestQProcess (unittest.TestCase):
+ def testStartDetached(self):
+ value, pid = QProcess.startDetached("dir", [], os.getcwd())
+ self.assertTrue(isinstance(value, bool))
+ self.assertTrue(isinstance(pid, int))
+
+ def testPid(self):
+ p = QProcess()
+ p.start("dir", [])
+ p.waitForStarted()
+ pid = p.processId()
+ # We can't test the pid method result because it returns 0 when the
+ # process isn't running
+ if p.state() == QProcess.Running:
+ self.assertNotEqual(pid, 0)
+ p.waitForFinished()
+ else:
+ print("PROCESS ALREADY DEAD :-/")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qproperty_decorator.py b/sources/pyside6/tests/QtCore/qproperty_decorator.py
new file mode 100644
index 000000000..19f2bd251
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qproperty_decorator.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
+import weakref
+
+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, Property
+
+
+class MyObject(QObject):
+ def __init__(self):
+ super().__init__()
+ self._value = None
+
+ @Property(int)
+ def value(self):
+ return self._value
+
+ @value.setter
+ # Note: The name of property and setter must be the same, because the
+ # object changes its identity all the time. `valueSet` no longer works.
+ def value(self, value):
+ self._value = value
+
+
+class PropertyTest(unittest.TestCase):
+ def destroyCB(self, obj):
+ self._obDestroyed = True
+
+ def testDecorator(self):
+ self._obDestroyed = False
+ o = MyObject()
+ weak = weakref.ref(o, self.destroyCB)
+ o.value = 10
+ self.assertEqual(o._value, 10)
+ self.assertEqual(o.value, 10)
+ del o
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ # PYSIDE-535: Why do I need to do it twice, here?
+ gc.collect()
+ self.assertTrue(self._obDestroyed)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qrandomgenerator_test.py b/sources/pyside6/tests/QtCore/qrandomgenerator_test.py
new file mode 100644
index 000000000..c13a8b24a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qrandomgenerator_test.py
@@ -0,0 +1,33 @@
+# 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 QRandomGenerator, QRandomGenerator64
+
+
+class QRandomGeneratorTest(unittest.TestCase):
+ '''Test case for QRandomGenerator'''
+
+ def testGenerator(self):
+ self.assertTrue(QRandomGenerator.system())
+ self.assertTrue(QRandomGenerator.global_())
+ generator = QRandomGenerator()
+ r = generator.bounded(10, 20)
+ self.assertTrue(r >= 10)
+ self.assertTrue(r <= 20)
+
+ def testGenerator64(self):
+ generator = QRandomGenerator64()
+ r = generator.generate()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qrect_test.py b/sources/pyside6/tests/QtCore/qrect_test.py
new file mode 100644
index 000000000..8a14abc5a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qrect_test.py
@@ -0,0 +1,123 @@
+#!/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
+
+'''Test cases for QRect'''
+
+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 QPoint, QRect, QRectF
+
+
+class RectConstructor(unittest.TestCase):
+
+ def testDefault(self):
+ # QRect()
+ obj = QRect()
+
+ self.assertTrue(obj.isNull())
+
+ def testConstructorQPoint(self):
+ topLeft = QPoint(3, 0)
+ bottomRight = QPoint(0, 3)
+
+ rect1 = QRect(topLeft, bottomRight)
+ rect2 = QRect(topLeft, bottomRight)
+
+ self.assertEqual(rect1, rect2)
+
+
+class RectOperator(unittest.TestCase):
+ '''Test case for QRect operators'''
+
+ def testEqual(self):
+ '''QRect == QRect
+ Note: operator == must be working as it's the main check
+ for correctness'''
+ rect1 = QRect()
+ rect2 = QRect()
+ self.assertEqual(rect1, rect2)
+
+ rect1 = QRect(0, 4, 100, 300)
+ rect2 = QRect(0, 4, 100, 300)
+ self.assertEqual(rect1, rect2)
+
+ def testNullRectIntersection(self):
+ # QRect & QRect for null rects
+ rect1 = QRect()
+ rect2 = QRect()
+ rect3 = rect1 & rect2
+ self.assertEqual(rect3, rect1)
+ self.assertEqual(rect3, rect2)
+
+ def testNoIntersect(self):
+ '''QRect & QRect for non-intersecting QRects
+ Non-intersecting QRects return a 'null' QRect for operator &'''
+ rect1 = QRect(10, 10, 5, 5)
+ rect2 = QRect(20, 20, 5, 5)
+ rect3 = rect1 & rect2
+ self.assertEqual(rect3, QRect())
+
+ def testIntersectPartial(self):
+ # QRect & QRect for partial intersections
+ rect1 = QRect(10, 10, 10, 10)
+ rect2 = QRect(15, 15, 10, 10)
+ rect3 = rect1 & rect2
+ self.assertEqual(rect3, QRect(15, 15, 5, 5))
+
+ def testIntersetEnclosed(self):
+ # QRect & QRect for a qrect inside another
+ rect1 = QRect(10, 10, 20, 20)
+ rect2 = QRect(15, 15, 5, 5)
+ rect3 = rect1 & rect2
+ self.assertEqual(rect3, rect2)
+
+ def testNullRectIntersectBounding(self):
+ # QRect | QRect for null rects
+ rect1 = QRect()
+ rect2 = QRect()
+ rect3 = rect1 & rect2
+ self.assertEqual(rect3, rect1)
+ self.assertEqual(rect3, rect2)
+
+ def testNoIntersectBounding(self):
+ '''QRect | QRect for non-intersecting QRects
+ Non-intersecting QRects return a greater QRect for operator |'''
+ rect1 = QRect(10, 10, 5, 5)
+ rect2 = QRect(20, 20, 5, 5)
+ rect3 = rect1 | rect2
+ self.assertEqual(rect3, QRect(10, 10, 15, 15))
+
+ def testBoundingPartialIntersection(self):
+ # QRect | QRect for partial intersections
+ rect1 = QRect(10, 10, 10, 10)
+ rect2 = QRect(15, 15, 10, 10)
+ rect3 = rect1 | rect2
+ self.assertEqual(rect3, QRect(10, 10, 15, 15))
+
+ def testBoundingEnclosed(self):
+ # QRect | QRect for a qrect inside another
+ rect1 = QRect(10, 10, 20, 20)
+ rect2 = QRect(15, 15, 5, 5)
+ rect3 = rect1 | rect2
+ self.assertEqual(rect3, rect1)
+
+ def testGetCoordsAndRect(self):
+ rect1 = QRect(1, 2, 3, 4)
+ self.assertEqual(rect1.getRect(), (1, 2, 3, 4))
+ self.assertEqual(rect1.getCoords(), (1, 2, 3, 5))
+
+ rect1 = QRectF(1, 2, 3, 4)
+ self.assertEqual(rect1.getRect(), (1, 2, 3, 4))
+ self.assertEqual(rect1.getCoords(), (1, 2, 4, 6))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qregularexpression_test.py b/sources/pyside6/tests/QtCore/qregularexpression_test.py
new file mode 100644
index 000000000..a88c2dc24
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qregularexpression_test.py
@@ -0,0 +1,41 @@
+#!/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
+
+'''Unit tests for QRegularExpression'''
+
+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 QRegularExpression, QRegularExpressionMatch, QRegularExpressionMatchIterator
+
+
+class QRegularExpressionTest(unittest.TestCase):
+
+ def testMatch(self):
+ re = QRegularExpression('^.*(word2).*$')
+ self.assertTrue(re.isValid())
+ match = re.match('word1 word2 word3')
+ self.assertTrue(match.isValid())
+ self.assertEqual(match.captured(1), 'word2')
+ self.assertEqual(match.capturedView(1), 'word2')
+
+ def testMatchIterator(self):
+ re = QRegularExpression('(\w+)')
+ self.assertTrue(re.isValid())
+ count = 0
+ it = re.globalMatch('word1 word2 word3')
+ while it.hasNext():
+ it.next()
+ count = count + 1
+ self.assertEqual(count, 3)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qresource_test.py b/sources/pyside6/tests/QtCore/qresource_test.py
new file mode 100644
index 000000000..1cdd2c785
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qresource_test.py
@@ -0,0 +1,56 @@
+# 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 cases for QResource usage'''
+
+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 QByteArray, QFile, QIODevice
+import resources_mc
+
+
+class ResourcesUsage(unittest.TestCase):
+ '''Test case for resources usage'''
+
+ def testPhrase(self):
+ # Test loading of quote.txt resource
+ file = Path(__file__).resolve().parent / 'quoteEnUS.txt'
+ self.assertTrue(file.is_file())
+ orig = QByteArray(file.read_bytes())
+ # In case the file is checked out in 'crlf' mode, strip '\r'
+ # since we read binary.
+ if sys.platform == 'win32':
+ carriage_return = orig.indexOf('\r')
+ if carriage_return != -1:
+ orig.remove(carriage_return, 1)
+
+ f = QFile(':/quote.txt') # |QIODevice.Text
+ self.assertTrue(f.open(QIODevice.ReadOnly), f.errorString())
+ copy = f.readAll()
+ f.close()
+ self.assertEqual(orig, copy)
+
+ def testImage(self):
+ # Test loading of sample.png resource
+ file = Path(__file__).resolve().parent / 'sample.png'
+ self.assertTrue(file.is_file())
+ orig = file.read_bytes()
+
+ f = QFile(':/sample.png')
+ self.assertTrue(f.open(QIODevice.ReadOnly), f.errorString())
+ copy = f.readAll()
+ f.close()
+ self.assertEqual(len(orig), len(copy))
+ self.assertEqual(orig, copy)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/qrunnable_test.py b/sources/pyside6/tests/QtCore/qrunnable_test.py
new file mode 100644
index 000000000..d52f50ce1
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qrunnable_test.py
@@ -0,0 +1,45 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for QRunnable'''
+
+import os
+import sys
+import unittest
+from io import StringIO
+
+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 QCoreApplication, QRunnable, QThreadPool, QThread, qDebug
+from helper.usesqapplication import UsesQApplication
+test_result = ""
+
+
+def check_test():
+ global test_result
+ test_result = "test works"
+
+
+class QRunnableTest(UsesQApplication):
+ def testCreateWithAutoDelete(self):
+ global test_result
+ test_result = "" # reset
+ runnable = QRunnable.create(check_test)
+ runnable.run()
+ self.assertEqual(test_result, "test works")
+
+ def testwithQThreadPool(self):
+ global test_result
+ test_result = "" # reset
+ runnable = QRunnable.create(check_test)
+ tp = QThreadPool.globalInstance()
+ tp.start(runnable)
+ self.assertTrue(tp.waitForDone())
+ self.assertEqual(test_result, "test works")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qsettings_test.ini b/sources/pyside6/tests/QtCore/qsettings_test.ini
new file mode 100644
index 000000000..f54ae0029
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qsettings_test.ini
@@ -0,0 +1,4 @@
+[General]
+var1=a, b, c
+var2=a
+
diff --git a/sources/pyside6/tests/QtCore/qsettings_test.py b/sources/pyside6/tests/QtCore/qsettings_test.py
new file mode 100644
index 000000000..64ceffd70
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qsettings_test.py
@@ -0,0 +1,130 @@
+# 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 cases for QDate'''
+
+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 QDir, QSettings, QTemporaryDir, QByteArray
+
+
+class TestQSettings(unittest.TestCase):
+ def testConversions(self):
+ file = Path(__file__).resolve().parent / 'qsettings_test.ini'
+ self.assertTrue(file.is_file())
+ file_path = QDir.fromNativeSeparators(os.fspath(file))
+ settings = QSettings(file_path, QSettings.IniFormat)
+
+ r = settings.value('var1')
+ self.assertEqual(type(r), list)
+
+ r = settings.value('var2')
+ self.assertEqual(type(r), str)
+
+ r = settings.value('var2', type=list)
+ self.assertEqual(type(r), list)
+
+ # Test mixed conversions
+ ba = QByteArray("hello".encode("utf-8"))
+
+ r = settings.value("test", ba, type=QByteArray)
+ self.assertEqual(type(r), QByteArray)
+
+ r = settings.value("test", ba, type=str)
+ self.assertEqual(type(r), str)
+
+ # Test invalid conversions
+ with self.assertRaises(TypeError):
+ r = settings.value("test", ba, type=dict)
+
+ def testDefaultValueConversion(self):
+ temp_dir = QDir.tempPath()
+ dir = QTemporaryDir(f'{temp_dir}/qsettings_XXXXXX')
+ self.assertTrue(dir.isValid())
+ file_name = dir.filePath('foo.ini')
+ settings = QSettings(file_name, QSettings.IniFormat)
+ sample_list = ["a", "b"]
+ string_list_of_empty = [""]
+ settings.setValue('zero_value', 0)
+ settings.setValue('empty_list', [])
+ settings.setValue('some_strings', sample_list)
+ settings.setValue('string_list_of_empty', string_list_of_empty)
+ settings.setValue('bool1', False)
+ settings.setValue('bool2', True)
+ del settings
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ # Loading values already set
+ settings = QSettings(file_name, QSettings.IniFormat)
+
+ # Getting value that doesn't exist
+ r = settings.value("variable")
+ self.assertEqual(type(r), type(None))
+
+ r = settings.value("variable", type=list)
+ self.assertEqual(type(r), list)
+ self.assertEqual(len(r), 0)
+
+ # Handling zero value
+ r = settings.value('zero_value')
+ self.assertEqual(type(r), int)
+
+ r = settings.value('zero_value', type=int)
+ self.assertEqual(type(r), int)
+
+ # Empty list
+ r = settings.value('empty_list')
+ self.assertTrue(len(r) == 0)
+ self.assertEqual(type(r), list)
+
+ r = settings.value('empty_list', type=list)
+ self.assertTrue(len(r) == 0)
+ self.assertEqual(type(r), list)
+
+ r = settings.value('some_strings')
+ self.assertEqual(r, sample_list)
+
+ r = settings.value('some_strings', type=list)
+ self.assertEqual(r, sample_list)
+
+ r = settings.value('string_list_of_empty', type=list)
+ self.assertEqual(r, string_list_of_empty)
+
+ # Booleans
+ r = settings.value('bool1')
+ self.assertEqual(type(r), bool)
+
+ r = settings.value('bool2')
+ self.assertEqual(type(r), bool)
+
+ r = settings.value('bool1', type=bool)
+ self.assertEqual(type(r), bool)
+
+ r = settings.value('bool2', type=int)
+ self.assertEqual(type(r), int)
+
+ r = settings.value('bool2', type=bool)
+ self.assertEqual(type(r), bool)
+
+ # Not set variable, but with default value
+ r = settings.value('lala', 22, type=bytes)
+ self.assertEqual(type(r), bytes)
+
+ r = settings.value('lala', 22, type=int)
+ self.assertEqual(type(r), int)
+
+ r = settings.value('lala', 22, type=float)
+ self.assertEqual(type(r), float)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qsharedmemory_client.py b/sources/pyside6/tests/QtCore/qsharedmemory_client.py
new file mode 100644
index 000000000..d16c36da9
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qsharedmemory_client.py
@@ -0,0 +1,36 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Client for the unit test of QSharedMemory'''
+
+import sys
+
+from PySide6.QtCore import QSharedMemory
+
+
+def read_string(shared_memory):
+ """Read out a null-terminated string from the QSharedMemory"""
+ mv = memoryview(shared_memory.constData())
+ result = ''
+ for i in range(shared_memory.size()):
+ char = mv[i]
+ if not char:
+ break
+ result += chr(char)
+ return result
+
+
+if __name__ == '__main__':
+ if len(sys.argv) != 2:
+ print('Pass segment name', file=sys.stderr)
+ sys.exit(-1)
+ shared_memory = QSharedMemory(sys.argv[1])
+ if not shared_memory.attach(QSharedMemory.ReadOnly):
+ raise SystemError(f'attach to "{name}" failed')
+ if not shared_memory.lock():
+ raise SystemError(f'lock of "{name}" failed')
+ data = read_string(shared_memory)
+ shared_memory.unlock()
+ shared_memory.detach()
+ sys.stdout.write(data)
+ sys.exit(0)
diff --git a/sources/pyside6/tests/QtCore/qsharedmemory_test.py b/sources/pyside6/tests/QtCore/qsharedmemory_test.py
new file mode 100644
index 000000000..ed8a47939
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qsharedmemory_test.py
@@ -0,0 +1,73 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Unit tests for QSharedMemory'''
+
+import ctypes
+import os
+import subprocess
+import sys
+import unittest
+
+from pathlib import Path
+FILE = Path(__file__).resolve()
+sys.path.append(os.fspath(FILE.parents[1]))
+from init_paths import init_test_paths
+init_test_paths(False)
+
+from PySide6.QtCore import QSharedMemory, QRandomGenerator, qVersion
+from qsharedmemory_client import read_string
+
+
+TEST_STRING = 'ABCD'
+
+
+def run(cmd):
+ # FIXME Python 3.7: Use subprocess.run()
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=False,
+ universal_newlines=True)
+ output, error = proc.communicate()
+ proc.wait()
+ return_code = proc.returncode
+ return (return_code, output, error)
+
+
+class QSharedMemoryTest(unittest.TestCase):
+
+ def setUp(self):
+ r = QRandomGenerator.global_().bounded(1000)
+ v = qVersion()
+ self._name = f"pyside{v}_test_{r}"
+ print(self._name)
+ self._shared_memory = QSharedMemory(self._name)
+
+ def tearDown(self):
+ if self._shared_memory.isAttached():
+ self._shared_memory.detach()
+
+ def test(self):
+ # Create and write
+ self.assertTrue(self._shared_memory.create(1024, QSharedMemory.ReadWrite))
+ self.assertTrue(self._shared_memory.lock())
+ mv = memoryview(self._shared_memory.data())
+ for idx, c in enumerate(TEST_STRING + chr(0)):
+ mv[idx] = ord(c)
+ mv = None
+ self.assertTrue(self._shared_memory.unlock())
+
+ # Read
+ self.assertTrue(self._shared_memory.lock())
+ self.assertEqual(read_string(self._shared_memory), TEST_STRING)
+ self.assertTrue(self._shared_memory.unlock())
+
+ # Run a subprocess and let it read
+ client = FILE.parent / 'qsharedmemory_client.py'
+ returncode, output, error = run([sys.executable, client, self._name])
+ if error:
+ print(error, file=sys.stderr)
+ self.assertEqual(returncode, 0)
+ self.assertEqual(output, TEST_STRING)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qsize_test.py b/sources/pyside6/tests/QtCore/qsize_test.py
new file mode 100644
index 000000000..bc324ba73
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qsize_test.py
@@ -0,0 +1,37 @@
+#!/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
+
+'''Unit tests for QSize'''
+
+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 QSize
+
+
+class QSizeOperator(unittest.TestCase):
+ def testOperatorMultiply(self):
+ # QSize operator * float
+ # bug 131
+ a = QSize(1, 1)
+ x = a * 3.4
+ self.assertEqual(QSize(3, 3), x)
+
+ def testOperatorRevertedMultiply(self):
+ # QSize operator * float, reverted
+ # bug 132
+ a = QSize(1, 1)
+ x = 3.4 * a
+ self.assertEqual(QSize(3, 3), x)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/qslot_object_test.py b/sources/pyside6/tests/QtCore/qslot_object_test.py
new file mode 100644
index 000000000..a95afb090
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qslot_object_test.py
@@ -0,0 +1,54 @@
+#!/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.QtCore import QCoreApplication, QObject, QTimer
+
+"""
+This is a simple slot test that was updated to use the qApp "macro".
+It is implicitly in builtins and does not need an import.
+"""
+
+
+class objTest(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ self.ok = False
+
+ def slot(self):
+ self.ok = True
+ qApp.quit() # noqa: F821
+
+
+class slotTest(unittest.TestCase):
+ def quit_app(self):
+ qApp.quit() # noqa: F821
+
+ def testBasic(self):
+ timer = QTimer()
+ timer.setInterval(100)
+
+ my_obj = objTest()
+ timer.timeout.connect(my_obj.slot)
+ timer.start(100)
+
+ QTimer.singleShot(1000, self.quit_app)
+ qApp.exec() # noqa: F821
+
+ self.assertTrue(my_obj.ok)
+
+
+if __name__ == '__main__':
+ QCoreApplication()
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qsocketnotifier_test.py b/sources/pyside6/tests/QtCore/qsocketnotifier_test.py
new file mode 100644
index 000000000..2e812947c
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qsocketnotifier_test.py
@@ -0,0 +1,38 @@
+#!/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
+
+'''Unit tests for QUuid'''
+
+import os
+import socket
+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 QCoreApplication, QSocketNotifier
+
+
+class QSocketNotifierTest(unittest.TestCase):
+ def testClass(self):
+ app = QCoreApplication([])
+ # socketpair is not available on Windows
+ if os.name != "nt":
+ w_sock, r_sock = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
+
+ self.assertIsInstance(r_sock.fileno(), int)
+
+ notifier = QSocketNotifier(r_sock.fileno(), QSocketNotifier.Read)
+
+ self.assertIsNotNone(notifier)
+
+ w_sock.close()
+ r_sock.close()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qsrand_test.py b/sources/pyside6/tests/QtCore/qsrand_test.py
new file mode 100644
index 000000000..fef44261b
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qsrand_test.py
@@ -0,0 +1,33 @@
+# 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 QRandomGenerator
+
+
+class OverflowExceptionCollect(unittest.TestCase):
+ '''Test case for OverflowError exception during garbage collection. See bug #147'''
+
+ def assertRaises(self, *args, **kwds):
+ if not hasattr(sys, "pypy_version_info"):
+ # PYSIDE-535: PyPy complains "Fatal RPython error: NotImplementedError"
+ return super().assertRaises(*args, **kwds)
+
+ def testOverflow(self):
+ # NOTE: PyQt4 raises TypeError, but boost.python raises OverflowError
+ self.assertRaises(OverflowError, QRandomGenerator, 42415335332353253)
+ # should not abort if bug #147 is fixed
+ gc.collect()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qstandardpaths_test.py b/sources/pyside6/tests/QtCore/qstandardpaths_test.py
new file mode 100644
index 000000000..b8274769b
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qstandardpaths_test.py
@@ -0,0 +1,32 @@
+#!/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
+
+'''Unit tests for QStandardPaths'''
+
+import ctypes
+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 QStandardPaths
+
+
+class QStandardPathsTest(unittest.TestCase):
+ def testTestModeEnabled(self):
+ print("QStandardPaths.isTestModeEnabled:", QStandardPaths.isTestModeEnabled())
+ sp = True
+ QStandardPaths.setTestModeEnabled(sp)
+ self.assertEqual(QStandardPaths.isTestModeEnabled(), sp)
+ sp = False
+ QStandardPaths.setTestModeEnabled(sp)
+ self.assertEqual(QStandardPaths.isTestModeEnabled(), sp)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qstorageinfo_test.py b/sources/pyside6/tests/QtCore/qstorageinfo_test.py
new file mode 100644
index 000000000..5869d9f00
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qstorageinfo_test.py
@@ -0,0 +1,26 @@
+#!/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
+
+'''Unit tests for QStorageInfo'''
+
+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 QStorageInfo
+
+
+class QandardPathsTest(unittest.TestCase):
+ def testQStorageInfo(self):
+ for v in QStorageInfo.mountedVolumes():
+ print(v.name(), v.rootPath(), v.device())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qstring_test.py b/sources/pyside6/tests/QtCore/qstring_test.py
new file mode 100644
index 000000000..d740eeeef
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qstring_test.py
@@ -0,0 +1,37 @@
+#!/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
+
+'''Test cases for QString'''
+
+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
+
+
+class QStringConstructor(unittest.TestCase):
+ '''Test case for QString constructors'''
+
+ def testQStringDefault(self):
+ obj = QObject()
+ obj.setObjectName('foo')
+ self.assertEqual(obj.objectName(), 'foo')
+ obj.setObjectName('áâãà')
+ self.assertEqual(obj.objectName(), 'áâãà')
+ obj.setObjectName('A\x00B')
+ self.assertEqual(obj.objectName(), 'A\x00B')
+ obj.setObjectName('ä\x00B')
+ self.assertEqual(obj.objectName(), 'ä\x00B')
+ obj.setObjectName(None)
+ self.assertEqual(obj.objectName(), '')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qsysinfo_test.py b/sources/pyside6/tests/QtCore/qsysinfo_test.py
new file mode 100644
index 000000000..602852fab
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qsysinfo_test.py
@@ -0,0 +1,28 @@
+# 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 QSysInfo
+
+
+class TestQSysInfo(unittest.TestCase):
+
+ def testEnumEndian(self):
+ self.assertEqual(QSysInfo.BigEndian.value, 0)
+ self.assertEqual(QSysInfo.LittleEndian.value, 1)
+ self.assertTrue(QSysInfo.ByteOrder.value > -1)
+
+ def testEnumSizes(self):
+ self.assertTrue(QSysInfo.WordSize.value > 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qtextstream_test.py b/sources/pyside6/tests/QtCore/qtextstream_test.py
new file mode 100644
index 000000000..d4ed94e14
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qtextstream_test.py
@@ -0,0 +1,92 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Unit tests for QTextStream'''
+
+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 QByteArray, QTextStream, QIODevice, QFile
+
+
+class QTextStreamShiftTest(unittest.TestCase):
+
+ def setUp(self):
+ self.ba = QByteArray()
+ self.read = QTextStream(self.ba, QIODevice.ReadOnly)
+ self.write = QTextStream(self.ba, QIODevice.WriteOnly)
+
+ def testNumber(self):
+ '''QTextStream << number'''
+
+ self.write << '4'
+ self.write.flush()
+ res = self.read.readLine()
+ self.assertTrue(isinstance(res, str))
+ self.assertEqual(res, '4')
+
+
+class QTextStreamGetSet(unittest.TestCase):
+
+ def setUp(self):
+ self.obj = QTextStream()
+
+ def testDevice(self):
+ '''QTextStream get/set Device'''
+ device = QFile()
+ self.obj.setDevice(device)
+ self.assertEqual(device, self.obj.device())
+ self.obj.setDevice(None)
+ self.assertEqual(None, self.obj.device())
+
+
+class QTextStreamInitialization(unittest.TestCase):
+
+ def testConstruction(self):
+ '''QTextStream construction'''
+ obj = QTextStream()
+
+ self.assertEqual(obj.device(), None)
+ self.assertEqual(obj.string(), None)
+
+ self.assertTrue(obj.atEnd())
+ self.assertEqual(obj.readAll(), '')
+
+
+class QTextStreamReadLinesFromDevice(unittest.TestCase):
+
+ def _check_data(self, data_set):
+
+ for data, lines in data_set:
+ stream = QTextStream(data)
+
+ res = []
+ while not stream.atEnd():
+ res.append(stream.readLine())
+
+ self.assertEqual(res, lines)
+
+ def testLatin1(self):
+ '''QTextStream readLine for simple Latin1 strings'''
+
+ data = []
+
+ data.append((QByteArray(), []))
+ data.append((QByteArray(bytes('\n', "UTF-8")), ['']))
+ data.append((QByteArray(bytes('\r\n', "UTF-8")), ['']))
+ data.append((QByteArray(bytes('ole', "UTF-8")), ['ole']))
+ data.append((QByteArray(bytes('ole\n', "UTF-8")), ['ole']))
+ data.append((QByteArray(bytes('ole\r\n', "UTF-8")), ['ole']))
+ data.append((QByteArray(bytes('ole\r\ndole\r\ndoffen', "UTF-8")), ['ole', 'dole', 'doffen']))
+
+ self._check_data(data)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qthread_prod_cons_test.py b/sources/pyside6/tests/QtCore/qthread_prod_cons_test.py
new file mode 100644
index 000000000..a179c936f
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qthread_prod_cons_test.py
@@ -0,0 +1,116 @@
+#!/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
+
+'''Producer-Consumer test/example with QThread'''
+
+import gc
+import logging
+import os
+from random import random
+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)
+
+logging.basicConfig(level=logging.WARNING)
+
+from PySide6.QtCore import QThread, QCoreApplication, QObject, SIGNAL
+
+
+class Bucket(QObject):
+ '''Dummy class to hold the produced values'''
+ def __init__(self, max_size=10, *args):
+ # Constructor which receives the max number of produced items
+ super().__init__(*args)
+ self.data = []
+ self.max_size = 10
+
+ def pop(self):
+ # Retrieves an item
+ return self.data.pop(0)
+
+ def push(self, data):
+ # Pushes an item
+ self.data.append(data)
+
+
+class Producer(QThread):
+ '''Producer thread'''
+
+ def __init__(self, bucket, *args):
+ # Constructor. Receives the bucket
+ super().__init__(*args)
+ self.runs = 0
+ self.bucket = bucket
+ self.production_list = []
+
+ def run(self):
+ # Produces at most bucket.max_size items
+ while self.runs < self.bucket.max_size:
+ value = int(random() * 10) % 10
+ self.bucket.push(value)
+ self.production_list.append(value)
+ logging.debug(f'PRODUCER - pushed {value}')
+ self.runs += 1
+ self.msleep(5)
+
+
+class Consumer(QThread):
+ '''Consumer thread'''
+ def __init__(self, bucket, *args):
+ # Constructor. Receives the bucket
+ super().__init__(*args)
+ self.runs = 0
+ self.bucket = bucket
+ self.consumption_list = []
+
+ def run(self):
+ # Consumes at most bucket.max_size items
+ while self.runs < self.bucket.max_size:
+ try:
+ value = self.bucket.pop()
+ self.consumption_list.append(value)
+ logging.debug(f'CONSUMER - got {value}')
+ self.runs += 1
+ except IndexError:
+ logging.debug('CONSUMER - empty bucket')
+ self.msleep(5)
+
+
+class ProducerConsumer(unittest.TestCase):
+ '''Basic test case for producer-consumer QThread'''
+
+ def setUp(self):
+ # Create fixtures
+ self.app = QCoreApplication([])
+
+ def tearDown(self):
+ # Destroy fixtures
+ del self.app
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testProdCon(self):
+ # QThread producer-consumer example
+ bucket = Bucket()
+ prod = Producer(bucket)
+ cons = Consumer(bucket)
+
+ cons.finished.connect(QCoreApplication.quit)
+ prod.start()
+ cons.start()
+
+ self.app.exec()
+
+ self.assertTrue(prod.wait(1000))
+ self.assertTrue(cons.wait(1000))
+
+ self.assertEqual(prod.production_list, cons.consumption_list)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qthread_signal_test.py b/sources/pyside6/tests/QtCore/qthread_signal_test.py
new file mode 100644
index 000000000..4e312dcc8
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qthread_signal_test.py
@@ -0,0 +1,71 @@
+# 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 cases for connecting signals between threads'''
+
+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 QThread, QTimer, QObject, Signal, Slot, QCoreApplication
+
+
+class Source(QObject):
+ source = Signal()
+
+ def __init__(self, *args):
+ super().__init__(*args)
+
+ @Slot()
+ def emit_sig(self):
+ self.source.emit()
+
+
+class Target(QObject):
+ def __init__(self, *args):
+ super().__init__(*args)
+ self.called = False
+
+ @Slot()
+ def myslot(self):
+ self.called = True
+
+
+class ThreadJustConnects(QThread):
+ def __init__(self, source, *args):
+ super().__init__(*args)
+ self.source = source
+ self.target = Target()
+
+ def run(self):
+ self.source.source.connect(self.target.myslot)
+ self.source.source.connect(self.quit)
+ self.exec()
+
+
+class BasicConnection(unittest.TestCase):
+
+ def testEmitOutsideThread(self):
+ global thread_run
+
+ app = QCoreApplication([])
+ source = Source()
+ thread = ThreadJustConnects(source)
+
+ thread.finished.connect(QCoreApplication.quit)
+ thread.start()
+
+ QTimer.singleShot(50, source.emit_sig)
+ app.exec()
+ thread.wait()
+
+ self.assertTrue(thread.target.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qthread_test.py b/sources/pyside6/tests/QtCore/qthread_test.py
new file mode 100644
index 000000000..4d26e0597
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qthread_test.py
@@ -0,0 +1,84 @@
+#!/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
+
+'''Test cases for QThread'''
+
+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 QThread, QCoreApplication, QObject, QTimer, Slot
+from PySide6.QtCore import QEventLoop
+
+from helper.usesqapplication import UsesQApplication
+
+
+class Dummy(QThread):
+ '''Dummy thread'''
+ def __init__(self, *args):
+ super().__init__(*args)
+ self.called = False
+
+ def run(self):
+ # Start-quit sequence
+ self.qobj = QObject()
+ self.called = True
+
+
+class QThreadSimpleCase(UsesQApplication):
+
+ def setUp(self):
+ UsesQApplication.setUp(self)
+ self._started_called = False
+ self._finished_called = False
+ self.called = False
+
+ def testThread(self):
+ # Basic QThread test
+ obj = Dummy()
+ obj.start()
+ self.assertTrue(obj.wait(100))
+
+ self.assertTrue(obj.called)
+
+ @Slot()
+ def abort_application(self):
+ if self._thread.isRunning():
+ print("Warning: terminating thread", file=sys.stderr)
+ self._thread.terminate()
+ self.app.quit()
+
+ @Slot()
+ def finished(self):
+ self._finished_called = True
+
+ @Slot()
+ def started(self):
+ self._started_called = True
+
+ def testSignals(self):
+ # QThread.finished() (signal)
+ self._thread = Dummy()
+ self._thread.started.connect(self.started)
+ self._thread.finished.connect(self.finished)
+ self._thread.finished.connect(self.app.quit)
+
+ QTimer.singleShot(50, self._thread.start)
+ QTimer.singleShot(1000, self.abort_application)
+
+ self.app.exec()
+ if self._thread.isRunning():
+ self._thread.wait(100)
+
+ self.assertTrue(self._started_called)
+ self.assertTrue(self._finished_called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qtimer_singleshot_test.py b/sources/pyside6/tests/QtCore/qtimer_singleshot_test.py
new file mode 100644
index 000000000..2ccaa300e
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qtimer_singleshot_test.py
@@ -0,0 +1,195 @@
+#!/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
+
+'''Test cases for QTimer.singleShot'''
+
+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, QThread, QTimer, Signal, Slot, SLOT
+from helper.usesqapplication import UsesQApplication
+
+
+class WatchDog(QObject):
+ '''Exits the QCoreApplication main loop after sometime.'''
+
+ def __init__(self, watched):
+ super().__init__()
+ self.times_called = 0
+ self.watched = watched
+
+ def timerEvent(self, evt):
+ self.times_called += 1
+ if self.times_called == 20:
+ self.watched.exit_app_cb()
+
+
+class ThreadForContext(QThread):
+ def __init__(self):
+ super().__init__()
+ self.called = False
+ self.qthread = None
+ self.context = QObject()
+
+ def run(self):
+ self.called = True
+ self.qthread = QThread.currentThread()
+ self.exec()
+
+
+class TestSingleShot(UsesQApplication):
+ '''Test case for QTimer.singleShot'''
+
+ def setUp(self):
+ # Acquire resources
+ UsesQApplication.setUp(self)
+ self.watchdog = WatchDog(self)
+ self.called = False
+ self.qthread = None
+
+ def tearDown(self):
+ # Release resources
+ del self.watchdog
+ del self.called
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ UsesQApplication.tearDown(self)
+
+ def callback(self):
+ self.called = True
+ self.qthread = QThread.currentThread()
+ self.qthread.exit()
+ self.app.quit()
+
+ def testSingleShot(self):
+ QTimer.singleShot(100, self.callback)
+ self.app.exec()
+ self.assertTrue(self.called)
+
+ def testSingleShotZero(self):
+ QTimer.singleShot(0, self.callback)
+ self.app.exec()
+ self.assertTrue(self.called)
+
+ def testSingleShotWithContext(self):
+ thread = ThreadForContext()
+ thread.start()
+ thread.context.moveToThread(thread)
+ QTimer.singleShot(100, thread.context, self.callback)
+ self.app.exec()
+ thread.wait()
+ self.assertTrue(self.called)
+ self.assertTrue(thread.called)
+ self.assertEqual(self.qthread, thread.qthread)
+
+ def testSingleShotWithContextZero(self):
+ thread = ThreadForContext()
+ thread.start()
+ thread.context.moveToThread(thread)
+ QTimer.singleShot(0, thread.context, self.callback)
+ self.app.exec()
+ thread.wait()
+ self.assertTrue(self.called)
+ self.assertTrue(thread.called)
+ self.assertEqual(self.qthread, thread.qthread)
+
+
+class TestSingleShotCallableObject(UsesQApplication):
+ '''Test case for QTimer.singleShot with callable inside an object'''
+
+ def setUp(self):
+ # Acquire resources
+ UsesQApplication.setUp(self)
+ self.watchdog = WatchDog(self)
+
+ def tearDown(self):
+ # Release resources
+ del self.watchdog
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ UsesQApplication.tearDown(self)
+
+ class CallbackObject(QObject):
+ def __init__(self, app) -> None:
+ super().__init__()
+ self.app = app
+
+ @Slot()
+ def func(self):
+ self.called = True
+ self.app.quit()
+
+ def testSingleShotWithObjectAndMember(self):
+ callback = self.CallbackObject(self.app)
+ QTimer.singleShot(100, callback, SLOT("func()"))
+ self.app.exec()
+ self.assertTrue(callback.called)
+
+ def testSingleShotWithObjectAndMemberZero(self):
+ callback = self.CallbackObject(self.app)
+ QTimer.singleShot(0, callback, SLOT("func()"))
+ self.app.exec()
+ self.assertTrue(callback.called)
+
+ def testSingleShotWithCallableInObject(self):
+ callback = self.CallbackObject(self.app)
+ QTimer.singleShot(100, callback.func)
+ self.app.exec()
+ self.assertTrue(callback.called)
+
+ def testSingleShotWithCallableInObjectZero(self):
+ callback = self.CallbackObject(self.app)
+ QTimer.singleShot(0, callback.func)
+ self.app.exec()
+ self.assertTrue(callback.called)
+
+
+class SigEmitter(QObject):
+
+ sig1 = Signal()
+
+
+class TestSingleShotSignal(UsesQApplication):
+ '''Test case for QTimer.singleShot connecting to signals'''
+
+ def setUp(self):
+ UsesQApplication.setUp(self)
+ self.watchdog = WatchDog(self)
+ self.called = False
+
+ def tearDown(self):
+ del self.watchdog
+ del self.called
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ UsesQApplication.tearDown(self)
+
+ def callback(self):
+ self.called = True
+ self.app.quit()
+
+ def testSingleShotSignal(self):
+ emitter = SigEmitter()
+ emitter.sig1.connect(self.callback)
+ QTimer.singleShot(100, emitter.sig1)
+ self.app.exec()
+ self.assertTrue(self.called)
+
+ def testSingleShotSignalZero(self):
+ emitter = SigEmitter()
+ emitter.sig1.connect(self.callback)
+ QTimer.singleShot(0, emitter.sig1)
+ self.app.exec()
+ self.assertTrue(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qtimer_timeout_test.py b/sources/pyside6/tests/QtCore/qtimer_timeout_test.py
new file mode 100644
index 000000000..70f151989
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qtimer_timeout_test.py
@@ -0,0 +1,73 @@
+# 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 case for timeout() signals from QTimer object.'''
+
+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, QTimer, SIGNAL
+from helper.usesqapplication import UsesQApplication
+
+
+class WatchDog(QObject):
+ '''Exits the QCoreApplication main loop after sometime.'''
+
+ def __init__(self, watched):
+ super().__init__()
+ self.times_called = 0
+ self.watched = watched
+
+ def timerEvent(self, evt):
+ self.times_called += 1
+ if self.times_called == 20:
+ self.watched.exit_app_cb()
+
+
+class TestTimeoutSignal(UsesQApplication):
+ '''Test case to check if the signals are really being caught'''
+
+ def setUp(self):
+ # Acquire resources
+ super().setUp()
+ self.watchdog = WatchDog(self)
+ self.timer = QTimer()
+ self.called = False
+
+ def tearDown(self):
+ # Release resources
+ del self.watchdog
+ del self.timer
+ del self.called
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super().tearDown()
+
+ def callback(self, *args):
+ # Default callback
+ self.called = True
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testTimeoutSignal(self):
+ # Test the QTimer timeout() signal
+ refCount = sys.getrefcount(self.timer)
+ self.timer.timeout.connect(self.callback)
+ self.timer.start(4)
+ self.watchdog.startTimer(10)
+
+ self.app.exec()
+
+ self.assertTrue(self.called)
+ self.assertEqual(sys.getrefcount(self.timer), refCount)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/qtimezone_test.py b/sources/pyside6/tests/QtCore/qtimezone_test.py
new file mode 100644
index 000000000..ad953f1cc
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qtimezone_test.py
@@ -0,0 +1,27 @@
+# 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 QTimeZone
+
+
+class TestQTimeZone (unittest.TestCase):
+ def testTimeZone(self):
+ id = bytes('Europe/Berlin', "UTF-8")
+ timeZone = QTimeZone(id)
+ self.assertTrue(timeZone.isValid())
+ self.assertEqual(timeZone.id(), id)
+ name = timeZone.displayName(QTimeZone.GenericTime, QTimeZone.DefaultName)
+ self.assertTrue(name)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qtnamespace_test.py b/sources/pyside6/tests/QtCore/qtnamespace_test.py
new file mode 100644
index 000000000..c08c727ec
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qtnamespace_test.py
@@ -0,0 +1,30 @@
+#!/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
+
+'''Test suite for QtCore.Qt namespace'''
+
+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 Qt
+
+
+class QtNamespace(unittest.TestCase):
+ '''Test case for accessing attributes from Qt namespace'''
+
+ def testBasic(self):
+ # Access to Qt namespace
+ getattr(Qt, 'Horizontal')
+ getattr(Qt, 'WindowMaximizeButtonHint')
+ self.assertTrue(True)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/quoteEnUS.txt b/sources/pyside6/tests/QtCore/quoteEnUS.txt
new file mode 100644
index 000000000..909b4fa17
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/quoteEnUS.txt
@@ -0,0 +1 @@
+Fine! Dishonor! Dishonor on you, dishonor on ya cow!
diff --git a/sources/pyside6/tests/QtCore/qurl_test.py b/sources/pyside6/tests/QtCore/qurl_test.py
new file mode 100644
index 000000000..df16c74e0
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qurl_test.py
@@ -0,0 +1,149 @@
+#!/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
+
+'''Test suite for QtCore.QUrl'''
+
+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 QUrl
+from PySide6.QtCore import QUrlQuery
+
+
+class QUrlBasicConstructor(unittest.TestCase):
+ '''Tests the basic constructors'''
+
+ def testBasic(self):
+ # Default constructor for QUrl
+ url = QUrl()
+ self.assertEqual(url.toString(), "")
+
+ def testSetAttributes(self):
+ # Construct QUrl by set* methods
+ url = QUrl()
+
+ url.setScheme('ftp')
+ self.assertEqual(url.toString(), 'ftp:')
+
+ url.setHost('www.google.com')
+ self.assertEqual(url.toString(), 'ftp://www.google.com')
+
+ url.setPort(8080)
+ self.assertEqual(url.toString(), 'ftp://www.google.com:8080')
+
+ url.setPath('/mail/view')
+ self.assertEqual(url.toString(),
+ 'ftp://www.google.com:8080/mail/view')
+
+ url.setUserName('john')
+ self.assertEqual(url.toString(),
+ 'ftp://john@www.google.com:8080/mail/view')
+
+ url.setPassword('abc123')
+ self.assertEqual(url.toString(),
+ 'ftp://john:abc123@www.google.com:8080/mail/view')
+
+
+class QueryItemsTest(unittest.TestCase):
+ '''Test query item management'''
+
+ def testQueryItems(self):
+ url = QUrl('http://www.google.com/search?q=python&hl=en')
+ valid_data = [(('q'), ('python')), (('hl'), ('en'))]
+
+ self.assertEqual(sorted(QUrlQuery(url.query()).queryItems()), sorted(valid_data))
+
+ def testEncodedQueryItems(self):
+ url = QUrl('http://www.google.com/search?q=python&hl=en')
+ valid_data = [(('q'), ('python')), (('hl'), ('en'))]
+
+ self.assertEqual(sorted(QUrlQuery(url.query()).queryItems()), sorted(valid_data))
+
+ def testSetQueryItems(self):
+ urla = QUrl('http://www.google.com/search?q=python&hl=en')
+ urlb = QUrl('http://www.google.com/search')
+
+ urlb.setQuery(urla.query())
+
+ self.assertEqual(urla, urlb)
+
+ def testAddQueryItem(self):
+ url = QUrlQuery()
+ valid_data = [('hl', 'en'), ('user', 'konqui')]
+
+ url.addQueryItem(*valid_data[0])
+ self.assertEqual(url.queryItems()[0], valid_data[0])
+
+ url.addQueryItem(*valid_data[1])
+ self.assertEqual(sorted(url.queryItems()), sorted(valid_data))
+
+ def testAllQueryItemsValues(self):
+ url = QUrlQuery()
+ key = 'key'
+ valid_data = ['data', 'valid', 'test']
+
+ for i, data in enumerate(valid_data):
+ url.addQueryItem(key, data)
+ self.assertEqual(url.allQueryItemValues(key),
+ list(valid_data[:i + 1]))
+
+ def testPath(self):
+ url = QUrl("http://qt-project.org/images/ban/pgs_front.jpg")
+ self.assertEqual(url.path(), "/images/ban/pgs_front.jpg")
+
+# PYSIDE-345: No bindings for QUrlQuery
+
+
+class QueryItemsTest(unittest.TestCase):
+ '''Test query item management'''
+
+ def testQueryItems(self):
+ url = QUrl('http://www.google.com/search?q=python&hl=en')
+ valid_data = [(('q'), ('python')), (('hl'), ('en'))]
+
+ self.assertEqual(sorted(QUrlQuery(url.query()).queryItems()), sorted(valid_data))
+
+ def testEncodedQueryItems(self):
+ url = QUrl('http://www.google.com/search?q=python&hl=en')
+ valid_data = [(('q'), ('python')), (('hl'), ('en'))]
+
+ self.assertEqual(sorted(QUrlQuery(url.query()).queryItems()), sorted(valid_data))
+
+ def testSetQueryItems(self):
+ urla = QUrl('http://www.google.com/search?q=python&hl=en')
+ urlb = QUrl('http://www.google.com/search')
+
+ urlb.setQuery(urla.query())
+
+ self.assertEqual(urla, urlb)
+
+ def testAddQueryItem(self):
+ url = QUrlQuery()
+ valid_data = [('hl', 'en'), ('user', 'konqui')]
+
+ url.addQueryItem(*valid_data[0])
+ self.assertEqual(url.queryItems()[0], valid_data[0])
+
+ url.addQueryItem(*valid_data[1])
+ self.assertEqual(sorted(url.queryItems()), sorted(valid_data))
+
+ def testAllQueryItemsValues(self):
+ url = QUrlQuery()
+ key = 'key'
+ valid_data = ['data', 'valid', 'test']
+
+ for i, data in enumerate(valid_data):
+ url.addQueryItem(key, data)
+ self.assertEqual(url.allQueryItemValues(key),
+ list(valid_data[:i + 1]))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qurlquery_test.py b/sources/pyside6/tests/QtCore/qurlquery_test.py
new file mode 100644
index 000000000..36eb29475
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qurlquery_test.py
@@ -0,0 +1,39 @@
+#!/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
+
+'''Unit tests for QUrlQuery'''
+
+import ctypes
+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 QUrlQuery
+
+
+class QUrlQueryTest(unittest.TestCase):
+ def testConstructing(self):
+ empty = QUrlQuery()
+ self.assertTrue(empty.isEmpty())
+
+ empty.clear()
+ self.assertTrue(empty.isEmpty())
+
+ def testAddRemove(self):
+ query = QUrlQuery()
+
+ query.addQueryItem("a", "b")
+ self.assertTrue(not query.isEmpty())
+ self.assertTrue(query.hasQueryItem("a"))
+ self.assertEqual(query.queryItemValue("a"), "b")
+ self.assertEqual(query.allQueryItemValues("a"), ["b"])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/quuid_test.py b/sources/pyside6/tests/QtCore/quuid_test.py
new file mode 100644
index 000000000..45c6fc89d
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/quuid_test.py
@@ -0,0 +1,29 @@
+#!/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
+
+'''Unit tests for QUuid'''
+
+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 QUuid
+
+
+class QUuidTest(unittest.TestCase):
+ def testFromString(self):
+ uuidString = '{fc69b59e-cc34-4436-a43c-ee95d128b8c5}'
+# testing overload QUUid::fromString(QStringView)
+ uuid = QUuid.fromString(uuidString)
+ self.assertTrue(not uuid.isNull())
+ self.assertEqual(uuid.toString(), uuidString)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/qversionnumber_test.py b/sources/pyside6/tests/QtCore/qversionnumber_test.py
new file mode 100644
index 000000000..23f6ba639
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/qversionnumber_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
+
+'''Unit tests for QVersionNumber'''
+
+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 QVersionNumber
+
+
+class QVersionNumberTest(unittest.TestCase):
+ def testFromString(self):
+ versionString = '5.9.2'
+ version = QVersionNumber.fromString(versionString)
+ self.assertTrue(not version.isNull())
+ self.assertEqual(version.majorVersion(), 5)
+ self.assertEqual(version.minorVersion(), 9)
+ self.assertEqual(version.microVersion(), 2)
+ self.assertEqual(version.toString(), versionString)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/repr_test.py b/sources/pyside6/tests/QtCore/repr_test.py
new file mode 100644
index 000000000..87cceaa82
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/repr_test.py
@@ -0,0 +1,97 @@
+# 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
+from PySide6.QtCore import QByteArray, QDate, QDateTime, QTime, QLine, QLineF
+from PySide6.QtCore import Qt, QSize, QSizeF, QRect, QRectF, QPoint, QPointF
+try:
+ from PySide6.QtCore import QUuid
+ HAVE_Q = True
+except ImportError:
+ HAVE_Q = False
+
+
+class ReprCopyHelper:
+ def testCopy(self):
+ copy = eval(self.original.__repr__())
+ self.assertTrue(copy is not self.original)
+ self.assertEqual(copy, self.original)
+
+
+class QByteArrayReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QByteArray(bytes('the quick brown fox jumps over the lazy dog', "UTF-8"))
+
+
+class QDateReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QDate(2010, 11, 22)
+
+
+class QTimeReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QTime(11, 37, 55, 692)
+
+
+class QDateTimeReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QDateTime(2010, 5, 18, 10, 24, 45, 223, Qt.LocalTime)
+
+
+class QSizeReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QSize(42, 190)
+
+
+class QSizeFReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QSizeF(42.7, 190.2)
+
+
+class QRectReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QRect(100, 200, 300, 400)
+
+
+class QRectFReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QRectF(100.33, 200.254, 300.321, 400.123)
+
+
+class QLineReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QLine(1, 2, 3, 4)
+
+
+class QLineFReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QLineF(1.1, 2.2, 3.3, 4.4)
+
+
+class QPointReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QPoint(1, 2)
+
+
+class QPointFReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QPointF(1.1, 2.2)
+
+
+class QUuiCopy(ReprCopyHelper, unittest.TestCase):
+ @unittest.skipUnless(HAVE_Q, "QUuid is currently not supported on this platform.")
+ def setUp(self):
+ self.original = QUuid("67C8770B-44F1-410A-AB9A-F9B5446F13EE")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/resources.qrc b/sources/pyside6/tests/QtCore/resources.qrc
new file mode 100644
index 000000000..0a0b03d40
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/resources.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file alias="quote.txt">quoteEnUS.txt</file>
+ <file alias="sample.png">sample.png</file>
+ </qresource>
+</RCC>
+
diff --git a/sources/pyside6/tests/QtCore/resources_mc.py b/sources/pyside6/tests/QtCore/resources_mc.py
new file mode 100644
index 000000000..05766a22a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/resources_mc.py
@@ -0,0 +1,3547 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+# Resource object code
+#
+# Created: Thu Feb 3 16:09:36 2011
+# by: The Resource Compiler for PySide (Qt v4.6.3)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PySide6 import QtCore
+
+qt_resource_data = b"""\
+\x00\x00\x00\x35\
+\x46\
+\x69\x6e\x65\x21\x20\x44\x69\x73\x68\x6f\x6e\x6f\x72\x21\x20\x44\
+\x69\x73\x68\x6f\x6e\x6f\x72\x20\x6f\x6e\x20\x79\x6f\x75\x2c\x20\
+\x64\x69\x73\x68\x6f\x6e\x6f\x72\x20\x6f\x6e\x20\x79\x61\x20\x63\
+\x6f\x77\x21\x0a\
+\x00\x00\xda\x88\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\xb1\x00\x00\x00\xd2\x08\x06\x00\x00\x00\x05\x49\x21\x31\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\
+\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\
+\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xda\x03\x0a\
+\x0c\x02\x2e\xb0\x96\x99\x74\x00\x00\x00\x19\x74\x45\x58\x74\x43\
+\x6f\x6d\x6d\x65\x6e\x74\x00\x43\x72\x65\x61\x74\x65\x64\x20\x77\
+\x69\x74\x68\x20\x47\x49\x4d\x50\x57\x81\x0e\x17\x00\x00\x20\x00\
+\x49\x44\x41\x54\x78\xda\x94\xbd\xd9\xaf\x24\xd9\x7a\xdd\xf7\x8b\
+\x21\x33\x77\x44\xe4\x9c\xa7\xaa\xcf\xa9\xb1\xab\x87\x6b\xf2\x92\
+\xd4\x15\x49\x0b\x84\x64\xd9\x22\x64\x3f\xd8\x30\x0c\xd8\x8f\x34\
+\xfc\x68\x43\x7f\x8b\xfe\x04\x02\x06\xfc\x64\xbf\xd1\x06\x04\x13\
+\x7a\x30\x65\x59\x04\x4d\x03\xa4\x48\xba\x29\xf9\x72\xb8\xdd\x5d\
+\x55\x5d\xc3\x39\x75\xea\x9c\x9c\x23\xf6\xce\xcc\x18\xfc\xb0\x87\
+\x88\xc8\xcc\x6a\xd9\xd9\x68\x44\xce\x79\x2a\x73\xc5\x8a\xb5\xd7\
+\xb7\xbe\x2f\xbc\xdf\xff\x17\xbf\x57\x09\x00\x15\x82\xc8\x29\x89\
+\xb0\x97\x24\xaa\x90\x52\x51\x12\x91\x44\x95\xb9\x37\x42\x56\x1e\
+\x91\x97\x91\x4a\xcf\x3d\x27\x8a\x04\x12\x1a\xaf\xd6\xcf\x45\x54\
+\xa0\x3c\x7e\xfc\x22\xeb\xe7\x9b\xeb\xfa\xbd\xea\xdb\x08\x01\x4a\
+\x01\x11\x42\x54\x28\xe5\xe9\x2d\x20\xc0\xdd\x6e\x5e\xdc\x7d\x4a\
+\x02\x7d\x2a\xd1\x73\x8f\x79\x6a\x07\xa2\xa0\x22\xd6\xd7\x81\x24\
+\xdb\xe3\x8d\x87\xad\xf7\xc8\xe3\x12\x80\x30\xf3\xc9\xe3\x92\x30\
+\xf3\x09\x63\x81\x22\x43\x10\x03\x99\x79\x66\x6c\xfe\xce\x12\x94\
+\x5f\xbf\xc1\xd1\xed\x38\x28\xf4\xfb\x85\x11\x79\x2e\xf1\x37\x7d\
+\xb6\xb1\xe4\x61\x76\xe0\xf6\xe5\x82\xc3\x04\x46\xe3\x01\x00\x7d\
+\x42\xb6\xe4\x4c\xbd\x31\xd5\x70\xc3\xc6\xef\x33\x28\xb7\x78\xeb\
+\x01\xeb\x47\x01\x09\x3d\x52\x76\x24\xe8\x7f\x57\x90\x29\x3a\x71\
+\x0f\x45\xfd\x7d\x77\x85\x60\xaf\xd4\xc9\x37\x2e\x44\x81\x52\x01\
+\x82\x0a\x85\x87\xcc\x04\xdf\x7e\xbc\x67\x1c\x06\xfa\xfb\x99\x54\
+\xcc\x98\x50\x72\x4f\x12\x27\x88\x69\x42\x99\x15\x27\xef\xe3\xc7\
+\x41\xeb\xfe\xbd\x52\xc8\x4c\x00\x50\x72\x8f\xcf\x8c\x49\x2c\x29\
+\x45\x84\x1f\x07\x54\x9d\x11\xde\x61\xa5\x1f\xcf\x0a\x56\x73\xb8\
+\x5b\xbc\xa4\x5a\xae\x4f\xde\xdb\x1b\x0f\x19\x52\xf1\xd9\xe3\x11\
+\x4c\x1f\x52\x75\x46\x27\xcf\x79\xf4\xe8\x6b\x42\xfd\x63\x07\x20\
+\x72\x50\x01\xb0\xa7\x2b\xba\xec\x91\xec\xa5\x06\x88\xaf\x0e\x48\
+\x72\x03\x18\x0d\xea\x14\x8f\x3d\x12\x64\xc4\x1e\x40\xda\xfb\x61\
+\x8f\x44\x00\x25\x5e\x8d\x4f\xc0\x47\x52\x12\x31\x2c\x3d\xd6\x7e\
+\xe5\x6e\x83\x47\x15\x65\x78\xd2\xc3\x8f\xa0\x94\xfa\x47\x90\x91\
+\xa4\xb4\x3b\x8a\x52\x06\xd2\x12\x94\x05\xa9\xbe\x47\x99\x5d\x47\
+\x35\x76\x16\x0b\x68\x0d\xe4\x08\xa5\x4a\x03\x66\xe8\x09\xfd\xfc\
+\xca\x00\xaf\x12\x3d\xfa\xf3\x0d\x69\xdc\xa5\xf2\xf5\xeb\x06\xa5\
+\xc7\xc6\xaf\x18\x64\x3e\x79\x2c\xd0\x1f\x1a\x93\xc7\x10\x02\x82\
+\xb8\x01\xe4\x06\x58\x9b\x00\x06\x8a\x2a\x26\x40\x11\x67\x92\x2c\
+\x8e\xc8\x8a\x80\xa2\x27\x98\x50\xd6\xc0\xce\x24\x19\x53\x1e\xbe\
+\x80\x2d\x39\x7d\x42\xd4\x7c\x05\xd3\x11\x7d\x42\xf6\xd5\x16\x56\
+\x1e\x83\xd1\x96\xd5\x6a\x44\x39\xd8\x32\xe2\x82\x42\x1c\x10\xf8\
+\xa0\x34\x80\x01\x14\x1e\x5d\x21\xda\x80\xa5\xa2\x14\x91\x03\x73\
+\x57\x08\x94\x52\xee\x7e\x94\xe2\x2f\x6e\x7e\xce\x24\xeb\xc3\x64\
+\x48\x31\x9a\x10\x2c\x16\x94\x13\x0d\xc2\xae\xf8\x34\xfd\x34\x01\
+\x5c\x55\x63\xba\x62\x09\x68\x20\xfb\xcc\xea\xbf\xc9\x3e\x7f\x59\
+\x12\x24\xf5\x0e\xc0\xbc\x60\xbb\x08\x48\x3c\x48\xab\x09\x89\xb7\
+\x00\x20\x8d\xbb\x24\xcb\x35\x98\x1d\x1a\xc0\x3b\xac\x5a\x40\xf6\
+\x0e\x2b\x92\x7e\x07\xfd\x8d\x0b\xf3\x87\x88\x02\x44\x41\xa6\xe6\
+\x35\x9b\x01\x4a\xe4\x1a\xe8\xe6\xf6\x1e\xc9\x1e\x49\xd7\x80\xa7\
+\x4b\x64\x71\x85\xdf\x40\xed\xbe\x71\xbd\x06\x2c\x6c\xfd\xcc\xec\
+\xa9\x91\x7b\xcc\x93\xb1\x7e\x8e\xf4\xf0\x0d\xeb\x5b\x30\xa7\xd2\
+\x03\xa9\xdc\xbb\xc9\x06\x5f\xcb\x16\x9b\xd7\xcf\x50\xca\xd3\x47\
+\x81\x06\xb8\x85\xa8\xe8\x89\x88\x9d\x92\x20\x0a\xc7\xc0\x9e\xda\
+\xe9\x2f\x30\x38\xb8\x77\xdb\xf8\x15\xd1\x11\xb3\xb7\x18\x3a\x53\
+\xa7\x00\xb6\xc0\xed\x09\xb7\x0d\x76\x35\x80\x5b\xaf\xcf\x25\x59\
+\x11\x10\xb3\x26\x9c\x68\x60\x66\x0c\x99\x7a\x63\xba\x5e\x9f\x7c\
+\x9a\x68\x20\x37\x2e\x87\x95\xa7\x9f\x1f\xea\xf7\x4a\xf0\x89\x18\
+\x20\x44\x41\x11\x0b\x3a\x71\xef\x04\xc0\x80\x06\xea\x19\x66\xb6\
+\xc0\x96\x99\xe0\xe3\xdb\x1c\x80\x65\x5e\x10\xac\x34\x90\x3e\x96\
+\x17\x44\xb1\x3a\x01\xeb\xa7\x2e\x41\xb2\xd1\xdf\x7e\x56\xff\x0d\
+\xf6\xf5\x00\x45\x3a\x20\x48\x36\x54\x9d\x11\x65\x56\x50\xa4\x83\
+\xd6\xe3\x16\xc0\xcb\xaa\x20\xc9\xf6\xa4\x71\xb7\xf5\xfe\x16\xc0\
+\x96\xc9\x01\xd2\xed\x01\x3f\x57\x92\x03\x19\x76\xbb\xc9\x4b\x64\
+\xd8\x63\x93\x97\xe4\x4a\xb2\xc9\x4b\x0e\xee\x90\x69\x7e\x33\x15\
+\x9a\x43\xc7\xbe\x05\x5a\x0b\x72\xcb\x5b\xdd\x86\xb8\x28\x3f\x71\
+\xdd\x8f\x2a\x4a\x22\xfd\x3e\x91\xa8\x81\x6c\xbe\x78\xbb\xb5\xaf\
+\x29\xa5\x57\x33\xf5\xb1\xe4\x70\xd7\x23\x07\xe0\x63\x56\xf6\xcc\
+\xbf\x45\x19\x06\x06\xe8\x77\x05\x24\x29\x69\xd1\x31\xcc\x1c\x18\
+\x00\x1b\x90\x92\x91\xc7\x82\x4c\x1f\x73\xb4\x1c\x88\x85\x79\x9f\
+\x8c\xa2\x8a\xdb\x3f\xe6\x4e\x51\xf4\x04\x83\x3c\xa5\x9f\x45\x2d\
+\x70\x0f\x7b\x5d\x27\x27\xe2\xa0\x60\x3b\xd0\xe0\xf7\x37\x7d\xca\
+\xc1\x96\x65\xe5\xc3\xd8\x27\x9c\x8c\xc8\xa7\x89\xf9\xf4\x5a\xe2\
+\x6c\x07\x3e\x49\x6c\x8f\x44\x01\x3e\x29\x25\x09\x82\xaa\x75\x88\
+\xf7\xe3\xa0\x75\x88\x3f\xbe\xde\x7c\x7e\x3e\xd2\xdf\xe7\x22\xde\
+\x32\x0e\x03\x96\xb9\x06\xec\x67\x7e\xc5\xff\x9f\x4b\x91\x0e\xd8\
+\x2b\xd5\x02\xe6\xb9\xbf\xc1\x3b\xac\xf0\xe3\x80\x20\xd9\x38\xc0\
+\xa7\xd5\x84\x65\x55\xb0\xac\x0a\xc6\x5e\xe0\xe4\x5d\x4b\x5e\x18\
+\xf0\x1e\xcb\x0a\x1f\x40\xe5\xe6\x07\x31\xdb\x6a\xb5\x43\x76\x6f\
+\xc9\x52\xc3\x6b\xf7\x1e\x07\xb1\xa9\x59\x57\xe4\x0e\xa0\xea\x88\
+\x71\xbb\x47\xaa\xf8\xdf\x75\xb1\x80\x6c\x5e\xb7\x4c\xec\x47\x15\
+\xa5\x92\x24\x51\x85\x2f\x22\xf7\xce\xb5\x3e\xaf\xb9\x58\xfe\x88\
+\x0e\x3f\xa7\x97\x05\xe0\x91\x51\x88\x94\x8d\x5f\x69\x20\x43\x83\
+\x7d\x63\xc2\x4c\x19\x29\x11\x1b\x19\x12\xb6\x98\x16\xa0\xd3\x9b\
+\x12\xec\x94\xbb\xff\x18\xa8\x00\x59\x1c\x31\xec\x75\xb5\x84\x88\
+\x43\x26\x71\x5b\x72\x0c\x09\xf0\x1f\x7b\x84\x61\x84\xff\xd8\x63\
+\x1d\x7b\x24\x71\xc2\xe8\xf1\x23\xd4\x24\xc1\x9f\x14\x74\x27\x43\
+\xb6\x03\x9f\x69\xd8\x37\x47\x80\x94\xd5\xfa\xee\x93\x8c\xdb\xbc\
+\x58\x76\xb6\x5b\x61\x8e\xbc\x16\x58\xe1\xaa\x82\xcf\x87\x4c\xb2\
+\xbe\x03\x70\x1b\x24\xe9\x89\x0e\x3e\x77\xf1\xbc\x25\x9d\xde\x65\
+\x8b\x89\x9b\x92\xc6\x32\xb5\x05\x61\x91\x1a\xed\x3f\x29\x38\x70\
+\xe7\xc0\x6b\xc1\x9c\xc6\x5d\x56\xc5\x96\xdc\xdf\x9e\x30\xb1\x05\
+\x74\x52\x76\xf1\xe7\xb1\xbe\x21\xc3\x9e\x03\xef\x7d\x25\x51\xe9\
+\x73\x7d\x7f\xf7\x16\x6f\xd4\xc3\x33\xa0\xd8\x23\x41\x05\x7a\x2b\
+\x0a\xba\x44\x8e\x99\xed\xe3\x25\x91\xd6\xd2\x47\x2c\x7d\x0c\xc0\
+\x13\xc9\xd1\x7c\xcc\xcb\x5a\xbb\x43\xa9\x34\xc3\xfa\x51\x85\x3c\
+\x62\xbe\x7a\x39\x69\x24\x85\xf2\xea\x6d\x53\x52\x58\x80\x9a\x6d\
+\x45\x4c\xa0\x12\x06\xa5\xc7\x76\xaf\xa8\x44\x8f\x4c\x2f\x13\x90\
+\x4a\xb2\xf1\xab\xc6\xc2\x0d\x02\xe5\xd3\x31\x12\xa1\x29\x17\x8a\
+\x9e\xd0\x92\xe2\xdc\x4e\x3a\xd8\xd6\x6c\x1c\xd7\xdf\xd3\x64\x3a\
+\xe3\xb3\xe1\x8c\xd1\xf0\x82\x22\x16\x24\xf4\x98\x4d\x05\x13\x31\
+\x62\x22\x46\x88\x69\x42\x57\x08\x92\x38\x21\x89\x93\x13\xb0\x0a\
+\x62\x46\xc3\x36\x68\x7d\x25\x5b\x00\x6b\x5d\x37\x40\x14\x54\x2d\
+\xe9\xd3\x15\x82\x0f\xa5\xc7\x17\xd5\x80\x7c\x90\x30\x79\xe0\x9f\
+\x2c\x00\x7f\x4c\x07\x37\x3f\xa7\xaa\xc6\x1c\x76\x37\x6e\x51\xd7\
+\x94\x16\xcd\x1d\xcc\x02\xd0\x82\x7a\xbb\xa8\xc1\x0b\xb4\x98\xd8\
+\xf3\xe6\x84\x65\x9f\xd2\x5f\xb4\x64\x84\xdd\x01\x52\x7f\x8f\x2f\
+\x3e\xd6\xd4\xac\x1e\xac\x48\x6f\xbb\x04\xc9\x15\x22\x79\xcd\x32\
+\x1e\x9f\xa7\x4f\x51\x20\x54\x48\x97\x48\x83\x56\x74\xcc\xa2\x50\
+\x33\xb1\x05\xaf\x3a\xf3\xd2\x54\x1e\x39\x15\x91\xa8\xb7\x52\xd5\
+\xb7\x81\x2d\x9a\x85\x25\x90\x44\x42\xbb\x22\x44\x2d\x80\x47\x44\
+\x48\x64\x43\x54\x44\x48\x51\x19\x38\x37\x80\x2c\xaa\xda\xc5\x30\
+\x00\x2e\x44\xda\x62\xe2\x41\xe9\xe1\xa9\x82\x98\x2e\x91\xa8\x18\
+\x94\x9e\x63\xe1\x4e\x4f\xd0\x69\x68\x5d\x0b\x5a\xa7\x7f\xab\x98\
+\x49\xec\x33\xa1\x64\x81\xef\xd8\x36\x0c\x23\xfc\x49\xa1\xc1\x48\
+\x8f\x84\x1e\x13\x31\xd2\x32\x40\x44\x74\x85\xa0\x2b\x84\x5e\xfd\
+\xf7\x8b\x5a\x0a\x64\x6b\xf6\x4a\xb1\x5a\xdf\xb1\x79\xa7\x98\xe7\
+\x5b\xfa\x1b\xf3\x99\xf3\xa5\x01\x98\x80\x78\xe8\x40\x74\xcc\xc4\
+\x4d\xb0\xa5\x94\x27\x2e\x85\xd5\xc7\x0f\xfa\x4b\xe7\x4a\xe4\xe5\
+\xd4\x49\x8a\x7d\xfe\xf6\x64\xa1\xfa\x63\x8b\x3b\xcf\x5b\xb6\x34\
+\xbf\xd5\xc4\x4d\xe9\x52\x75\x46\x0e\x80\xe7\xdc\x06\x56\xa1\x03\
+\xf3\xb2\x2a\xa8\xd6\x93\x16\x13\xdb\xc5\x5d\x90\x6c\xdc\xe7\x86\
+\xcb\x78\xcc\xc4\x82\x2e\x7d\xce\xc5\x58\xb2\x38\x40\xb4\x7f\x48\
+\xd4\x91\xb0\x7f\xe8\x98\x7a\x00\xa0\x02\xba\xa2\x8b\x62\x6f\xd8\
+\x2e\xd0\xc7\xe6\xc6\x1e\x5b\x44\x15\x9e\x8c\xe9\x1e\x31\x6e\xd7\
+\x30\x69\x53\x42\x68\x17\x83\x1a\xc0\x66\x5b\x20\xe9\x13\x21\x1d\
+\xb0\x65\xad\x51\xab\x18\xe9\x65\x0e\xc0\xc7\xf6\x5c\xa4\x3c\x63\
+\xc9\x79\x2d\x69\xa1\x0c\x0b\x6b\xdd\x9e\x11\xa8\x84\xc8\x00\xde\
+\x31\xa4\x88\x0c\x30\x05\x01\x0a\xcf\x80\xf4\x90\x78\x3c\xac\x1a\
+\xd2\xa7\xf3\x04\xff\xb0\xa4\xec\x8c\x19\x1c\x24\x9b\x4e\x04\x87\
+\x25\xe5\xe8\x82\x27\x07\x49\xca\x8e\x72\x74\xc1\x2c\xa8\xce\xda\
+\x52\x30\x84\xac\x60\xaf\x94\x61\xbb\x21\x7e\x39\x39\x79\x6e\x18\
+\x46\x0c\x27\xda\x70\xc3\xab\xd9\x7e\xbf\xbd\xa5\xe4\x33\xba\xfd\
+\x05\x6c\x87\xf8\x86\x89\x89\xfb\x2d\x60\xed\x95\xa2\x10\x07\x22\
+\x06\xec\x51\x28\x3c\x07\xaa\xbd\x52\x74\x85\x60\x53\x44\x2c\xf3\
+\x3b\xc2\x4d\x4a\x10\x06\x5c\x4c\xc6\x6c\xbf\xff\x81\xd7\x6f\x97\
+\x84\xbf\x1e\x31\x11\x33\x67\xa5\x1d\x5b\x6a\xcd\x7f\x93\x9a\xa7\
+\xa4\x59\x0a\xa4\x5a\xe3\x4f\xee\x81\xc4\xd9\x6b\x7a\x61\xb7\x72\
+\xee\x84\x5b\xb0\xd2\x90\x45\xa3\xdc\x5d\x1d\x7b\x01\xde\x70\x01\
+\x8c\xf5\x77\x53\xb6\xdd\x89\xaa\x1a\x6b\x77\xe2\x59\xa4\x57\xe8\
+\x83\xd0\x67\xd2\x91\x6e\xdb\xbc\x0c\x42\x9f\x41\xe8\x23\x1a\x4e\
+\x46\x57\x74\xe9\x12\x39\x3b\xae\x7b\xc6\x69\x00\xa8\xa2\x0c\xdf\
+\x3c\xbe\x8f\x2a\xa7\xa1\xfd\xa8\x62\xdf\x94\x0f\x0d\x00\x97\xd2\
+\xd3\x00\x06\x22\xc3\xcc\xa9\xf4\x88\x3c\xfd\xfc\xc8\xab\xb0\x0a\
+\x39\x32\xff\x39\x96\x76\x87\x15\x0f\x41\xa6\xf7\x2f\x7c\xad\x89\
+\x0d\xa0\x2d\x13\xdb\x45\x5e\x24\x2a\x36\x7e\xe5\x3c\xe1\x09\x25\
+\xe3\x64\xc3\x70\xa2\xd9\xf5\x6a\x1a\xf2\xac\x17\x50\x4e\xa1\xec\
+\x8c\x29\xa7\x10\x07\x6b\x84\xf0\x99\x05\x15\x62\x9a\x30\x0b\x2a\
+\x26\x62\xc4\xe0\x20\xcd\xce\x30\xe2\xc1\xc0\x77\xcc\xea\x18\xb6\
+\xaf\xfd\xd0\xd2\x5f\xe0\xc7\x01\x62\x9a\x68\xe7\x27\xab\xef\xd7\
+\xd2\x63\x48\x21\x0e\x24\x71\x42\x11\x0b\xed\x3e\x3c\xaa\xdc\xf5\
+\x45\x19\x10\x64\x8a\xfd\x5d\x17\x5f\x49\x14\x9e\xf6\x87\xb3\xf5\
+\x09\x80\x03\xd5\x69\xb1\x70\xd3\x47\xde\x2b\xc5\xe0\x20\x19\x87\
+\x01\xf9\x20\x61\xbb\xd0\x7f\xc7\xe7\x5f\x3c\xe3\x65\x01\x7f\xfe\
+\xe7\x6f\xb9\xff\x6e\x89\x9a\xa7\xf8\xa4\xa8\x79\x4a\x31\x5f\x3a\
+\xf6\xf7\xe3\x00\x6f\x34\x85\xf9\x56\x1f\x31\x16\x01\xf3\x45\xc0\
+\xd8\x2b\x9d\x0c\xaa\xaa\xb1\x93\x0f\xe7\xd8\xb7\xc3\x05\xdb\xfd\
+\xde\x31\xb1\x05\xf0\xb2\x2a\x60\x51\x51\x6d\x47\x90\xad\x5b\x1e\
+\x33\x80\x3f\xf6\x49\xb7\x07\x2d\x00\xfd\x20\x01\x34\x80\xed\xed\
+\xc4\x93\x66\xd5\x18\x91\xab\x39\x21\x7d\x54\x83\x6d\xad\x96\x3d\
+\x5e\xc8\x95\x44\x54\x51\x46\xe9\x2c\xb3\x18\x90\x1a\xd4\xb2\x21\
+\x1f\xa4\xd2\xaf\x8d\xaa\x1f\x2d\x7f\x58\xa0\xa6\x46\x9c\xe8\x42\
+\xcb\xe9\x6b\x9a\xf7\x09\x7c\x14\x25\x8a\x58\xb3\x8e\x28\x50\xca\
+\xa3\x27\x22\x3c\x91\x39\x00\x6b\x9f\xb8\xf6\x85\x43\x2a\x2d\x13\
+\xa2\x10\xaf\x6a\xc8\x2c\x55\x32\x13\xa1\x96\xc7\xc1\x9a\x84\x29\
+\x25\x05\x1f\x45\x48\xe2\x57\x06\x80\x09\x92\x0d\x01\x7b\x20\xd1\
+\x2c\x87\x70\xee\x81\x64\x43\xc4\x00\x89\x07\x2c\x49\x08\x80\x35\
+\xc4\x43\x0d\xe4\xf9\x2d\xa8\x00\x21\x02\x4a\x0a\xe8\xaf\x09\x54\
+\x97\x94\x1d\x42\xf8\x04\xaa\x83\xa2\xa6\xb0\xd1\xf0\x82\x0e\x15\
+\x05\x70\xc8\x76\x04\x40\x11\x17\x28\x95\x50\x88\x0d\x81\xea\x18\
+\x1d\xdf\x39\xfb\xfd\x5a\x20\xdb\x62\x47\x31\x9a\xc0\xbd\x66\xc4\
+\xe5\xee\x9a\xe2\xb3\x2b\x7e\xf6\x1b\x3f\x43\xbe\x7a\xcd\xdb\xc5\
+\x9a\x3c\x2f\xf8\xea\xc1\x8c\x7c\xb1\xe4\xe5\xab\x1f\xe8\x7c\xbf\
+\xe6\x97\x7f\xf5\x21\x28\x78\x9b\xdd\xb1\xf9\x7e\xc3\xab\x97\xbf\
+\xa0\x3f\xb9\xe0\xf3\x17\xcf\xd9\x8e\xa7\x4c\xd0\x45\x8e\xaa\xaa\
+\xa5\x80\x95\x03\xf6\xfa\x87\xd2\xe3\xc0\x1d\x7d\x19\x43\x37\x87\
+\x51\x4e\x59\x6d\x59\xd2\xaf\x8f\xec\x71\x41\x27\x9e\xb5\x5e\x5b\
+\xa4\x03\x0e\xbb\xf7\x24\xfd\x8e\x06\xb1\x05\xac\x03\xa5\xbd\xad\
+\x02\x12\x21\x41\x44\x40\x61\xa4\x43\xe1\x00\x9c\x56\x8d\xe7\x36\
+\xfd\x60\x0b\xe0\x06\xa0\x01\x3a\x51\xc6\x41\x2a\x84\x01\xb2\x4f\
+\xd5\xf2\x85\x6d\xd5\xcf\x8f\xaa\x96\x71\x26\x91\x24\x51\xf4\x49\
+\x00\x9f\xfe\x40\x65\xcb\x5a\xb3\xd7\x2b\x2b\x29\x94\x44\x08\xed\
+\x4e\x48\x15\x13\x09\xcd\xc2\x21\x10\x1f\x2a\xaa\x78\xd5\x02\x71\
+\xbe\xde\xf0\x61\x0d\xa3\x61\x44\x21\xba\xa4\x99\xd6\x7e\x0f\xc2\
+\x0a\xca\x09\x29\x25\xb0\xb1\x4b\x57\x53\x45\xcb\x59\xd8\x4a\x20\
+\xf7\x28\x42\x02\x14\x59\x67\xc8\xe0\x70\x57\xaf\x17\x94\x22\x25\
+\x04\x42\xc8\x52\x56\x6b\x49\x18\x2a\x12\xa5\xdf\xc7\xee\x44\xed\
+\x23\x70\x0a\x24\x0e\x88\x6b\x34\xb9\x0c\xb3\x80\x22\xfe\x34\x70\
+\x8f\xdd\x82\x26\x98\x3f\xf3\x2b\x82\x30\x60\x39\x48\x58\xbe\x4b\
+\x11\xd3\x25\x0c\xe0\xf1\x6f\xfe\x1a\xf3\xfb\x35\xb3\xd5\x82\xbb\
+\xc5\x92\x8b\xc9\x98\xce\x62\xcd\xdd\x72\xc1\x9b\x77\x05\x30\xe1\
+\xf5\xea\x7b\xaa\x65\xc8\x7e\xf4\x80\x8b\xf1\x98\x8b\xc9\xf8\x93\
+\x8b\xb9\x26\x08\x83\x64\xc3\x67\x7e\x85\xe4\x82\x03\xcb\x9a\x89\
+\x8d\xa3\x58\x56\x5b\xaa\xf1\x8c\x73\xb5\x96\xc3\xee\x86\x34\x4b\
+\x35\x13\x77\x89\xd8\xab\xba\x4a\x67\x81\xbc\x57\xfb\x96\xce\x75\
+\xa5\xca\xc6\xe1\x3f\x91\xf2\x44\xf3\x5a\x3f\x57\xeb\x62\x08\xa4\
+\x47\x69\xc0\xad\x88\xe8\xe2\x81\x94\x4e\x3e\xf8\x8d\x85\x9c\x2b\
+\x63\x9b\xeb\xbe\xb9\x1e\x9d\x61\x5b\x0b\xee\xa8\xe1\x4e\xb4\xca\
+\xd1\xca\xab\x8b\x1c\xf8\xba\xb8\x41\xa6\xe5\x84\xa8\x1c\x1b\x6b\
+\x49\x11\xb9\xd2\x76\x10\x17\x44\xbd\x09\x4a\x95\x08\xa1\x8f\x4c\
+\x01\x11\xc5\xbb\x94\x70\xbc\x45\x70\xe1\x0e\xf7\x6c\xd7\xa4\xe6\
+\xcb\xd7\x40\xcb\x0d\xa0\xd1\xc0\xcc\x72\x88\x43\x03\x52\x48\xb3\
+\x14\x3f\xde\x91\x66\xf5\xe2\x47\xdb\x70\xfa\x79\xc4\x21\xa1\x71\
+\x32\x52\xeb\x6f\x1a\x47\xc3\x02\xda\x28\x65\xc0\xee\x20\x3d\x86\
+\x04\xac\x29\x28\xe2\xc2\x01\xbc\x59\x8e\xfe\x14\x13\x0b\x2a\xc7\
+\xc4\x51\xac\x28\x4a\xcd\xc6\x77\xcb\x05\x17\xff\x46\x4b\x8a\x7e\
+\xfa\x9a\x89\x0f\xc5\x63\xc1\x40\x1b\x7b\xfc\xf2\xaf\x3e\x44\x66\
+\xcf\xf8\x50\xea\xef\x77\xb6\x78\x00\x63\xf8\x7c\x32\x74\x00\x1e\
+\x4d\x6b\xdd\x1a\x24\x1b\x07\xda\xa6\x1c\xd0\xd2\x62\xce\x61\xb5\
+\xd4\x0c\xbc\x5a\x90\x45\x09\xfd\xf5\x18\x46\x39\xb3\xaa\xa0\xda\
+\x54\xe4\xfe\x96\x90\x87\xad\x85\x9d\x98\x42\xa7\x77\x59\x57\xec\
+\xba\xa2\x7b\x22\x0d\x9c\xe6\x6d\xdc\xa7\xce\xf9\xc0\x0d\x10\x36\
+\x75\x70\x20\x3d\x57\xc0\xd8\x9b\x6d\xb7\xc1\xba\xcd\xd7\x36\xfd\
+\x5f\xd9\xb8\x1e\xb5\x96\x6b\x5a\x4a\x70\x24\x33\xb0\x15\x2a\x03\
+\xdc\xf6\x4e\x57\x39\x37\xc5\x82\xba\x09\xe0\x8a\x18\xd1\x5c\xd1\
+\x2b\xc5\x26\x0b\x90\xbb\x05\x42\xf8\xba\x54\xdd\x94\x4a\xeb\x7a\
+\xa5\x9f\x66\x4b\x94\x52\xa8\xf9\x1e\xb9\x5b\x40\x96\xb3\xf5\x52\
+\x16\x59\xa9\xc1\x9b\x99\x05\x8a\xb9\xbe\x96\x5b\x88\x43\xfd\xb8\
+\x2d\xa1\x14\x0d\xbf\x35\xab\x17\x34\xe5\xa2\xed\xc3\xae\xe5\xf6\
+\x47\x59\xd5\x32\x71\x90\x05\x67\x01\x5c\x88\xc3\x89\x2b\x61\x4b\
+\xce\xda\xae\xab\xe8\x0a\xc1\x6c\x02\x83\x99\x96\x03\x87\xd5\x92\
+\x57\xdf\xff\xc0\xab\x05\x6c\x19\x93\xb2\x73\xef\xbb\xe9\xe8\xef\
+\x2c\x58\x2d\x90\xaf\x5e\xeb\x1d\x72\x90\x70\x31\x19\x73\x98\x8c\
+\x98\x4c\xd3\x56\x15\xaf\xcc\x0a\x67\xa7\x59\x67\x22\x48\x36\x94\
+\x4b\xfd\x5d\xac\xaa\x0a\x56\x21\xfe\x48\x2f\x6c\xcb\xa1\x26\x86\
+\x85\xaf\x8f\x86\x61\xd9\x3f\xa9\xd4\x55\x9d\xd1\x91\x26\x6e\x94\
+\x84\x9b\x8b\xb4\x63\x1f\x57\x57\xe2\x74\x2e\x42\x49\x45\x27\xaa\
+\x38\x48\x75\xe4\x4a\x68\xf6\xb5\x4c\x5b\x36\xae\xfb\x4d\x1b\xad\
+\x11\x2c\x6a\x32\x30\x47\xc0\x75\x60\x3d\x62\xe2\xda\x56\x13\x44\
+\x48\x04\xc2\x1d\x25\xd4\xa7\x02\x47\x8e\xa9\x33\x97\x9b\x50\x4a\
+\x22\x44\x44\x98\xf9\x60\x16\x76\x9b\x2c\x00\x16\xa4\x72\x07\xd9\
+\x54\x33\xe6\x7c\xc5\xbb\x65\xc9\x44\x7e\x64\xdb\xbf\x22\x3e\x54\
+\x06\x88\x3b\xf0\x04\x78\x8a\x78\xe5\x43\x08\x6b\x4f\xd5\xb9\x09\
+\x2f\x63\x58\x09\x5d\xd5\xcb\x72\x5b\x5f\xd2\x36\x5c\xaf\xcb\xda\
+\x53\x0c\xa3\x3e\x6b\xb9\x65\x68\xf3\x06\x93\x7b\x67\x51\x85\x59\
+\xc4\x30\xee\xff\x7f\xab\x98\x19\x26\x4e\x8e\xc4\xc7\x39\x79\x61\
+\xf3\x0c\x7a\xc1\xa7\xaf\x0f\x0e\x92\xd0\x17\x7c\x18\x4d\x18\xfe\
+\x6c\xc2\x37\x7f\xfe\x0d\x37\x7f\xfb\x1d\x00\x3f\x7d\xa8\xa9\xf5\
+\x62\x5c\x3b\x28\x77\xcb\x05\xe3\xa7\x4f\x18\xcc\x2e\xf8\xcc\xaf\
+\x0c\xfb\xae\xb4\x55\x58\x6a\x17\xc3\x3a\x1a\x96\x89\x2d\x98\x2d\
+\x90\xef\xbe\x5f\x3a\x57\xa2\x5c\x2d\xe8\xf3\x80\xb2\xb3\x87\x55\
+\x48\x39\x5c\xe2\x8d\x4a\xe0\x49\x4b\x8a\x34\xb5\x71\xd2\xef\x10\
+\x5a\xd0\xee\x39\x95\x06\x4e\x5a\x44\x15\x5d\xa9\x0b\x08\x5d\x0b\
+\x9d\x48\xa0\x9a\xbe\xae\x54\x1c\xa4\x87\x88\x2a\x0d\x77\x03\x52\
+\xcd\xce\xc2\x95\xa3\x6d\x65\x2e\x89\x04\xa9\xac\x8b\x1c\xf2\x18\
+\xbc\x55\x4c\xe4\x65\xad\x4c\x5b\x1b\xc0\xb5\x3f\x8c\x10\x67\x81\
+\xab\x8e\x00\x7c\x2c\x25\xdc\xfb\x29\x0f\xcf\x4f\xe9\x67\x09\x39\
+\x0a\x01\x7c\x54\x7a\xf7\x2e\x59\x72\xd8\xa4\xe0\x57\x78\xc5\x9c\
+\xc5\xed\x94\x22\x54\xed\x32\xbb\xf1\x52\x33\x51\x12\x28\x05\xf8\
+\xae\x10\x82\xd0\x80\x0d\xbc\x8c\x45\x15\x13\xec\x14\x0b\x63\xdb\
+\xad\x3d\x45\x51\xc5\x2c\xb2\x92\xc0\x33\xc0\x8e\x57\x90\xc1\x26\
+\x4c\x18\xe4\x69\xcd\xd2\x8d\x42\x89\x9f\x8d\x28\xe3\x15\x65\x67\
+\x0c\xc6\x0d\x19\x12\xb0\xce\xb4\x1f\x7d\x4e\x4a\x58\x4f\x58\xa7\
+\xd7\x54\xcb\x62\xf3\x95\x34\xe1\x28\x8f\xd1\x14\xba\xac\x51\xaa\
+\xe4\xef\xfc\xa3\x67\x8c\xdf\x3e\x61\xf9\xdd\x5b\xc6\x4f\x1f\x13\
+\x6e\x52\xc7\xba\x83\xd9\x05\x4f\x79\x6e\x4a\xd3\x95\x29\x35\x9b\
+\x85\xec\x76\xa8\x17\xa7\x8d\x94\x9b\x95\x14\x16\xbc\x45\x3a\xc0\
+\x1f\xfb\x5c\x4c\x0a\xde\x7c\xf8\x6b\x58\xc5\x64\x51\x42\x2c\x3f\
+\x92\x1d\x12\xe2\xe1\x12\xd6\x07\x2a\xff\xe2\x93\xba\xba\xea\x8c\
+\x1a\x9a\xb8\x01\xe4\x26\xa0\x1d\x78\xa5\x76\x85\x9b\x55\xb8\x52\
+\x7a\x0e\x94\x0a\x0c\x2b\x7b\x6e\xa1\x56\x1a\x4f\x58\x57\x1d\x6a\
+\xeb\xcc\x8f\x04\xbe\x94\x86\xcf\x9b\xa0\x6e\xfb\xb5\x78\x59\xcb\
+\xa9\x88\x1a\xce\x44\xdb\x1f\xe6\x4c\x04\xf4\x0c\x98\xcf\x00\xb8\
+\xa5\x8b\x55\x00\x5d\x1d\xb9\x54\x71\xd9\x08\xfa\xf8\x78\xc1\x80\
+\x70\xb1\x26\x1f\x02\x83\xda\x73\x0e\x33\x1f\x11\x0b\x17\x02\x2a\
+\xaa\x98\x40\x64\xa0\x34\x68\x8b\x5e\xac\x41\xdd\x03\x94\xcf\x20\
+\x48\xc9\x08\x08\xcc\xbf\xcd\x66\x2e\x26\xb1\xcf\x5a\xd6\xd2\x61\
+\x90\x14\x4c\xd2\x84\xfc\x53\xc5\x05\x53\x65\x1d\x1c\xa4\xa9\x88\
+\xa5\x4e\x52\x68\x4d\x5c\xeb\x68\x0b\x66\x6b\xb1\xd9\x20\x97\x95\
+\x19\x7b\x05\x5d\x11\xe9\x8a\x9e\x0a\xf0\x95\x24\xeb\x0c\x89\xc5\
+\x9a\x9f\x54\x4f\xf9\xc9\x17\x70\xff\xc5\x0b\xd6\xd5\x8a\x7c\xae\
+\x01\x35\x9b\x98\x52\xb5\x75\x4a\xa6\x38\x8a\x2a\x49\xa8\xaa\x31\
+\x9e\xb7\x3c\xf1\x96\xeb\x62\x48\xe0\x40\xf9\xa1\xf4\x28\xb2\x88\
+\x15\x15\x03\x99\x6a\x4d\x2c\x63\x4a\x99\xc2\xb0\x53\x07\xac\xce\
+\x64\x28\xbc\xc3\x4a\x97\x9d\x8f\x59\xb7\xbd\x72\x52\xee\x7e\x6d\
+\x87\x09\x2d\x3b\x4c\x50\xc7\x79\xbb\x86\x85\x5d\xde\xc1\xea\x61\
+\xf3\x7a\x11\x09\x84\x54\xee\xb1\xa8\xa1\xa3\x65\x83\x89\x9d\x94\
+\x30\x3f\xae\xb4\x8c\x6c\x41\xeb\x65\x48\xf3\x9f\xf3\x87\x95\xd2\
+\xc5\x8d\x63\x8b\xae\x51\xe4\xb0\x9f\x96\x37\xdc\x0a\x17\xc3\x24\
+\x76\xd7\x9b\xf9\x61\xfb\x3a\x1b\xf4\xc9\x5f\x0c\xa9\x82\xa9\xcb\
+\x16\xeb\xc7\x1a\x5f\xae\xf2\x5d\x39\xda\x7e\xe9\xc1\x4e\x11\x07\
+\x85\x03\xad\x8d\x61\x1e\x03\x78\x91\x95\x0c\x23\x2d\x19\x86\x95\
+\xc0\xab\x46\x2c\xf0\x5d\xe6\xb8\xa9\x9b\xfd\x6c\x84\x9f\x8d\x5c\
+\x49\x37\x8a\xef\x19\xd2\xd4\xd0\xc9\x09\x80\xcf\xbb\x13\x29\x89\
+\x0a\x11\x54\x8d\x50\x50\x0a\xa2\xe4\xc1\x21\x23\x62\x40\xb0\xbb\
+\x26\xf0\xde\x71\xe1\xad\xf8\x6a\x2f\xf9\xc9\x45\xc5\x2f\xf5\x33\
+\xfd\x78\xac\x18\x4d\x61\x38\x19\x9f\x94\xb6\x03\xef\xdd\x27\x3f\
+\xb7\x29\x2d\x9a\x21\xa3\xd1\x58\xef\x84\xb1\x4c\x29\xf9\x88\x3f\
+\x9a\x90\x1d\xba\xee\xbb\x3d\x97\x66\xab\x3a\x23\x5d\x76\xb6\xcc\
+\xeb\xd8\xf7\x48\x13\x1f\x87\x75\x2c\x38\x8b\x66\xe5\xcd\x80\xb2\
+\x4b\xa4\xb5\xaf\x88\xe8\x97\x71\xeb\xb1\xd2\x80\xce\x37\x1a\x98\
+\x23\x56\x6f\xb1\xaa\x97\x41\x15\x1b\x49\x51\xb5\x64\xc3\x89\x3f\
+\x7c\x9c\x9b\x68\x2c\x00\x2d\x5b\xdb\x05\x5d\xa0\x12\xc7\xc2\xde\
+\x51\x32\x0f\x60\xbb\x57\x28\x25\x1d\x50\x15\x31\x79\xa6\x1c\x90\
+\xbd\xf1\x90\x62\x90\x10\xc6\x25\x79\xe6\xbb\x14\x1b\xa2\xd4\x91\
+\x55\xfb\x85\xdb\x2f\x5d\x94\x64\x9d\xd3\x1d\xac\xa8\x62\x97\x27\
+\x5e\xcb\xad\x2e\x55\x67\xa5\x06\x34\x1a\xd4\xf6\x71\x1b\x22\x22\
+\xcb\xf1\x99\x69\x19\x61\x98\x38\x8a\x95\x73\x3a\x80\x86\x94\xc8\
+\x29\x3b\xe3\x23\x47\xa3\x1d\x06\x82\xd8\x2d\xec\xba\x42\x80\xf2\
+\xb5\x0f\x6d\xfe\x76\x5f\x69\x8f\xd7\x25\xe5\x6c\x9a\xb0\xb1\x18\
+\xf4\x95\x74\x59\x89\xbd\x52\x2d\x96\xf7\x49\x5d\xd1\xc5\xb2\xb1\
+\xbd\x7e\xbc\xc8\x6b\x16\x39\x36\xd5\x85\xbb\x1d\x77\xf6\x3f\x1a\
+\xc5\xb4\xdb\xb3\x9a\xd8\x8f\x2a\x94\x2d\x46\x9c\xa0\x46\xb3\xaf\
+\x27\xe3\xda\x03\x96\xed\x1d\x20\xf1\x32\xd6\xbe\xe7\xec\xb3\xd2\
+\xd9\x65\xed\xbc\xb0\x05\x78\xd3\xb1\x70\x4c\x6c\xca\xca\x2d\xb8\
+\x2a\x79\x26\xf0\x13\x9d\x08\x0a\x0d\x7c\x88\x84\xae\xcd\x09\x17\
+\x00\xca\xe8\xb5\x0a\x1d\x75\x97\x47\xbf\x2b\xd8\xfa\x29\x42\x44\
+\x48\xe5\x11\xc5\x25\x52\x49\xa2\xb8\x22\x37\x07\x68\x9d\x68\xcb\
+\x34\x58\xe3\x92\xdc\xb2\xbc\xf9\xe1\x85\xcd\x15\xdb\xc3\x9f\xbd\
+\xae\x7c\x17\xa0\x1f\xe4\xa9\x76\x25\x4c\xaa\x6d\x51\xc5\x2c\x4c\
+\x95\x70\x2d\x33\x26\x71\xdf\x69\xe0\x45\x56\x32\xc8\x53\x07\xe4\
+\x32\x5e\x39\x3d\xec\x67\x23\xd2\x78\x75\xe4\x1e\xef\xdc\xfd\xfe\
+\x61\x79\x96\x89\xf7\x4a\x91\xb2\x43\x66\x23\xee\xb3\x05\x33\x26\
+\xdc\xb3\x70\x5d\x1c\x92\x99\x0b\xef\x90\x65\xb5\xf7\x9d\xd5\x8c\
+\x5f\x4b\x17\xa3\xf7\x17\xef\xc8\x33\x9f\x65\x3e\x24\xdc\xdc\xd2\
+\x9f\x0c\xf9\xfa\x71\x8f\xa6\xc1\x7b\x5c\xaa\x76\x60\x36\x05\xca\
+\x55\x55\x31\xf0\xa0\x42\x67\xd9\xb7\x51\x46\xbc\x3e\xc0\xf8\x54\
+\x46\x1c\x83\x3a\x3c\xab\x21\x8d\x0c\x38\x66\x65\x5d\xc8\x88\x8c\
+\xcb\x60\x5d\x88\xca\xad\xc6\x6c\xf8\x27\x95\x6d\x5b\x4e\x44\x15\
+\xd8\x16\xa6\x33\x15\xba\xa8\xe1\x0b\x63\x98\x58\x36\x16\x70\xd1\
+\x89\x5f\xd1\xbe\x1e\xa4\x3e\x45\x22\x8d\xe7\x19\x6b\x29\x61\x74\
+\x70\x33\xb5\xe6\x18\x58\x05\xae\x72\x67\x3b\x3b\xb6\x4a\x01\x01\
+\x0a\x49\x64\x81\xec\x5e\x97\x91\xc7\x75\x2b\x92\x75\x34\x5c\x5b\
+\x92\x05\xaa\xf2\x81\x0c\xa1\xe2\x13\x1d\x67\x3b\x41\x28\xe2\xfa\
+\xc7\xdf\x29\xe7\x50\x60\x1d\x0c\xeb\x5c\x64\x39\x13\x80\x30\x3a\
+\xab\x87\xed\xd6\x7a\xc4\xc7\x8f\xdb\xd6\x25\xc7\xe0\x68\xc7\x63\
+\xbd\xe9\xb3\xdd\x5f\xa3\x78\x8b\x48\x07\xcc\x79\xa9\x19\x90\x0d\
+\x07\xee\xe8\x18\x49\x60\xf3\x0c\x1d\x2e\x38\xf0\x9a\x4e\x12\x41\
+\x9a\x40\x92\x9a\x0c\xf6\x15\xd3\x49\xa1\x8f\x18\x93\x0b\xfc\xde\
+\x88\xa7\xb1\x42\x66\x33\x3e\xbe\xfc\x86\x8f\x3c\xe7\xc1\x63\x23\
+\xad\xe2\xe1\x27\x43\xf5\x77\x8b\x25\xdb\xc5\x1d\xfd\xc9\x45\xeb\
+\xfe\xb8\xa9\x89\x8f\xd8\xfc\xb8\xb3\x23\xb4\xc0\xeb\x1c\x81\xd1\
+\x05\x76\x8c\xfd\xe6\xb6\x51\x45\x81\xc4\x23\xa6\x38\xb2\xd8\xdc\
+\x73\x84\x4e\x9a\xa9\xa3\x50\x8f\x05\x6a\xd4\xd0\xbb\x78\x19\x52\
+\x2a\x92\x48\x1c\x89\x04\xd9\x28\x33\x67\xed\x62\x88\x54\xf4\xcb\
+\x98\xad\x9f\xd1\x2f\x63\xca\x6a\x4b\x90\xf6\x51\x49\x0d\x9c\xc8\
+\x84\x7f\x44\xc3\x9d\xe8\x99\x9e\xb8\x4a\xf4\x4e\xe4\xc4\x09\x13\
+\x8b\x0a\xa9\x3c\x2a\x11\xe0\xa9\x82\x48\x64\xda\x86\x03\xfa\x24\
+\x90\x59\xfd\x9c\x81\x8a\x5d\x44\x53\x19\x50\x2b\xe5\x6b\x66\x36\
+\x92\x43\x58\xd6\xb6\x8f\x99\x85\xdf\xda\xfc\xdb\x16\xf8\x47\x6c\
+\x6c\xe4\xc6\x6e\xcf\xb0\xd7\xa5\x4a\xd2\x56\x15\xd1\xcf\x46\x44\
+\xf1\x3d\xeb\x46\x26\xb9\x20\x27\x25\xac\x01\x6c\x5e\x9f\x67\x2f\
+\x5d\x90\x3f\x8c\x25\xcf\x26\x0f\x5d\xae\x61\xd3\x79\xee\x02\x4c\
+\xb3\xe0\x19\x00\xf7\x85\xc7\xe0\xf0\xb0\xf1\xed\x3c\x44\x66\xc2\
+\x85\xe7\xa7\xfe\xe8\x24\x47\x6c\xfe\x71\x74\x7a\x63\xf2\xc5\x73\
+\xfc\xf9\x1b\x0e\xde\x63\x3a\x8f\x22\x5d\x5e\x27\x71\x0b\xbc\x63\
+\x40\xf7\x27\x17\x8e\x81\x87\x5e\xc9\xba\xf2\x09\xe3\x88\x78\x9d\
+\xe2\x0d\xe6\x28\x9e\x20\x3e\x91\x61\x66\xed\x69\x39\x21\x22\xa1\
+\xcb\xc1\x06\xcc\xbe\xd4\xdb\xbd\xd4\x8f\xf9\x52\xb6\xec\xb2\xc0\
+\x64\x1e\x8a\x06\xe0\xad\xee\xf5\x91\x94\x0a\xfc\x48\xcb\x05\xd1\
+\x14\x00\x86\x69\x2d\x18\x71\xcd\xa6\xfa\x59\x41\xea\xb3\xf6\x2b\
+\x92\x48\xd6\xcc\xac\xe6\x48\xd0\x1a\xdb\xd7\x00\x06\xd8\x26\x3a\
+\xb5\x5c\x50\x12\xa4\x7d\xca\x6a\xeb\x52\x6e\x51\x23\xbd\xa6\x0c\
+\x9b\xf6\x88\xd9\x71\x5e\x4e\xd8\x7e\xba\xfe\xa1\x64\x4b\x0d\x60\
+\xbd\x2d\x88\x44\x85\x52\x92\x64\x69\xbe\xfc\x81\x87\x17\x0c\x1a\
+\x7d\x76\x70\xd8\x29\x02\x51\x82\x52\x28\x15\x23\x0c\x58\x01\xa6\
+\x99\x47\x16\x57\x4e\xd3\x17\x76\xe1\xd7\x70\x60\x02\x2f\x63\x6d\
+\x16\x76\x64\xb9\x03\x35\xa2\x24\x3f\x48\xc2\x34\x69\x34\x9a\xe4\
+\x8e\x71\xf5\xdf\xbf\x65\xed\xf7\xcf\xba\x12\xf3\x6c\xce\xe2\xd5\
+\x86\xc9\xe7\xcf\xe8\x67\xe0\x4f\x6c\x61\x44\x7f\x8f\x63\x63\x44\
+\x0e\xe2\x94\x85\x79\xcb\x32\x97\x6c\x36\x7a\xa1\xb9\x04\x86\xcc\
+\x59\xe3\xb1\xfd\x3e\xa0\x3f\xd1\xa5\x66\xfd\x7b\xcf\x09\xe7\x26\
+\xa7\x3c\x1d\xd1\xf5\xfa\xc0\x9c\xed\xcb\x37\x7a\x31\x3c\x5d\xd2\
+\x7f\xb7\x25\xf9\x72\xd6\x62\x53\xbb\xd5\x72\xe0\xde\x01\x18\x60\
+\x5d\xf9\x0c\xbd\x12\x64\xda\x4e\x3a\x9e\x61\xe2\x32\x2b\x60\x58\
+\x11\x0a\xa0\x40\x22\xf0\x50\xc6\x45\x50\x40\xc7\xbe\x58\x7a\x54\
+\x51\x45\x60\x4b\xc5\xad\x36\xa4\x88\x22\xca\x60\x11\x22\xd8\x3a\
+\xf1\xaf\x5b\x8a\x32\x84\x01\x5c\x5c\x94\x64\x52\xe9\x6d\xe0\xeb\
+\xcc\x6f\xa3\xd8\x11\xa4\x3e\x65\xb5\x65\x1b\xf8\x0c\xcb\x98\xad\
+\x94\xe8\x67\xe9\x2c\x85\x8e\x66\xda\xfc\x80\xd0\xaf\x6f\xf8\x19\
+\x9d\x24\xe3\x90\xf6\x29\x1a\xcd\x97\x3d\x62\x76\x22\x73\xad\x52\
+\x4d\x00\x1f\x5f\x36\xbe\xce\x0e\x6f\x8b\x0e\xd1\xe0\xdf\x91\xcd\
+\x30\x00\xae\x8a\x8d\x0d\x91\x1e\xc9\x89\x1a\xc0\x7a\xab\x8b\x09\
+\xb6\x22\x88\x10\x47\xa5\x08\x0d\x5c\x5b\x20\xb1\xa5\xe6\x49\x96\
+\xb3\xf6\x14\xf1\xa1\x22\x0c\xa3\x9a\x89\x1b\x9e\xb1\x2e\x67\xe7\
+\x2c\xca\x80\xa9\x1f\x38\x56\xd6\xe5\x6f\x28\xdf\x55\x75\x45\x6c\
+\xf1\x3d\x0b\x60\xf5\x32\x60\xe0\xdd\x39\xb0\xcc\x06\x3e\x55\x30\
+\x65\x34\x1e\xb0\x5a\x6e\x1a\x7f\xd5\x7d\xbd\xe6\x32\xdb\x47\x93\
+\x81\x03\x6f\xdf\xe4\x3d\x6e\x57\x25\xbb\x72\x41\x6f\x55\x72\x98\
+\x68\x81\x3b\x1b\xe9\x9d\x77\x38\x99\xb2\x5f\xac\x51\x4a\xd1\x15\
+\xc9\x89\xe5\xe6\x9b\x1d\xd1\x63\x4a\xc5\x9c\x75\xe5\xb7\x81\xdc\
+\xac\x14\xf7\xd7\x94\xdb\xe1\x49\xe8\xdf\x55\xec\x02\x22\x8a\x48\
+\xd2\x95\x1e\x45\x54\x21\xa4\x87\x32\x7a\xb7\x59\x81\x73\x8b\x32\
+\x23\x0f\xb4\x5c\x88\x40\x28\x50\x03\x67\xbb\x95\x52\xea\xae\x65\
+\x22\x7c\x35\x27\x03\xf2\x55\x48\x16\xe7\x70\x00\x9f\xd0\x24\xdb\
+\x42\xed\xc2\x89\x9c\xb8\x71\x84\x89\x8c\xf4\x00\xed\x37\x27\x54\
+\xa7\xb5\x3c\x67\xa1\xe9\x18\xa2\xdc\xef\x89\x92\xb0\x4e\xb1\x19\
+\xf3\x5e\x9d\x69\xf6\xac\xce\xb0\xb1\x2d\x4f\xb7\xb5\x70\xa3\x5d\
+\x49\x05\x78\xe3\x1a\x7e\xc5\x20\xa1\xb0\x5a\x57\x65\x74\x7a\x53\
+\x0e\xbb\x66\x79\x25\xa3\xa8\xa6\xa8\xe5\x9a\x55\xb6\x67\xc4\x80\
+\x2c\xae\xc8\xe7\x7b\xe7\x6e\x0c\x07\x1d\xe6\xc5\x0e\x44\x0d\xe4\
+\xb5\xa7\x40\xc2\x10\xe1\xaa\x82\x6b\x4f\x31\x34\x4c\x6c\xf5\x32\
+\x71\xe8\x4a\xd5\xfd\x4d\xc9\x7a\x52\x34\x98\x38\x24\x5f\x6f\x08\
+\x27\x11\x53\x86\xae\x73\xa2\x3f\x29\x98\x4c\xe0\x62\xf2\x33\xf6\
+\x8b\xef\xf1\x99\x32\xf6\x4a\xf6\x95\x6e\x52\x7d\x61\xed\xb2\xb1\
+\x0f\xcb\x52\x6f\x81\x4e\xdc\xe3\x90\x35\x9c\x8e\xc6\x63\x4f\xbc\
+\x3e\xf0\x14\xc6\x3e\x45\x2c\x08\xde\x67\xfc\xdb\xf9\x96\xc3\x6a\
+\xc9\xaf\x98\x58\x67\x90\x05\xf8\x22\xc5\x25\x7b\x4c\xea\x4f\x4b\
+\x1c\xc9\x76\x71\x47\x32\xf1\x9d\x94\x38\x06\xb2\x00\x28\x27\xae\
+\x80\xd2\x64\x65\x9d\x9d\x30\x01\x74\xeb\x36\x78\xb2\xb6\xc6\x02\
+\x63\x7d\x15\x06\xb8\x2e\xd0\xde\xd0\xb9\x42\x2a\x23\x87\xf2\x96\
+\x13\xa1\x6d\x9a\x43\xa3\xb1\x32\x22\xee\xf4\x28\xc5\x54\x5b\x27\
+\x22\x32\x5b\x3d\xeb\xa2\xea\xc7\x44\x91\xa0\x30\xba\x56\xb7\x31\
+\x45\x6e\xdb\xea\xa8\x33\x00\x96\xe6\xf0\x2c\xa5\x32\x76\x4c\x64\
+\x42\xef\x25\x42\x54\x2e\x3b\x21\x1a\x8b\xba\x73\x00\xf6\xc8\xd8\
+\xf8\x15\xc9\xa1\x3c\xe9\x70\x96\xd6\x6b\x1e\xd7\x11\xff\xad\x9f\
+\x36\x58\x22\x43\x08\xdb\xb2\x94\x35\x58\x58\x7f\x6a\x12\x1c\x60\
+\xe0\xb1\xc6\xd3\x95\x3f\x20\xce\xbc\xba\x64\xed\xa4\x9d\x62\x10\
+\x17\x14\x55\xec\x00\x9d\x15\x01\x59\xc7\xd3\xc9\xba\x24\xd5\x76\
+\x5c\xec\xd7\x00\x8e\xdb\xeb\xf2\x66\x79\x24\x0c\x23\x92\x38\x61\
+\x32\x9d\xd5\x8c\x3f\xe8\xf0\xf4\xf1\x15\xc3\xc9\x98\x07\x5f\x7e\
+\xc1\x83\xc7\x3d\x18\xfb\x74\x27\x43\xc6\x13\x03\x5e\x03\x4e\xb7\
+\x35\x51\xcf\x4e\xdc\x70\x3a\xcc\x63\x55\xb9\x6a\xbd\x26\xc8\x14\
+\xc5\xa3\x98\x27\x13\x0d\x56\xdb\xad\xdd\x89\xf5\x71\xb4\xcc\x0a\
+\x17\x4d\xfd\xb1\x4b\x93\x85\x8f\x17\x76\xc7\x76\x5d\xba\x3d\xe0\
+\x97\xd2\xe3\x60\x80\x77\x68\x54\xdb\x9a\x16\x98\x03\x76\xc3\xdb\
+\x15\x0d\xbd\xdb\x64\xd0\x33\xc7\x5f\x10\x11\xd1\x24\x24\x4b\x2e\
+\xf0\x45\x0d\xd8\xaa\x1f\xeb\x34\x5c\x54\x39\x97\x57\x82\x03\x27\
+\xc7\xc5\x68\x0b\xda\xa6\xa1\x26\x74\x01\x46\xcb\x14\x79\xc6\x6a\
+\xf1\x5a\x1d\xd8\xad\x05\x89\xa9\xd6\x09\x11\xe9\xb6\xfd\x8e\xef\
+\x40\x6b\xc1\x7c\x0c\xea\x3c\x2e\xdb\xa1\x21\xd0\x92\x41\x94\xad\
+\x56\x26\x5b\xec\xf0\x2f\x9e\x52\x0c\x1e\x90\xc7\x25\xfe\xc5\x53\
+\xdd\x35\x1d\x47\x84\xd3\xae\x91\x1e\xb5\x2b\xb1\x34\xbe\xe9\x02\
+\xdf\xb1\x70\x7c\xa8\xc8\x3a\x9e\xc9\x73\x68\x3d\xbc\xc8\xca\x16\
+\x13\x77\x46\x55\x43\x5e\x68\x67\xc2\x76\x44\xef\x95\xe2\xd5\xcb\
+\x5f\xe8\xac\xef\xa6\xc4\xdf\x7e\xa0\xb8\xff\x86\xe2\xfb\xb9\x66\
+\x57\x13\xc2\x71\xdb\x26\xdb\x36\xfe\xdf\x6f\x6f\xf5\x76\xb1\x86\
+\x65\x49\x55\xae\x38\xac\x6a\x0f\xbc\x13\xf7\xdc\xc8\x80\xe9\x17\
+\x9f\xb3\xaa\x2a\x3e\x2e\xee\xe9\x4e\x86\x94\x62\xd6\xc8\x9b\x27\
+\xf8\xe8\x80\x7d\xdd\x28\x7a\xe1\xd8\x37\x59\x04\x2d\x36\x06\xc8\
+\xfd\xad\x2b\xa4\x9c\x6b\x52\x0d\xab\x28\x03\xe9\xd5\xe1\x19\x03\
+\x13\x81\x70\x5e\x71\x2d\x13\xbc\x56\x74\xb2\x95\x87\x20\x42\x52\
+\xb5\x53\x6a\x22\xd7\x93\x85\x9a\xa5\xe4\x46\x93\xe7\x71\xb9\xd8\
+\x39\xbe\x4a\x9d\x3c\x2e\xed\x82\xcd\xde\x67\x26\x02\x49\xa0\x5f\
+\x64\x7a\x87\x20\xd2\xbe\xb0\x69\x41\xe2\x4c\x97\x73\x93\x85\x2d\
+\x2b\x4b\xe5\xe1\x99\xd8\xa9\x05\xad\x95\x15\x76\xf2\x8f\x03\xb0\
+\x59\xcc\xe9\x49\x40\xa5\xb3\xd8\x94\x52\x08\x3b\x94\x44\x98\x8a\
+\x5c\x4f\x03\x39\x30\x56\x5c\xd1\xf0\x92\x6d\x89\x7a\x58\xe9\x06\
+\xad\x45\x55\x7b\xc8\x71\x50\xe0\x6f\xfa\xc4\x83\xed\x89\x76\x76\
+\x0b\xbe\x46\x1a\xee\xb0\xf2\xf4\x5a\xcb\xb1\x73\x6a\x5c\x0a\x78\
+\x9b\x49\x7e\xc8\xde\xf1\x2c\x7e\x4c\xc6\x90\xb2\xd4\xef\xe9\x57\
+\x3e\xf1\x62\x8d\x9a\x24\x0c\x97\x25\xeb\x71\x45\xb9\xd0\x7a\xb7\
+\x4e\xc7\x4d\xdd\xa2\x6e\xbc\xd2\x8b\x39\x7f\x92\xa0\xa8\x28\x17\
+\x23\xfc\x49\x41\xb6\x80\xb7\x8b\x35\x89\xb7\xe0\xd9\xaf\x3c\x41\
+\xc4\x7d\x3e\x6e\x34\x03\xaf\x4d\x85\xf3\x84\x55\x0d\x13\xd7\x8d\
+\xa2\x5a\x4e\x00\xdc\x72\xc0\x67\xc1\xc5\xe2\x21\xc1\xf4\x00\xf8\
+\xe4\x65\xff\xbc\x17\x6c\x41\x3c\xdf\x54\x44\xb9\x42\xe6\x25\x22\
+\x54\xd8\xce\xa4\xb2\x55\x46\x8e\xf0\xe5\xf9\x84\x82\x6a\x65\x2a\
+\xda\xc5\x0d\x0d\xe0\xcd\x49\x41\xc2\x5e\xfb\x54\xde\x41\x0a\x41\
+\xa4\x54\xed\x0f\x3b\xc0\x4a\x22\x21\x74\xa9\xb9\x51\xbd\xcb\x02\
+\x9f\x7e\xea\x53\xcc\xaa\xd6\xdf\x64\xab\x68\x9f\x5a\xd0\x35\xdb\
+\x93\xd4\x32\x68\x69\x62\xeb\x50\x0c\x4e\xfe\xbd\xd9\xc9\x6d\xa1\
+\x62\xc7\xc8\x1a\xc8\x3e\x42\x64\xee\xd8\x65\xc3\x40\x81\x97\xb5\
+\x87\xac\x54\x31\x50\xb2\xde\xed\xb5\x5f\x5c\x04\xf4\xb3\x88\x6d\
+\x2c\xc9\x81\x69\xa3\xec\xdc\x04\xb0\x5d\x04\x0e\x2b\x41\xb9\x08\
+\xd8\x0e\xf4\x2a\xc3\xb2\x73\xea\xe4\x46\x8f\x19\x13\x7e\xfa\xf8\
+\x67\x6e\x41\x96\x15\x11\x79\xa6\x18\x32\xe7\x36\x8e\x18\x02\x6f\
+\xa3\x1d\x43\xba\xf8\x93\x02\x1f\x5d\xf2\x1e\x8d\xa6\x4c\x0f\x4b\
+\xfc\xec\x0b\xc6\x23\x8f\xca\xd7\x12\xc1\x5f\xac\x18\x4e\xc6\xdc\
+\x4f\x2a\xfc\xc5\x8a\xf1\x17\x63\xc2\xc5\x92\xbb\xc5\x90\x37\xef\
+\x16\x4c\x33\xd8\xee\x74\xa5\xed\xcb\xa1\x47\xc7\x24\xeb\x9a\x12\
+\xa2\x29\x29\xf2\xec\x3c\x0a\xd2\x49\xe1\xa6\x6d\x08\x30\xc9\xb8\
+\xba\x68\xd2\x64\xe4\x50\x9b\xfd\x15\x03\x7c\x36\xb9\xa0\x13\xe2\
+\x1a\x3a\x05\xc2\xb8\x13\x19\x05\x10\x50\x39\xc6\x16\x26\x5b\x21\
+\x8e\x18\xd9\xea\xd9\x54\x7a\xf4\x3b\x7b\xb2\xc3\x00\xc8\xd9\x02\
+\x81\x54\x10\x9d\xd6\xdb\x4e\x8a\x1f\x8e\x89\x4d\x5a\xcd\x54\xea\
+\x22\x03\xe6\xd6\x7d\x40\x50\xc6\x4e\x4b\xdb\xe6\xd0\xf6\xac\x89\
+\xcc\xfd\x8d\xc7\x9a\xb8\x32\x0b\x33\x08\x8c\x4c\xa8\x5a\x5a\xf8\
+\xf4\x62\xbc\xe6\x62\xe3\x16\x27\xea\xcc\x0e\xa2\x41\xed\x1b\xfb\
+\x6d\x4e\x60\x3e\xaf\xe8\x09\x0d\xe6\xaa\xd6\xc2\xe0\xeb\xad\xd0\
+\x1d\xde\x76\xc1\xb3\xde\xc1\xb0\x17\x01\xca\x01\xbd\xc9\xca\xa0\
+\x47\x02\x9c\xbb\x24\xb1\xa9\xe0\x21\x18\x3f\x7d\x42\xb8\x49\xe9\
+\x4e\x9e\xd1\x05\xa2\x89\x62\xd3\x89\x74\x03\xd0\xea\x8e\x71\xef\
+\x8a\xe5\xee\x9a\x71\xef\x8a\xbb\xc5\x92\xe9\xa4\x60\xfe\xca\x94\
+\xd2\x78\x69\xaa\x6a\x13\x57\xa3\xbb\x5b\x4c\x18\x32\xe7\x8e\x29\
+\x77\x8b\xa5\x71\x78\x34\x83\x87\xbb\x3d\x79\x16\x71\x31\x9e\x50\
+\x4e\x86\x28\x8a\x13\xd9\x69\x01\x6c\x01\xb9\x1b\x97\xb0\x80\x64\
+\xe2\x73\x28\x3e\xf0\x78\xf1\x84\x74\x52\xb0\xae\xec\x20\x2c\xce\
+\x96\xaf\x7d\x52\x5d\xec\x18\x0c\x62\xa7\xe5\x06\xa6\x75\x48\x49\
+\x2d\x27\xea\x92\x70\x44\x61\xb5\x70\x43\x5b\xda\x38\xa6\x38\x93\
+\x03\xf6\x91\x26\xc0\xb1\xa9\xa1\x6a\x16\x91\xcd\x7e\x0c\x3b\x8c\
+\x30\x6a\x15\x94\xdb\xcd\x49\x91\x59\xb0\x49\x03\xee\x08\xd9\xaa\
+\xf4\xcd\x92\x82\xc2\xf6\xcb\xd9\xd6\xfc\xc6\xce\x55\x11\x23\x0c\
+\xd0\x76\xc6\xd7\x3d\x76\x29\x3c\x91\xa1\x96\x7b\x2a\xd1\x6b\x31\
+\xf1\xd6\x46\x34\xe3\xa3\x24\x55\x30\xe0\xb0\xd9\x20\x06\x89\x03\
+\xb6\xb2\xfa\x18\x9c\x57\x8c\x5b\xe4\x95\x2d\x06\x0e\x3c\x3d\x39\
+\x28\x35\x16\x5d\x62\x99\xdc\x56\xf6\x8c\x55\xb7\x46\xdb\x6c\x04\
+\x85\x8b\x74\x5a\x56\x76\x51\xcd\x66\xb0\xde\xb2\x31\x90\xc4\x39\
+\x12\x1d\x74\x0f\xc2\x80\x57\x1f\xfe\x8a\x7e\x57\x10\xee\x04\x79\
+\x76\xad\xa5\x6f\x3e\xe4\x62\x78\xed\x7a\xeb\xc2\x18\xe6\x8b\x88\
+\x3c\x96\x84\x59\x44\x1e\x0b\x53\xc8\x91\x0d\xfa\x92\x6c\x7a\x13\
+\xf2\x9d\x74\x05\x9d\x61\x35\x61\x34\x9a\xea\x46\xd9\x09\xbc\x01\
+\x62\xd6\x08\x1e\xb4\xfe\xed\xad\x30\x90\x92\x2c\xf3\x82\xa9\x17\
+\xba\x8e\x98\x4e\xf0\x19\xe9\xa4\x40\x72\x4f\xd4\x82\xb0\x0d\x18\
+\x0d\x1b\x8b\xbc\xc4\x44\x31\xed\x62\xce\xe8\x5d\xd5\xe8\x81\xb3\
+\xb2\xa0\x38\xb3\x60\xb2\x61\x20\xa1\x6c\x0f\x5e\x0d\x3e\x69\x3d\
+\x61\x36\x8d\xc7\x3e\x7d\xb1\x15\x38\xcb\xa6\x16\xe6\x91\x6d\xbb\
+\x6f\x48\x15\x07\x6f\xc3\xca\x49\x54\x71\x48\x03\x48\x24\xa8\xa8\
+\x9e\x94\x69\x62\x97\x98\xc5\x9b\x05\x74\xaf\x31\xc9\xd2\x02\xd8\
+\xca\x09\x31\xee\x1a\x56\x8e\x1c\x13\x27\x87\x92\x66\x48\x2c\x63\
+\x4f\x6c\xf4\x71\xb0\xd1\x51\xcd\x30\x36\xa0\xb3\x9f\xd3\x00\xad\
+\x6a\xe6\x2b\x44\xc9\x61\x37\x77\xce\xc5\x61\x37\x87\xa8\x24\x69\
+\xac\x13\x6a\x56\xcf\x48\xbd\x92\x40\xfa\xf8\xa2\x44\x1c\x22\x07\
+\xe0\xb5\xa7\x75\xf6\x49\xca\xed\xf8\x90\x4c\x08\xdc\xb3\xb9\x87\
+\x8b\xe1\x9e\x71\x3c\x26\xcf\x14\x0b\x25\x19\x18\xef\xfa\x62\xb8\
+\x67\xdc\xbb\xa2\x8c\x57\xae\x6b\x63\x70\x90\x04\x19\x74\x26\x3d\
+\x14\xa6\x0b\x64\x3a\xf9\xd1\xdf\xd0\xc6\x2f\x2b\xff\xd2\x84\x82\
+\x16\x74\xbd\x91\x2b\xbf\x5b\x09\xe1\xb6\x26\x60\x34\x0e\x77\xbc\
+\x5d\x94\x8e\x8d\xfd\xc9\x82\x74\x31\x21\x99\xcc\x18\x2c\xbe\x85\
+\xe1\x57\xba\x3d\x69\x7b\xa1\x19\xdc\x3a\x1c\x59\xe2\x2c\xb6\xd0\
+\xfa\xbe\x55\x54\x51\xca\xb8\x66\xd7\x48\xb4\x17\x69\xcd\x85\x9f\
+\x54\xf8\x4d\xf7\x41\x6d\x80\x01\xd2\xa6\x39\xc0\xb0\xf0\xce\x59\
+\x74\x41\x43\x38\x14\x48\x02\x3b\x53\xc2\x14\x43\xb6\x41\xe6\xc8\
+\xd7\x8d\x89\x35\xc5\x01\x54\x04\xaa\xd6\xc3\x56\x7f\x46\xa6\xca\
+\xe7\xba\x76\x45\xd5\x72\x20\x9a\x96\x9a\x65\xdf\xe3\xaa\x9d\x6d\
+\x16\xf5\x44\x81\x5a\xee\x9d\x2e\xb2\x4c\x7c\x2a\x26\x72\x0a\x21\
+\x08\x94\xc2\x0b\x29\xf9\xbd\x95\x00\x00\x20\x00\x49\x44\x41\x54\
+\x06\x6c\xf7\x77\x24\x45\x8f\xce\x80\x46\x67\x89\x72\xec\xac\x7d\
+\xe4\x7a\xf8\xa0\x10\x82\xd4\xcb\x48\x2a\xed\x4c\xf8\x55\xc6\x6e\
+\xa7\x0b\x0b\xc1\x46\x5b\xa9\x5f\x4c\x47\x2c\x6d\x2b\x96\xf9\xda\
+\x8a\x95\x2e\x96\xac\x1b\x9e\xf2\x8f\x01\xb8\xd9\xf2\x14\x74\x57\
+\x14\xbd\x09\x4f\xe2\x88\xee\x95\x68\xb5\xf2\xd7\xbf\x6a\xcf\x65\
+\x94\x01\x96\xa3\x89\xbb\xbe\xc8\x22\x4a\x5b\xf2\x68\xb4\x51\x35\
+\x27\x13\x09\xf1\xce\xe8\x7d\xc9\x3a\x8b\x78\x44\x40\x35\xdc\x00\
+\xbd\x96\x23\xe1\xa4\x84\x19\x66\x68\xc7\x66\xf5\x96\x3e\xfe\x64\
+\x41\xb9\x98\xe0\x4f\x16\xc0\x8c\xcd\xe4\x2b\x2e\x4c\x7b\x52\xd9\
+\x2f\xf0\xb7\xfa\xf5\xf6\x3d\xf6\x4a\xe9\xb2\xb3\xed\xc0\x08\xa4\
+\x6c\x31\x5e\x13\xb4\xcd\x7f\x6a\x57\x7a\x0e\xc0\x71\x51\x92\x89\
+\x9c\xb8\xe8\x91\x1d\x36\x2d\x85\xab\x7d\xdb\x1e\x19\xd0\x27\x62\
+\x6b\x80\x6b\x8b\x2b\x4d\x19\xd2\xeb\x47\xf8\x69\x40\x91\xa4\x48\
+\xe9\x1d\x39\x15\x5e\xad\x9e\x8d\x0e\xce\x84\x47\xac\xac\x7f\xbc\
+\xa3\x93\x14\x3a\xb3\xa0\x70\x4c\x6c\x01\xaa\x27\x60\xd6\x32\xa8\
+\xf7\x09\x9f\xd8\x16\x3b\x6c\x76\xc2\x96\xa3\xb7\x45\x87\x04\xad\
+\x7f\xad\x53\xb1\x53\xb9\x63\xe3\x3e\x17\x1a\xc8\xef\x2b\x78\xd4\
+\x6f\x15\x3b\x9a\x3e\xb2\x65\x66\x9f\x0c\x5d\x14\xcc\xb8\x55\x8a\
+\xe2\xed\x82\x0f\xab\x5b\x76\x77\x7b\x3e\x2c\xdf\xf2\x48\xe4\xfc\
+\xd5\x93\x9f\xf0\xd3\xe7\xda\x76\xaa\x06\x53\x3a\x55\xc2\xd5\x64\
+\x4c\xe0\x95\x40\x41\xbe\x92\x70\x26\xe2\xd9\xb4\xdd\xec\xed\xf5\
+\x22\x73\x76\x1f\x71\xa9\x3b\xb0\x33\x93\xcb\xcb\xd2\xd3\xd7\x34\
+\x0f\xdd\x71\x42\x9a\xa5\x5a\x5f\x37\x82\x44\xee\x08\x9a\x09\xfa\
+\x2c\x59\x2e\x20\x98\xe0\xbc\xe4\x92\x7b\x32\x86\x8c\x58\x81\xf2\
+\x4d\xa1\x83\xf6\xe2\x4e\x49\xba\x22\x22\xdc\xdc\x36\xdc\xa9\x19\
+\xcb\xe2\x9a\x31\x57\xa4\x8b\x92\xab\xa9\xfe\x4b\x9a\x4c\xdc\xf2\
+\x8a\x15\xba\xec\x8c\x49\xa4\x45\xd1\x84\x54\xea\x6a\x91\x30\x76\
+\x1a\x26\x81\x56\x18\xe0\xb9\xd2\x85\x19\xc8\x9d\xf5\xe3\xfa\xe7\
+\x92\xbe\x2b\x2b\x47\x91\x60\x7b\x34\x1c\xb0\xa9\x77\xb7\x48\x44\
+\x14\xd5\x95\x3f\x24\x24\x11\x30\xa5\x44\x11\xa4\x1e\x45\x52\x3a\
+\x2d\x8c\x8a\x9c\x6b\x81\x52\xc4\xf4\x88\x84\x44\xa8\x8c\x83\x9e\
+\xd3\xd3\xea\xa1\xeb\x89\xc8\x01\xd3\x5e\xb7\xba\xb8\x82\x93\xf6\
+\x24\x77\x5b\x05\x48\xea\x8a\x5d\x4e\x45\x1f\xc1\x76\x0f\xc9\x26\
+\x85\x60\xe0\xd8\xb8\xe9\x1b\x57\xfe\x0c\xaf\xeb\xa1\x96\x8a\x24\
+\x38\xb8\xb2\xb4\x17\x0c\x34\xd0\xb7\xd7\x6c\xc3\x09\x87\x4d\xca\
+\xdb\xbb\x0f\x6c\xb2\x15\x3f\x7c\xfb\xbd\xfe\x61\xa3\x4b\xd4\xf5\
+\x3b\xae\xf7\x1a\xe4\x7f\x79\xb7\x81\x3f\xff\xd7\xfc\xcb\x8b\x01\
+\x5f\x3e\xec\x90\x2d\x0b\xe2\x71\xc0\xdf\xfb\xfa\x37\x99\x3d\x0b\
+\x18\x8b\x3e\xb3\xcf\x1e\x30\x59\xc3\x75\x67\x8f\x98\x07\x84\x93\
+\x91\x2e\x96\x78\x05\x1e\xc9\x09\x30\x3d\xb5\x23\x4e\xba\x75\x07\
+\x36\xb0\x5e\x64\xc4\x41\x41\xb6\x08\x18\xf6\xba\x8d\xce\x6b\xbd\
+\x28\x94\xd9\x0c\x50\x8e\x6d\x93\x38\x41\x70\x8f\x6a\x4d\xe0\x94\
+\x2c\xb2\x31\xdb\xf8\x9a\x07\xf1\xd8\xb1\xeb\x7a\xb7\xe7\x89\xd7\
+\x83\x46\x50\xc8\x02\xf8\xb8\xd8\x91\x0f\xea\xeb\xe9\xc2\xca\xc9\
+\x7b\x60\xc2\x87\x6a\xc1\x8c\x19\x61\xb7\x51\x59\xb5\xd5\xbe\x6c\
+\x4d\x57\x24\x86\x89\x5b\xae\x6d\xbb\x4d\xc8\xea\x61\xcb\xa0\x96\
+\x4f\x14\x15\x42\x49\x5d\xc9\x33\x00\xb7\x56\x17\x46\x0a\xb8\x09\
+\xf2\x26\xff\x10\x48\x0f\x19\xd1\x7a\x3f\x5b\x1c\xd1\x96\x9a\xfe\
+\x1b\x92\x08\x48\xeb\x50\x7b\xa4\x1a\xf6\x9c\x93\x17\x0a\x44\x84\
+\x42\xb5\x7a\x1a\x6c\x5e\xa2\x6d\xff\x65\x8d\x83\xe5\xa9\x57\xdc\
+\x6a\x4f\x32\x5e\xf1\x71\xe9\x19\xd0\x63\x5f\x8b\x3b\x44\x3c\x3d\
+\x11\x18\x91\xc8\x08\xd1\xab\xfd\x3c\xee\x12\x66\xba\x2c\x1d\x6c\
+\x36\x04\x1b\xf8\xb6\x90\xdc\xbe\x7b\xc5\xab\x77\x19\xea\xfa\x1d\
+\x37\xcb\x37\xf5\x0e\x14\x6b\x6a\x98\x45\x4f\xb9\x97\x6f\x78\xf6\
+\xf4\xa7\x74\x0b\x0d\xea\xef\x6e\x0f\xa4\x77\x1b\x7e\x7a\x7b\xe0\
+\x7f\xf8\x8b\xff\x91\x17\xcf\x03\xa2\xc7\xff\x21\xff\xf1\x3f\xe8\
+\xf1\x60\xf4\x1f\x10\xcb\x15\x74\x21\xcf\xbb\xf8\x1d\x89\x57\x3d\
+\x04\x8e\x3a\xad\x9b\x15\x3c\x7a\x48\x46\x94\xdc\x33\xec\x75\xf5\
+\x00\xed\xd0\xce\x10\x6e\x57\xd1\xce\x8d\x67\x55\xce\x8d\xa9\x07\
+\xaf\x44\xb1\x62\x9f\x17\x7a\x04\x80\x29\xf5\xf7\xb3\xa8\x36\x33\
+\x1a\x91\xd4\x93\xe9\x9a\x4a\x4f\x1e\x7a\x6b\x6f\x4f\x16\x70\x87\
+\x93\x14\x0f\x17\x0b\x18\xce\xc8\xf7\x99\x03\xb2\x93\x23\xb6\x83\
+\xc5\xdf\xb7\x3d\xe4\x61\xe9\xb1\x95\xd2\x68\x52\xa9\x01\x28\x3d\
+\x8a\xc8\x00\xcf\x68\xe1\x75\x2a\x11\x89\x06\xa6\x02\x02\x93\x58\
+\x3b\x8e\xa7\xdb\x02\x48\xab\xf3\xf6\x9c\xa9\xd6\xd0\x9e\xa9\xf4\
+\xf0\xcd\x02\x4f\x2f\xec\xa4\x0b\xfc\x38\x6b\xad\xe1\x11\x97\xd5\
+\x16\x21\xa6\x28\x2a\x76\x66\xae\x84\x05\x72\xd3\x99\x50\x67\x5c\
+\x89\xe3\xdc\xc4\xb1\xfd\x66\xc3\xf1\x22\xee\x12\x66\x3e\xdb\x3d\
+\xa8\xe5\xbe\x55\x82\x6e\xca\x06\xab\x50\x42\x33\x88\xe5\xa6\x08\
+\xd8\xbc\xbb\x65\x79\x77\xcd\xdf\xbc\xc9\x1d\x38\x89\x1f\xb3\xca\
+\xbf\xe6\x8b\x81\xa2\x5b\xbc\x63\x1f\x3c\x6e\x01\x79\x16\x3d\x65\
+\x16\xa1\x1f\x7b\xfa\x53\xb6\xa6\xdf\xf7\x46\xbe\x81\xd7\x6f\xf8\
+\xfd\x6b\x9f\xaf\x2e\xbf\xe3\xf1\xd3\xdf\xe2\xcb\x9f\x8c\x08\x46\
+\xa5\x8e\x86\xae\x37\x8e\x4d\x5d\x51\x84\x7a\x0e\x73\x9a\xa5\x10\
+\xef\x48\x48\x4c\x6b\x93\x32\x91\xcd\x5e\xeb\x76\x42\xaf\x9e\x7b\
+\xd1\x92\x18\x5a\x4e\x94\x8b\x40\xa7\xe1\x0c\x4b\x87\x8d\xcc\xf3\
+\x49\x37\x89\x25\x9e\x13\x97\xc1\xa7\x14\x11\xdb\xc5\xc7\xd3\xcf\
+\x31\xda\xf8\x76\x82\xd3\xc4\xc7\xaf\xb7\x3a\x3b\x29\xbb\xa6\x65\
+\xdf\xf8\xba\xbe\x99\xe0\x6e\x17\x5c\x76\x3b\xd8\x56\x64\x81\x02\
+\x15\xa2\xa8\x78\x38\x6b\x03\xd1\x2d\xd4\x8e\xfc\x5f\xdf\xee\x08\
+\x8d\x12\x36\x47\xbd\x19\xc7\xd5\xbb\x56\xde\xd8\x31\xaf\x74\xa7\
+\x3a\x88\xec\x8e\x61\xc6\xf5\x1f\xbc\x7e\x63\x9a\x4e\xfb\x3c\x1e\
+\x9f\xb2\xd4\xf2\xa3\x56\xa5\x66\xc3\xa8\x75\x2b\x8e\x2b\x76\xeb\
+\xd8\xc7\xf7\x0b\x50\x92\x30\xbb\x38\xb1\xdc\x74\x9c\x32\xa5\xa8\
+\x12\x96\x4a\xb2\x58\x2c\xb9\xfb\xdb\x1f\x78\x69\xe6\x32\xdc\xef\
+\xeb\xe7\xcf\xa2\xa7\x20\x7f\x01\x3c\xe5\xe3\xc3\xe7\x3c\x0d\xcc\
+\x21\xfe\x16\xc2\x27\x2f\xe0\x5e\xdf\xde\x07\x8f\x99\x8f\x5e\x33\
+\x5d\x3d\x77\xe0\xee\x16\xba\x7f\xed\xdb\x1b\x8f\xf7\xea\xcf\xa8\
+\xe6\x13\x2e\xfe\xee\xd7\x8c\x45\x9f\xac\x0f\x76\xc4\xc4\xc4\x00\
+\x2b\xcf\x22\xbc\xfd\x12\x46\x38\x6d\x2b\x19\x99\xd6\x26\xad\x89\
+\xed\x10\x40\xdb\xea\x94\x92\xb7\xe4\x45\x13\xc0\x76\xa4\xc0\xc9\
+\xbf\x3d\x53\x10\xf7\x74\xff\xdf\xe4\x9e\xa6\xa5\xd3\x94\x0f\xee\
+\xfa\x27\x4e\xa1\xd0\x09\x3e\x63\x77\xf7\x81\xf1\x85\x4f\xba\x98\
+\xe8\xcc\xd0\x51\x83\x41\xf3\xfd\x5a\x4c\xec\x37\x42\xf1\x27\x8b\
+\xdc\xc0\x2e\xe5\x36\x08\x11\x35\x3a\x99\x55\x6d\x7c\x35\x1a\x33\
+\xa3\x33\xe0\x94\xb4\xa5\x84\x3c\x03\xe6\xd6\xb4\x9f\x93\xce\x46\
+\xe3\x25\xab\xfa\xb1\x43\x1a\xd0\x49\x0a\x0a\x0b\x76\x3b\x40\x45\
+\x54\x27\x65\x71\x61\x58\x53\xcf\x24\x6e\x3b\x17\x1a\xac\x09\x1b\
+\xbf\x6a\x8d\xb6\x02\x58\xc7\x3e\x9e\xaa\x88\x45\x0e\x22\x22\x38\
+\x94\xdc\xed\xef\xb9\x60\x76\x02\xe4\x55\xe5\x91\x2f\x17\xbc\x7e\
+\xbb\xe0\xf5\x9f\xfd\x6b\xae\xf7\x25\xe9\xdd\x86\xe4\x62\xd0\x06\
+\x30\xf0\xe2\xab\x7f\x00\xc0\x4f\x2e\x66\xfc\x5f\x87\x11\x7f\xbf\
+\xb3\x82\xce\xbd\xae\x52\x3d\x86\x37\xea\x9a\xd1\x7d\xce\x74\xf5\
+\xfc\x84\xa5\x01\xc6\x83\x1b\xb2\x65\xc1\x1f\x2e\xef\x78\x51\x24\
+\x3c\xfb\xf2\x09\x97\xcf\xd7\x04\xa3\xaf\x48\xb3\x1d\xfd\x2a\x6a\
+\x05\xfe\xf3\x5c\x92\x66\x11\xc4\x21\x65\x76\xcf\xf5\x62\x4f\x1c\
+\x14\x84\x59\xc4\x7a\xb7\xa7\x9f\x45\xa6\x62\xa7\xc1\x3a\x1a\x5e\
+\x1c\xfd\x00\xf7\x46\x72\xd4\xd2\xc3\x4e\x0f\xb2\x2d\x4b\x13\x11\
+\x51\x66\xf7\x67\x17\x89\x9f\xac\xd8\x0d\xda\x32\xe6\x50\x7c\xa0\
+\x77\xd1\x65\x79\x77\x4d\xef\xa2\x0b\xcc\x4c\x05\xf4\x47\xca\xce\
+\x0e\x58\x52\x1d\x85\x79\x2a\xa4\xe9\x4c\xde\x22\xf5\x4c\x09\x67\
+\x87\xe1\xba\x3b\xdc\x20\x6d\x75\xe4\x2a\x9c\x01\x63\xd0\x90\x26\
+\x67\x2b\x75\xe7\xcb\x5e\x8d\xec\x84\x6a\x06\x3c\x5a\xfa\x8c\x46\
+\x07\xc7\xb9\x2a\xa2\x6a\x1c\xfe\x43\x51\x11\x9a\x53\x1f\xb8\x8a\
+\x9d\xef\x52\xbf\x8e\x89\x0b\x91\xd2\x27\x66\x2b\xb4\x0f\xac\x94\
+\xa4\x1f\x0c\x10\x9d\x94\x2d\x29\xa2\x39\x1d\x49\x49\x3e\x2e\x56\
+\xfc\xe2\xdf\x7c\xcf\xcb\xd7\x6f\x48\xef\x74\x2e\x20\xb9\x18\x38\
+\x20\xcf\xa2\xa7\x0c\x1f\xc2\xd7\xbf\xf6\x05\x9f\x5d\x3d\xa5\x5c\
+\xf7\x99\x87\x1e\xff\x19\x70\xb3\xdc\x33\x9e\xe9\x21\x21\xcb\xbf\
+\x79\xcb\x53\x71\x05\x8f\x61\xfd\xae\xd6\xcf\x57\x5d\x9f\x3d\x70\
+\x2f\xdf\x00\x4f\xe9\xa2\x59\xf9\xe5\xab\xd7\x04\xea\x15\xd9\xe1\
+\xef\xf1\xc5\x57\xdf\xe2\x75\x9e\x52\x25\x29\xc5\xca\x07\xfa\x6c\
+\xf7\x8a\xe7\xbe\xaf\xa7\xc5\x65\x39\xf9\x62\x45\x8e\x07\x03\xed\
+\x3b\x8d\x7b\x57\x44\x13\x75\x04\xd6\xf3\xce\x73\x21\xba\x04\x6a\
+\x6f\x8a\x32\x5e\xab\x42\xb8\x57\xaa\x76\x30\x1a\x71\xcd\xba\xf1\
+\x34\x69\x6d\x8b\xde\x15\xe1\xe6\x07\x0e\xc5\x07\xc3\xc0\xba\x5c\
+\x5d\x2e\x26\x74\x02\x78\xb8\xf8\x1e\x86\x33\x42\x7f\xeb\x7e\xcd\
+\xe3\x1d\x22\xe9\x77\x08\x0f\x44\x7a\xa2\x62\x54\xb9\xe8\x65\xad\
+\x65\x95\x03\x30\x91\x3e\xac\x67\x87\x2e\x7e\x60\x60\x7a\x34\x57\
+\xa2\x06\xb0\x6c\xed\x00\x7d\xfb\x63\x2b\xb3\xc3\x44\xc7\x13\x7e\
+\x9a\x4c\xac\x1f\xf1\xb6\x15\xbd\x7e\xa4\xb3\xc2\xa2\x6a\xa5\xd6\
+\x38\x3e\xa5\x55\xe3\xf4\x60\x34\x4f\x0b\x66\xde\x51\x1c\x55\x1a\
+\x43\xe5\x9d\x48\x8a\xe6\xc2\x4e\x29\xdd\x67\x97\x31\x44\xa9\x0d\
+\x7d\x11\xbb\xbe\xba\x9c\xd2\x81\x77\x6b\x5e\x9b\x2f\x7d\x16\x8b\
+\x0d\xdf\xfd\xe5\x1f\xf3\xd2\x2c\xc6\x2c\xfb\x5a\x30\x03\x46\x0a\
+\x3c\x06\x15\xf0\xf9\x64\x4c\x32\xd1\xc5\x85\x70\x55\x71\xff\xc5\
+\x0b\xf2\xfb\x35\x9b\xfb\x3b\xe6\xbf\x35\x63\xf9\xdd\x5b\x6e\xee\
+\xee\x19\x3e\x7e\x0a\x87\x37\xac\x6f\x71\xda\xf9\xaa\xeb\x73\xdd\
+\x90\x17\xfb\xe0\x31\xdf\xde\xbc\xe3\x2b\xfe\x94\xb9\xf7\x35\xd3\
+\x2f\xa1\x58\xfd\xc4\xc8\x81\x85\x9e\xb8\xee\x5f\x81\xc9\xe3\x86\
+\x93\x11\xd3\x46\x77\x74\x84\x72\x5d\xd2\x1a\xc0\xe9\x19\x20\x9b\
+\xd0\x8e\xb2\xc3\x0c\xdb\xcf\x49\x33\x5c\x72\x2e\xcf\x25\x8c\xdb\
+\x3a\xb6\x14\x91\x2b\x70\xd8\xad\x67\xe6\xd8\x5d\x97\x57\x3c\x0b\
+\x4a\x7a\x17\x5d\x76\x77\x7b\xc7\xc6\x37\x8b\x2f\xe8\x15\x77\x84\
+\xe5\xdf\x39\x49\xc1\x95\xa6\x33\x3b\xdd\x1e\x08\x3b\x48\x94\xf4\
+\x10\x78\xad\xc6\xce\x52\x7a\xe6\xd4\x5e\x9e\x69\xee\xd4\x95\x39\
+\xa1\xb4\x1f\xdc\xca\x50\x28\xe9\x5c\x09\xfd\xe3\x5a\x45\xa4\x41\
+\x1b\xa4\x3e\x71\xb5\x25\x13\xa7\x5a\xda\xce\x21\xb6\x47\x02\x89\
+\x47\x5c\x94\xb0\x3e\xe8\x25\x42\x3f\x6e\x2f\x10\x8e\x00\x2c\xa8\
+\x58\xd8\x40\x90\xd2\x3e\xb7\x70\x61\x9c\xc8\x01\x59\x1d\xb1\xf2\
+\x49\x2a\xaa\x31\x3c\x51\x88\xc8\x01\xd4\xc7\xd3\x41\xa0\x32\x21\
+\xa7\x64\x4b\x46\x9f\xd8\x9d\x16\x01\xe0\xe3\xe2\x3d\x2f\x7f\x71\
+\x7d\x16\xc0\xcb\x71\xc4\x78\xa9\xbf\x99\xeb\x7d\xc9\x0b\xe0\x90\
+\xbd\xe3\xcf\xfe\x48\x31\x1e\x8f\x78\xfe\xec\x21\xa3\x2f\x86\x8c\
+\x83\x29\xab\xc9\x03\x1e\x3d\x19\x72\x2b\x61\x91\x57\xa8\x59\x84\
+\xb8\x97\xdc\xdc\xc1\xd0\xb0\xf2\xf7\x1b\xc1\x28\xd4\x32\x46\x33\
+\x32\x5c\x75\x35\x23\xa7\x1f\x0a\xbe\x15\x07\xbe\xe2\x9e\xe9\x97\
+\x7f\xcb\x65\xfc\x33\xe6\x0b\x7d\x3a\xad\xfd\x62\x0d\x93\xc4\x65\
+\x90\xdb\xe7\xc0\x4b\x1b\xdf\x48\xda\x62\xde\x20\x0b\x28\xe2\xa2\
+\x35\x1a\xa0\x5c\x28\xfc\x09\x24\x71\x0d\xe4\xa4\xe1\x82\x4d\xfc\
+\xe2\x6c\x89\xb9\x05\xe4\x26\xa3\x1e\xde\x40\xe7\xb1\x63\x62\xc0\
+\x5c\xff\xc0\x20\xb8\x3a\xab\x89\xf5\x18\x81\xa4\x0e\x00\x75\xa2\
+\xca\x00\x19\x57\x72\xb6\x00\x2d\x4c\x76\x42\x33\x99\x86\x42\x3e\
+\x3f\xd0\x79\x6c\xaa\x70\x91\x30\x2c\xae\x4b\xcd\xbe\xd7\x67\xeb\
+\x7b\xa6\x25\xc9\x27\x8a\xa4\xb9\xad\xa5\x88\x46\x79\xe6\xb4\xb6\
+\x34\xef\x19\x45\xc2\x74\x2d\xeb\x56\x26\x26\x3d\x77\x68\xaf\x27\
+\xbf\xab\x23\xde\xd6\x72\xa2\xc9\xd2\x75\x7b\xbe\x0d\xc4\x47\x2e\
+\x5d\x86\x19\x46\x2d\x84\x40\x2d\x7d\x42\x3b\xab\xd8\x9c\x98\xd1\
+\x2e\xf2\xb6\xa4\x84\xca\xa3\x14\x03\x60\xa3\x47\xbf\xa2\x25\x46\
+\x5f\xc4\x6c\xc9\x88\x22\xc1\x66\xe1\xf1\xf1\xfa\x9a\x6f\xfe\xcf\
+\x6b\xfa\xd7\xdf\x90\xe6\x9d\x16\xfb\xf6\xe3\x35\x49\x38\x68\xc1\
+\xc2\x97\x37\xec\xee\x9e\xc0\xc5\x3d\x72\x79\x4f\x59\x6d\xc9\x8a\
+\xc7\xbc\xb8\x0a\x18\xc7\x43\xf0\x21\x61\xc0\x8b\x9f\x7c\xc9\x57\
+\x8b\x19\x1f\x9e\x7b\xf0\xe7\xdf\x38\x56\xfe\xe2\x9d\x96\x12\x16\
+\xc0\x76\xe7\xd0\x54\x1f\xc2\xab\xd7\x04\x4a\xff\xdb\xfb\xbf\x91\
+\x52\x15\x1b\x92\xac\x42\x7d\xf6\xd0\x2d\xec\xdc\x62\xce\x6c\xb5\
+\x17\xbc\x6b\xf9\xc8\x3e\x82\x92\x94\xf5\x4e\xc2\xae\x4e\x9b\x85\
+\xb1\x84\x18\x86\xb4\x4f\xcf\x65\x99\x78\xb9\xbb\x26\xcf\x46\x8c\
+\x9b\x55\x6a\x53\x72\xf7\x4d\xb1\x4a\x6f\x7d\xf6\x96\x5a\x3a\x4f\
+\x39\x14\xd7\x9f\xd4\xbc\xd6\x62\xb3\x16\x5d\xb3\x62\xe7\xe6\x13\
+\x07\x44\x04\x0d\xae\x2a\x90\x46\xdc\x7a\x04\xd2\xd3\x16\x9a\x05\
+\xb8\xd2\xad\x45\xba\x65\xa9\x69\x9b\x29\x67\x79\xc5\x05\x64\x87\
+\x1d\x1c\xc0\x2b\x7a\x70\x50\xd0\xe9\x21\x03\x45\x54\x98\x25\xd6\
+\x61\x07\x41\xd4\x0a\xd2\x17\xcd\x6e\x65\xdb\xd1\xa1\x38\x93\x38\
+\x6e\x6b\x60\x94\x57\x57\xf7\x8e\xc0\x5b\x7f\x91\xb2\x5e\x8c\x58\
+\x50\x5b\xcf\x58\xc4\xad\xa1\x2a\xa1\xb2\xb2\x6a\x4d\x6c\x40\xdb\
+\xa7\x5e\xec\xf5\x89\xd9\xca\x8c\xc5\x62\xc5\xcb\x5f\x5c\xf3\xc3\
+\x9b\x9f\xb3\xd8\x45\x4c\x7a\xa7\x95\xaf\x77\x79\xce\xe3\xc6\xc2\
+\xee\xbb\xdb\x03\xf0\x96\xcf\xcc\x90\xbc\x1f\xee\xde\xf2\xc3\x77\
+\x6f\xf9\xf0\xe5\x13\xaa\xbe\xc7\x2c\x18\x31\x0a\xfa\x84\x93\x11\
+\xb3\x27\x0f\x39\xa4\x7d\x5e\xfc\xe6\x13\xf8\x33\xb8\xb9\xbb\x67\
+\x35\x0b\xc9\xdf\xbe\x3c\xf9\x9c\xab\xae\xcf\xf5\xbe\xe4\xaa\xeb\
+\xf3\xed\x8d\x07\xfc\x82\xdd\xf8\x92\x8b\xb0\xa0\x1a\x4c\x1d\xd0\
+\x5c\x07\x88\xa9\xc6\xd5\xee\x44\x7d\x6e\xbd\x3c\x53\xe4\xf1\x9e\
+\x4e\x4f\x30\x31\x7e\x72\x39\xb1\x33\x2f\xbc\x06\x7b\x9f\xd7\xce\
+\x3a\x59\xd7\x37\x5d\x21\x01\x9d\x66\x17\x58\x63\x36\x47\xb7\xc1\
+\xc4\x9d\xf8\x31\x87\xe2\x43\xcb\xa5\x38\x14\x1f\xd8\x14\x77\xc0\
+\x17\xad\x79\x1e\x2d\xbf\xd9\x16\x3b\x22\x24\xdb\x48\x77\x70\x54\
+\x64\x6e\xe1\x25\x51\x26\xf7\x50\x03\xa6\x14\x1d\xc8\x34\x7f\xb6\
+\x22\x21\x91\xd0\x0c\xbb\x3e\xc0\xb0\x43\x2c\x4d\x3a\x3f\x2b\x08\
+\xed\xa9\x36\x94\x47\x66\x7c\xc4\xb8\xd3\xa3\x3a\xd3\x09\x22\xcf\
+\x74\x88\xd4\x8b\xba\xe8\x14\xcc\x06\xb8\x91\xad\xd8\x99\x57\x58\
+\xfc\x0a\x4e\xf3\x1f\xe2\x68\xa9\x7b\x5c\xbd\x2b\x44\x4a\xa0\xb4\
+\x36\x54\x4a\x12\xe2\xe9\x69\xa0\xa2\xd6\xc2\x1b\xe5\xb1\xbe\x97\
+\xbc\x7c\xfd\x86\xc5\x4e\x1f\x8a\x6f\x97\xb7\x94\xf2\x23\x7e\xf4\
+\xc0\x6d\xbf\x78\xf4\x81\x2a\x7c\xec\x18\x3a\xb9\x18\xf0\xdd\xed\
+\x81\x6c\xf9\x9a\x78\x5c\xdb\x50\xd7\x3f\xcf\xf9\xfc\x71\xcc\x9b\
+\xbb\x37\x8c\x2f\xae\x18\xce\x03\xbe\x79\xf5\x57\xae\xcb\x66\xd0\
+\xdf\x73\x73\x47\xcb\xa9\x68\x5e\x2c\x1b\x37\x81\x5c\x7c\xf3\x06\
+\xef\xc1\x67\xf4\x1e\xed\x18\x35\x2c\xb3\x34\x83\x3c\xbf\xd3\x43\
+\x5c\x76\x4b\x13\x62\x12\x80\xae\xde\xd1\xeb\xba\x41\x29\x7a\x4c\
+\x86\x76\x1c\x44\x7c\xcf\x21\x0b\x28\x9c\x8c\x48\x5d\x37\x89\x1e\
+\x68\x98\xd6\xbe\xb1\x59\xd8\x75\x6c\xf3\xa4\xcd\x93\xd8\x3c\xb5\
+\x6a\x30\xf1\x99\x8b\x05\xf4\x3e\x9b\xd6\x7e\xbc\x8a\x8f\xa4\xc8\
+\xbd\x2e\x3b\x07\x52\xb3\x58\xd0\x58\x5a\x35\xe3\x92\x4d\xc6\x45\
+\xe9\x54\xdb\x7e\xda\x21\x57\xba\xdf\xcd\x49\x04\x57\xb1\x2b\xf5\
+\xe4\x16\x33\xf8\x62\xb8\x3e\x40\xa7\x47\xd5\x8f\x89\xb7\x86\x81\
+\x2d\x78\xb6\x19\x55\xdf\x33\x59\x63\xcf\x2d\x0e\xcf\xf9\xc7\x38\
+\xcd\x6b\xd8\x3f\xf5\xdb\xc5\x12\xd1\x38\xf5\x97\x09\x17\xc5\x8b\
+\x1d\xea\x51\xd7\xc5\x4a\xad\x25\x77\x3e\xfc\xab\x35\x7f\x61\xea\
+\xfc\x96\x91\x9b\x0b\x40\x3b\xe2\x2a\xc7\x63\x7b\x7d\xcd\x87\xf7\
+\xd7\xbc\x7d\x27\x99\xf4\x72\x07\x64\x3f\x7a\xc0\xf5\xf5\x47\x36\
+\xea\x8a\xe7\xd1\x8e\x6f\xe5\x1b\x1e\x4d\x15\xf1\x44\x90\x5c\x3c\
+\x76\x52\xe3\x26\x5e\x53\xed\x1f\xd7\x8b\xb3\x0d\xfc\xf5\xf5\x2f\
+\xf4\x0e\xbe\x7c\x4b\x19\x5d\x72\xd5\x0b\x29\x67\x0f\x88\xbc\x15\
+\xb2\x1a\x11\x5e\x48\x9e\x7f\xff\x96\x25\x97\xe7\xbd\x83\xbb\x0d\
+\x3f\x0d\x0f\xbc\x1e\x4f\xb9\xea\xfa\x7c\x58\xbe\x25\x50\xaf\x78\
+\x11\x7f\x8d\xba\x1c\x73\x55\x14\xbc\x3b\xe4\x2c\x97\x7b\x67\xbd\
+\x0d\x07\x3d\xc2\x49\xd4\xee\xd7\xcb\x72\xa7\x83\x13\xe7\x03\x07\
+\x1c\x8e\x9c\x8a\x66\x55\x70\x8d\x9e\xc8\x39\x5f\xac\xc9\x83\xc2\
+\x2d\xec\x4e\x98\xd8\xc4\x4c\x5b\x4c\xfc\x23\x72\xa2\x1b\xcf\xeb\
+\x1c\xb7\x28\xcd\xe0\x43\x9b\xc7\x30\x51\x4c\x94\xc4\x13\x15\x92\
+\x18\xdb\xbe\x7f\x30\x4c\x17\x34\x2c\x14\x1b\xc7\x3c\x18\x98\xf5\
+\x85\x0e\xe4\xb4\xea\x5e\x07\x74\xf4\xb2\xd3\x00\xb6\xd5\xb6\x96\
+\x43\x27\x13\x5d\x44\x31\xe0\x97\xd2\xa3\x1f\x09\x88\x6c\x20\x3c\
+\x6a\x49\x85\x48\x19\x77\xa2\xb5\xb0\x93\x14\x89\x66\xd9\xa2\xd1\
+\x0e\xef\x6d\xeb\x10\xfc\xa4\x1f\x71\x28\x63\xca\xed\x96\x83\xa7\
+\xc1\xbb\xf5\x33\xfa\x69\x4c\xc7\x10\x71\x2e\x2a\xba\x4a\x39\xb6\
+\x6b\x9e\x1e\xcc\x56\xe2\xb4\xb4\xd0\x05\x92\x91\x57\x91\x4a\x9f\
+\x74\xb1\xe3\xcd\x56\xb2\xbe\xc5\x49\x88\x49\x2f\x87\xde\x43\x16\
+\xbb\x90\xab\x2b\xa8\xf6\x1b\xe6\xf7\x5b\xa6\xab\x29\xef\xf9\x88\
+\x2f\x1f\xf0\x70\x5c\x3b\x15\x6f\x16\x53\x9e\xf2\x8e\xbf\xcc\x73\
+\x1e\x87\x21\x3a\x81\x6b\xa4\xc1\x12\xf6\x1b\xf0\x07\x6f\x29\x77\
+\x39\xbe\xbc\x71\x39\x8b\x57\xfe\x8e\xe9\x27\xd8\x2b\xb9\x18\xf0\
+\xf3\xbb\x0d\x09\x70\xb3\x7c\xc3\x25\x4f\x79\x3f\x0e\x79\x01\xc4\
+\xdb\x15\xeb\x87\x0f\x61\x1e\x33\x1e\x6b\x54\x0d\x7b\xdd\xd3\x00\
+\x90\xb9\x6e\xa5\xc7\xf5\x42\x03\xfe\xb0\xf9\x08\x9b\x0a\x6f\x3c\
+\x64\xca\xd0\x2c\xe4\x12\x88\x77\xad\xd7\x8f\x99\x50\xb2\x3d\x62\
+\xe2\x8c\x7a\x68\x46\xdc\x8a\x6f\xde\x2d\xbf\x39\x2b\x27\x5c\x46\
+\x32\xb8\x38\x91\x21\x7a\xca\xbd\x19\x8a\x68\x27\xc5\x57\x06\xc0\
+\x56\xdf\x76\x8c\xab\x60\x59\xb6\x38\x1a\xb4\x6d\x17\x73\xba\x63\
+\xb9\xa7\x81\x2b\x22\xa2\x89\x7e\x97\x4d\xdf\xa3\xea\xc7\x8d\x22\
+\x89\x65\xdd\xd8\x2d\xe2\xaa\x7e\xec\x1a\x46\x6d\x17\xf3\xf1\x28\
+\x69\xd9\x3c\x81\x62\xc3\x33\xa6\x51\xec\xa8\xdf\xbf\x7e\xde\xcc\
+\x9c\x07\xad\x93\x14\xf8\x9e\x1d\xac\xa2\x8f\x1a\x4d\x26\x0e\x95\
+\x47\x89\x71\x30\x84\xce\x22\xe7\xa2\x72\x6c\x0c\xf5\xf4\xcc\x50\
+\x79\xa4\xd2\xd7\x67\x7f\x52\x7b\xf2\xeb\x65\xeb\x90\xbe\x10\x6b\
+\xed\x4a\x8c\xe6\x3c\x1c\x3f\xe4\xf9\xe8\x4b\xae\xae\x1e\x70\x3f\
+\xdd\x73\x58\x4d\x9d\xdc\xb0\x8c\x3d\xe9\xe5\x6c\xb3\x21\xe3\xa5\
+\x24\xbd\xdb\xf0\x2e\xcf\xf1\xb2\x77\x4e\x12\x74\x8b\x77\x7c\xef\
+\xef\x50\xd7\xef\xf8\xee\xf6\xc0\x72\x73\xc9\xcb\xd7\x6f\xa8\x6e\
+\xfc\x13\x29\x61\x59\xd8\xca\x95\xf4\x6e\xc3\x36\x1b\x72\xbd\x2f\
+\xc9\xff\xf6\x03\xdf\xbe\x3e\xb0\x54\x5b\x86\x1b\x7d\x62\x9d\xe1\
+\x24\x76\x00\xb6\x13\x36\xc9\x72\xd6\x8b\x8c\xf5\x6e\xc9\x7a\xb7\
+\x67\xbd\xdb\xb3\xc0\x67\xd8\xeb\x52\xf4\x04\x9d\xc1\x03\x3a\x8f\
+\x1e\x32\x9d\x0c\x0d\x6b\x1b\x2b\x2e\xcb\x5b\x91\xd0\x6d\xac\x65\
+\x8b\x8e\x61\x6a\x26\x3e\x2e\xd1\x5b\x39\x71\xd8\xdd\xe0\x4d\xf3\
+\x96\x7c\xb8\xde\xb5\xd7\x15\x5a\x13\x5b\x77\xca\x9e\x8b\xa5\x30\
+\x80\x16\x5a\x13\x7b\xe6\x84\x2c\xf6\x47\xde\x34\xaa\x6a\x59\xe0\
+\x9b\xfb\xda\x05\x85\x8e\xed\xac\x88\x74\xf0\xbc\xe5\xf3\x46\xda\
+\x23\x26\xaa\xbd\xe7\x28\xaa\xb4\x53\x71\xb6\x25\xa9\x2e\x26\xe3\
+\x3a\x38\x4c\x00\x47\x79\xad\xb3\x82\xfe\xd8\xa5\xd7\x8f\x38\xa4\
+\x81\x3e\x59\x49\x30\x45\x71\x40\x50\x19\xd0\x6a\xbf\x59\xdb\x75\
+\x95\x63\x61\xbb\x80\x13\xce\x58\x0e\x40\xe4\x46\x0f\x9f\x9f\x9e\
+\x99\x2e\x76\xac\xd3\x2d\x2f\x5f\xbf\xe1\xed\x3b\xa9\x0d\x9e\xd1\
+\x9c\xd9\x4a\x91\xaa\x0d\x4f\x2e\x1e\x33\x7b\xf0\x94\xd1\x2c\x24\
+\x7f\x1b\xd1\x79\x27\x39\x74\xdf\xd7\x3b\x9e\x7c\xcf\x62\x24\x60\
+\x35\x6d\x2d\x04\xc7\x4b\xc9\x96\x21\x64\x1a\x88\xd7\xfb\x12\x6e\
+\x7c\xbe\xbd\x5b\x91\x5c\x0c\xf8\xe1\xcd\xcf\x1d\x40\xcf\x31\x70\
+\x13\xcc\xcd\xeb\x3f\xc4\x92\x70\xf9\x96\xcd\x5d\x87\x95\xe8\x13\
+\xf7\x2e\x59\x54\xfa\x2c\x2a\xc1\x22\x33\x1d\x29\x99\xcb\x3b\xc7\
+\x41\x8f\x4d\xa8\xc9\x68\xc6\x84\x32\x5e\x31\x01\x7c\xae\xf4\x18\
+\xab\xc3\x52\x0f\x67\xc9\x72\x73\xb6\xd3\x94\xb7\x59\xc2\x73\x3c\
+\x37\x11\x6e\xb8\xf4\x60\x3c\x82\x65\x49\xe7\x51\x55\x47\x52\xdd\
+\x11\xae\x66\xe3\xe1\xa2\x03\x9d\xa7\x80\x96\x13\x57\xbd\xb6\xf9\
+\x19\x6f\x1e\x34\x18\xbc\x31\xb0\x51\x94\x28\x15\xe8\xb2\xb3\x88\
+\x22\xbc\x6d\xd9\x0a\xe8\x34\xcb\xc3\x75\xa5\xad\x6a\xb4\x14\xe9\
+\xdb\xce\x0f\x36\x80\x2b\x90\x6c\x81\x81\x99\xf8\x33\x28\x2a\xb2\
+\xc0\x73\x85\x0f\x3b\x7f\x4d\x7a\x99\xfe\x0c\x13\x78\x2f\x0c\x80\
+\xb7\x48\xfa\xca\x7c\x8a\x01\xef\xa7\x7b\xdd\xda\xee\x84\x12\x11\
+\xba\xe6\x56\x72\x6f\xd4\xdb\x71\x35\x4f\x9f\x0e\x2c\x72\xcc\x5a\
+\x11\xb3\xb3\xc3\x01\x8d\x26\xd6\x3a\x58\x5b\x6c\x42\x44\x4e\x07\
+\x5b\xe0\xef\xd5\x9e\x0f\xef\xaf\xf9\xe3\xbf\x0a\x98\xde\xbf\x61\
+\x5e\xcd\x99\xfa\x8a\x1f\x4a\xc1\xd4\x7f\x03\x7f\x03\xcf\x3f\x7f\
+\xca\x17\xc5\xd7\xdc\x5c\x96\x78\x79\x07\x5e\xb5\xff\xe4\x89\x1a\
+\xb2\x30\xec\xdd\x04\xb3\xf5\x94\xdf\xe5\x39\x95\xfa\xc0\x44\x0d\
+\x5b\xc0\xb4\xdb\xc5\x2e\x74\xaf\x59\x88\x35\xdc\x81\xbf\xbb\xe5\
+\xde\xec\x1c\x33\xde\x53\xf6\xf4\x2c\xb5\x67\xfb\x88\x6c\x59\xb0\
+\x7b\xbb\x64\x79\xb1\xa5\xea\xcc\x49\x3f\xe8\xf7\x19\x8f\xc7\xe6\
+\x7b\x89\xdd\xf9\xa8\x75\x37\x5d\x69\xec\xb8\x7b\xb0\x45\x8c\xf8\
+\x9e\x74\x65\xf3\x17\xd6\x17\xd6\x79\x8b\x60\xa7\xa0\x17\x39\x97\
+\x63\x3d\xae\x18\x2e\x4b\xaa\xe1\x86\x43\x36\xa2\x13\x17\x0e\xc0\
+\x3a\xca\x99\x02\x31\x5d\x21\xf4\x74\xa2\xe6\x02\x75\x97\xb7\x80\
+\x9c\x0d\x3e\x12\x96\xbf\xd6\x98\x2e\xea\xb9\x4e\x99\xd5\xfa\x4e\
+\x0f\xd9\xde\x42\x9d\x0b\x3e\xec\x5a\xb3\x82\x2d\x1b\x47\xad\x13\
+\x82\x73\x02\x78\x54\xed\xd5\xf6\x8f\x78\xb6\x5f\xc6\xee\xf5\x11\
+\xb8\xe1\x80\x7d\xd3\x7a\x14\x89\x8a\x3e\x7a\x28\x76\xdf\x76\xd4\
+\x99\xb3\x7c\x5a\xcb\x2c\xfa\x31\x36\x6e\x9e\x3d\xf4\x4c\x1f\xb5\
+\x70\x27\xe5\x3e\x75\x42\x9a\xd5\x3a\x65\xd8\xa1\xc9\xd0\x4d\x00\
+\x2b\xe5\xb1\x59\x6a\x16\x5e\xdf\xc2\xb3\xe1\x96\xde\x65\x40\x35\
+\xeb\x43\xf5\x88\x72\x5b\x70\xb7\xee\x30\x5f\x49\xfe\x8f\x3f\xff\
+\x53\x7e\xef\x5f\xfc\x3e\xdf\xfe\x6f\x7f\x42\xa5\x4e\x75\xde\xed\
+\xf2\x96\x19\xef\x5b\x00\x5e\xec\x42\x57\x14\x99\x7e\x78\x0d\xab\
+\x5a\xf9\xfa\xbb\x5b\x16\x62\xcd\xed\xf2\x16\x7f\x77\x5b\xdf\xb7\
+\x0b\x99\xad\x14\xb7\xcb\x5b\x6e\x24\xb0\x9a\x72\x90\xef\xdd\xe3\
+\x00\x3f\xcf\x3b\x5c\xef\x4b\xde\xa7\x1f\xd9\xdc\x7d\x44\xca\x1d\
+\x62\xdc\x65\x3c\xee\xba\x93\xa9\x0f\x27\x71\x3b\x58\x7f\x54\x81\
+\xb3\xb7\xab\x24\x35\xce\x86\xe4\xcd\xbb\x35\x2b\x33\xde\x3e\x0e\
+\x0a\x37\x99\x33\x37\x33\xde\x18\xfb\x78\x8d\x3c\xf1\x69\x97\x78\
+\x8d\xb3\x66\x69\xfd\x3c\x51\x95\x4e\x4e\x08\x2a\xe7\x13\x87\x61\
+\x04\xc3\x0a\xdf\xe6\x26\xb4\x7e\xd5\xa3\xa8\x2c\x38\x5d\xde\xb7\
+\xd1\x91\x71\x0c\xe0\xbe\x95\x00\x46\xd3\x7a\xdb\x86\x5d\xd5\x8f\
+\x29\x92\xf4\x44\x40\x44\x46\xe3\x44\x06\x84\x5b\x03\x58\xe9\xca\
+\xd3\xf5\x4e\x11\x35\x18\x59\x8a\x7a\x28\x9f\x2e\x8c\xf4\x5c\xce\
+\x58\x77\x36\x47\x35\x3b\x37\xec\x35\x7d\x52\x6e\x79\xb6\xdf\xaf\
+\x9e\x12\xd4\x5c\xc8\xb5\xf5\x70\x6e\xce\x46\xaa\xa4\xe2\xc3\xc7\
+\x90\xbf\xdc\xd4\x3e\xed\xa3\x6e\xc4\x7c\xf6\xcb\x78\xcf\x47\x5c\
+\x0c\x1e\xc0\x60\x82\x2f\xfe\x3e\x9b\xad\xe0\xc3\x12\xb6\xff\x77\
+\xca\xfb\x7d\xdb\xdb\xee\x44\x8f\xda\x00\x6d\x58\x74\x8b\x5d\xa8\
+\x01\x69\x80\x7d\xbb\xbc\xe5\x9e\x47\x1c\x6e\x14\x9d\x4b\xc1\x8d\
+\xd4\x92\xa4\xb9\x75\x55\xae\xf9\x37\xda\xf9\x90\x70\x3f\x12\x0e\
+\xc8\x5e\xf6\x8e\xf7\x66\xfe\xc7\xa3\xd0\x23\x16\x25\xc3\xde\xb8\
+\x35\xe8\xdb\xe9\xda\xc6\x22\x2d\xcd\xf4\x54\xcd\xd5\x5a\xb2\xde\
+\xed\xa9\xde\x0e\x59\xef\xf6\xb0\xd9\x13\xc6\xc2\x9d\xfd\x29\x2b\
+\x02\x86\x04\x24\xb1\x9e\x32\xf4\xe9\x4b\xbd\xb8\x6b\x4e\xa8\x1f\
+\x3e\x3c\xcf\xc2\x1f\x96\x6f\x19\x04\x17\xe4\xfb\xf3\xdd\xe4\x93\
+\xe9\x4c\x4f\x00\xa2\x15\x93\xdc\x9c\xd8\x5b\xda\xf6\x92\xad\x06\
+\xd1\xe3\x92\x71\xe1\x16\x5c\x7a\x12\x4f\x16\xf8\x66\x52\xbc\x96\
+\x17\x52\xaa\x76\x89\xc2\x02\xce\x16\x0f\x84\xce\x58\x34\x83\xe8\
+\xf2\x18\xf6\x8d\x94\x5c\x6d\xb3\xed\x1c\x08\x95\x63\x62\xd9\x38\
+\x97\x88\x57\x6f\x8f\x00\x9c\x37\x66\xac\x7d\xea\x62\x99\x3a\x37\
+\x9f\xbb\xbe\x97\x70\x78\xc3\x78\xa9\x6d\x35\x0b\xc6\xab\xce\xdf\
+\xf2\xa8\x1b\x39\x66\xfe\xc9\x8b\x9c\xe7\x83\xc7\x9a\xa5\xcf\x79\
+\xa0\x0d\xf0\xdd\x48\x98\xf1\x9e\x83\x7c\x4f\x27\x7a\xe4\x98\xf4\
+\x20\xf5\x7d\x97\x11\xf5\x7d\x37\xaa\xf1\x3b\xe8\x1c\xee\xee\xa6\
+\x70\x5b\x3f\x7a\x50\x7f\x86\x79\xae\x05\xf2\x68\xb5\xe3\x4d\xea\
+\xb1\x54\x5b\x53\x23\x50\xba\x7d\xc9\x53\x0c\x2b\x41\xd6\xf1\xf4\
+\x18\xd8\x5c\x32\x5f\xac\xdd\xe2\x2e\x0e\x0a\xe7\x64\x6c\x63\xc9\
+\xb0\xd7\x25\x9c\x8c\x18\x4e\x62\x9e\xf4\xea\xef\x74\x4d\x41\x90\
+\x05\x84\xc3\x01\x43\x82\xda\x1f\x3e\x26\x8d\x46\xa1\x62\xd3\xd1\
+\xad\xfd\xeb\xdb\x1a\xc0\xea\xf5\x77\xad\xc5\x9d\x5b\xd8\x99\x69\
+\xf6\xd6\x27\x46\x94\xae\x62\xd7\x3a\x19\x42\xdc\xe9\x59\x5b\xa0\
+\x96\x0a\x26\x0b\x61\x2f\x76\x8c\x6b\x33\x3f\x1c\xb4\xc6\x4e\xe9\
+\x05\x62\x91\x94\xce\xff\x2d\xa2\xaa\xb5\x23\x1c\x27\x3e\xb7\x4a\
+\xd1\x17\xa2\xa5\x7f\x23\x23\x31\x4e\xcb\xcd\xb4\x2a\x7c\xee\xac\
+\x49\xcd\x8e\x0e\x57\xe9\x10\x66\xc4\x54\xd5\xaa\xda\xb5\x98\x56\
+\x14\xc0\x96\x24\xeb\xb6\xc1\x7d\xec\x94\xd8\xe2\xcd\xad\x66\xc8\
+\xc5\x4e\x2f\xe8\x2e\x23\xe8\x5c\x8a\x16\x33\x03\xdc\x4f\xf7\x0e\
+\xd8\xf6\xbe\x73\x60\xb6\x40\x6e\xde\x6e\x5e\x9a\x4c\x6b\x19\xbd\
+\x94\x1f\xb9\x09\xfa\xad\xfb\x7b\x97\xc1\x09\xe3\xdf\x48\x28\x7b\
+\x0f\xd9\x66\x43\xfe\x62\x71\x8d\xc8\x7f\x41\x55\x4d\x11\x87\xc8\
+\xb5\x28\x59\x40\xeb\xef\xcc\x1c\x8d\x62\x41\x1c\x14\x3a\xaa\x19\
+\x46\xae\x48\x72\x35\xe9\xd6\x7e\x72\x83\xb1\xe3\xa0\xd0\xc5\x8e\
+\xd8\x33\x1e\xb3\xe0\x90\x05\x7a\x56\xdb\x27\xba\x43\x40\x37\xa5\
+\xde\x2d\x17\x6e\x41\x77\xbd\xcb\x59\x5c\x3e\x6f\xb1\xb1\xb3\xd8\
+\xcc\x6f\x6a\x7d\x62\xd7\xd9\xe1\x98\xb8\x59\xac\x50\x52\x83\xb0\
+\xb1\xb8\xeb\x9b\xd6\x9b\xe2\xf8\x7c\x1e\xa2\x72\x9a\xb8\x99\x47\
+\xab\xfa\x5e\xad\x8f\x1b\x92\x44\x36\xb4\xae\x34\xe0\x75\x5a\xf8\
+\xa8\x25\xc8\xb9\x18\x6a\x61\x2a\x72\xf2\x13\xba\xf8\x4c\x19\xda\
+\x4a\x04\x25\x99\x05\x5d\xed\x3e\x28\x69\x16\x7f\x38\x76\xdd\x39\
+\x9d\xd6\x27\x8d\xf7\x27\x72\xa2\x09\xea\x7b\x29\xf9\xf0\xfe\xda\
+\x49\x89\x83\x7c\xcf\xeb\x1f\x16\xbc\x9f\x7f\x6c\x31\x64\x13\xcc\
+\x16\x54\x96\x2d\x8f\x41\x66\x6f\x37\xc1\xb9\xbb\x29\x78\xbf\x97\
+\x6e\x5b\xca\x8f\x6e\x3b\x9b\x77\xdd\x73\xed\xf5\xe6\x4e\x62\x3f\
+\xd3\xb2\xb4\x95\x28\x76\x81\xb7\xbd\xa9\x48\x8b\x1d\xf3\x62\xa7\
+\x4f\x24\x49\xe6\x66\x28\x5b\x67\x22\xeb\x78\x9a\x6d\x2d\x78\xe3\
+\xd0\x69\xe3\x34\xd3\xe0\xb5\xb7\x8b\x58\x83\xb7\x79\x5e\x11\x9d\
+\x5b\x6e\x58\x94\xe5\x4a\x77\xff\x64\x01\x90\x11\x64\xca\x1c\x21\
+\x33\x3a\xbd\xcb\xb3\x0b\xba\x0f\x4b\xdd\xb0\xf4\xd9\xf8\x09\x9b\
+\xe2\xae\xdd\x63\xd7\xc8\x61\x58\xb9\xe8\xdb\x1f\xdc\x95\x7a\x85\
+\x96\x04\xc1\xd1\x02\x6f\x6b\x40\xe9\xce\x9a\x74\xd4\x56\xa4\xdf\
+\xa7\x1d\x75\xdf\x1a\x95\xdb\x5c\x00\xda\xfb\x11\x95\x5b\xdc\x6d\
+\x1b\x8b\xb4\x02\xc9\x20\xfc\x8e\x87\xe1\x77\x5c\xc9\x3f\xe0\xaa\
+\xfa\x23\xbd\x95\x7f\xc0\x17\xf2\x0f\xce\x80\xb6\xbd\x60\xd3\x80\
+\xf5\x98\x65\x26\x8c\x53\xec\x48\xb2\xae\xfe\xe2\xcc\xde\x9c\x8b\
+\x8a\xb0\xb5\x43\xd4\x4c\x7c\x96\x8d\x8f\x80\x6d\x19\xd3\xbb\xdf\
+\x72\x58\x4d\xb9\xbe\xfe\x78\x02\x9e\x26\x2b\xf7\x2e\x83\xd6\x6d\
+\x0b\x44\x0b\xba\x47\xdd\x88\xdd\x4d\xc1\x61\x35\x75\x0c\x0e\x70\
+\x59\x6c\xf1\xa3\x07\xcc\xe6\x5d\x6e\x82\x3e\x9d\xd1\xdc\x5d\xff\
+\x14\xc3\x3f\xea\x46\x2d\x59\x71\x69\x9e\xf2\x43\x57\x7f\xe6\xc7\
+\x77\x5b\xd4\x72\x6e\x16\xad\x71\x6b\x01\x1c\x86\x91\x9b\x2c\xe4\
+\x16\x79\x59\xee\x0a\x1f\x55\x92\xb6\x16\x7b\x36\xe1\x36\x24\x30\
+\x27\x82\x84\xf5\xe6\x70\x32\x4a\x20\xc8\xb4\xbc\x50\x24\x0d\x99\
+\x11\xbb\x93\xd6\x58\x26\x6e\x82\xf7\x7a\x97\x13\xa8\x57\xec\xb3\
+\x69\x5b\x13\x1f\x9f\x17\x05\x08\x2d\x70\x20\x72\xbe\x6e\x3d\x0c\
+\xbb\x06\x68\xdf\x36\x6c\x46\xed\x2f\x4e\xdb\x64\xb5\x08\xd0\x0f\
+\x6b\xef\x37\x10\xc2\xcc\x1f\xae\x08\x54\xd4\x38\xac\xdb\x05\x9d\
+\xb6\xd9\xfa\x4a\x4b\x87\xad\x52\x7c\x5d\xfd\x11\xdf\x7f\xf7\x03\
+\xbf\xc6\x3f\x6f\x7d\xce\xe8\x57\x61\xf5\x6f\xe1\xea\x19\xcc\x57\
+\x5f\xb1\x0f\x3f\xd3\x96\x9a\xeb\xb9\x33\x21\x24\xa1\x13\x77\xf3\
+\xed\x1c\xdf\x4c\x90\xdf\x99\xf3\x8e\x1e\x33\x71\xcb\xff\x8d\xf7\
+\x66\xf4\x95\x70\xe5\x66\xcb\xca\x12\x49\x59\x64\xac\x6f\xe1\x71\
+\x18\xf2\xd6\x68\xd7\x6a\xd6\x67\x7e\x3f\x67\xea\x4d\x99\xdf\xcf\
+\x39\x78\x53\x3a\x68\x20\xdf\x04\xfd\x13\x90\x59\x0d\xfd\x88\xf7\
+\x0e\xcc\xb3\x79\x97\xf7\x53\xc9\xe5\x68\xcb\x4d\xd0\x77\xb7\x67\
+\x68\xb0\x5e\xca\x8f\xdc\x4f\xfb\x06\xf0\x30\x6b\xec\x0c\xcd\xf7\
+\x3d\x27\x45\xac\xa4\x78\x68\x54\xe2\x7b\x15\xf2\x2b\x71\xce\x78\
+\x3c\xd5\xa3\x18\x7a\x42\xcf\x76\x43\xb9\x59\x16\xf1\xa1\x22\x18\
+\x95\x78\x69\x52\x4b\x06\x03\xe6\x7e\x95\xd4\x21\xa2\x58\xe7\x62\
+\xc8\x20\xcf\xb7\x4c\xb3\xbe\xcb\x2b\xbb\x35\x85\x3f\x72\x92\x42\
+\x19\x3d\x6c\x2d\x36\x45\xd2\x38\x93\x93\x61\x62\x03\xde\x0f\xcb\
+\xb7\x5c\x8d\x9f\xf0\x76\xf7\x84\x17\xf1\xfc\x14\xc0\x26\x47\xe1\
+\x02\x41\x91\xd0\x91\xca\xed\x51\x91\xa3\xa5\x1f\x0d\xe0\xa4\x39\
+\x31\xe3\xb1\x47\xdb\x5c\x74\xe9\xbe\xbc\xa8\x15\xce\x29\x8c\x2e\
+\x2d\x94\x02\xe5\x11\x08\xd1\xf0\x89\x8d\x3b\x61\x98\x7e\xfe\xb1\
+\x38\x01\x30\x68\x00\x03\x24\x3f\xfc\x2e\xcb\xd5\xff\x4e\x37\xfb\
+\x43\xae\xaa\x3f\xa2\x77\xfb\xaf\xb8\x92\x7f\xa0\x65\x07\x92\x37\
+\xd7\xd7\x2c\xae\xaf\x5d\xa2\xae\xea\x7b\x2e\x5c\x6f\x83\xf1\x16\
+\xc0\xa1\x68\x9f\x69\x5e\x34\x0a\x21\xb9\xf2\x50\x4a\x91\x1b\xf6\
+\xbe\x5b\xea\x0a\xdd\xbb\x3c\x77\x8b\xba\x47\xdd\x88\xab\xab\x07\
+\x6e\x41\xd7\xbb\x0c\x9c\x56\xfd\x14\xd0\xec\x02\xce\x3e\xc7\x32\
+\xef\x61\xd5\x2e\x26\x77\x46\x73\x2e\x8b\x1a\xd8\x56\x4e\x58\x56\
+\xb7\x2c\xdb\x89\x1e\x69\xbb\xee\x13\x97\xcb\xa8\x5e\xdc\x7d\x36\
+\x7e\x42\x34\x11\xf8\xa2\x64\x1a\xf4\x18\xe4\xa9\x1b\x4e\x68\xe7\
+\x23\x03\x1a\xc0\x86\x79\x01\x2a\x4f\x03\x71\xeb\xa5\xee\xfe\xe6\
+\x49\xd6\xed\xc2\xae\x5e\x8d\xed\x9d\x94\x68\x6e\x15\x89\x91\x13\
+\x89\x73\x27\xe6\xe6\x24\xe7\x96\x89\x7d\x79\xe3\x98\x78\x72\xf3\
+\xba\xd6\xc4\x67\x2a\xb6\xd8\x28\xa6\x34\x4c\x1c\x34\x67\x12\x5b\
+\xa0\xba\xd3\xde\x4a\xe3\xe1\xd2\x6e\xf8\xb4\xaf\x55\xb5\x7b\x10\
+\x99\x96\x7f\xf7\x9e\x06\xb4\xf5\xb6\x7d\x98\x8e\x44\xc5\x42\xbe\
+\xe7\x4a\xea\x39\x0c\xf3\xee\xbf\xc7\xe8\xcb\x1a\xb4\x2d\xcd\xfe\
+\x52\x11\xbf\x10\x7c\xf9\xf2\x7f\x21\x7e\x21\xe0\x07\x13\x50\xf9\
+\x01\xbe\xe2\x77\x79\x13\xfd\xb7\x26\xe0\x08\x1f\xd7\x01\xdd\x87\
+\xbf\xc9\x58\x3c\xaa\xa7\x55\x9e\xe9\xf0\x68\xc6\x32\xed\x8e\x9b\
+\x2b\xcf\x65\x34\x6e\x17\x92\xb7\x77\x8a\x97\x6f\xdb\x83\xfb\x26\
+\xbd\xdc\x55\xde\x00\x9e\x9b\xaf\xef\x37\xa2\xf7\xdc\xf3\xa5\x73\
+\x16\xee\x47\x82\xd9\x4a\x71\x3f\x9a\xf3\xb0\xf7\x90\x85\x58\x73\
+\xb8\x79\xdf\x3a\xfc\xef\x6e\x0a\xee\xa7\x7b\xb7\x20\x9c\xcd\xbb\
+\xdc\x4c\xfb\x78\xf7\x5b\x2e\xc7\x5b\x6e\xa6\x7d\xa0\xcf\xcc\xb0\
+\xf7\x65\xa1\xff\x96\xf7\x12\x6e\x02\x3d\x69\xbd\x33\x14\x1c\x56\
+\x53\x7a\x97\x81\x4b\xd0\xe9\xfc\x59\x0d\xf2\x40\xbd\xc2\xdb\x3e\
+\x61\xb7\x93\x94\xbd\xb8\x35\x03\x19\x30\xed\x4c\x0d\x26\xad\x46\
+\x3a\xee\x64\x40\xdd\xdc\xda\xa2\x87\x1d\x45\x8b\xe9\x14\xc9\x73\
+\x09\x9b\x3d\x6b\x0a\x06\xe8\xb1\xb3\x76\x7e\xb2\x3d\x4f\x88\x6d\
+\x2a\x3d\x89\x70\x46\x97\x4e\x13\x5f\x8d\x9f\xf0\x61\xd4\xab\xa3\
+\x98\x67\x4a\xd7\xee\x77\x44\x08\x02\x75\x6c\x7f\x09\xe7\x32\x64\
+\x52\x21\xa9\x4f\xba\x58\x34\x7c\xe4\xbe\x10\xe6\x40\x6d\x2b\x6b\
+\x5a\x46\x38\x96\xc5\x04\x77\x94\x4e\x95\x79\x32\x23\x2a\x04\x15\
+\x86\x7d\x8d\x84\x78\xd6\x81\xe4\xbb\xdf\xd5\x9f\xf1\xec\x9f\x38\
+\x00\x5b\x09\x61\xc1\x6b\x81\x7c\x0c\x6a\xbb\x7d\x2a\xff\x7b\xf7\
+\xf8\xf2\xc5\x7f\xc5\x68\xf7\x15\x8a\x47\xda\xa5\x68\xe9\x66\xdd\
+\x8a\xe4\xe6\xa6\x19\x0f\xd9\xc9\x0d\xa5\xe8\x89\x29\xd1\xa3\x29\
+\xdd\xf9\x8a\x57\x7f\xfd\x3d\xa3\xfb\x25\xf7\xa6\x3c\xdc\xac\xbc\
+\xd1\xcb\x5d\xe5\xed\x20\xdf\xa3\x55\xde\x7b\xae\xaf\x3f\xf2\x6e\
+\x5b\xe0\xf7\x03\x0e\x57\x0f\xb8\x44\x11\x4f\x60\xd9\xfd\x8c\xce\
+\xe5\x07\x58\x4d\x79\xbd\xfa\xce\xb1\xb1\x5d\xac\x35\x81\xdc\x19\
+\xe3\x98\xb8\x33\x9a\x73\x33\xed\xb7\x00\x0e\x50\x6d\x57\xcc\xfb\
+\x02\x96\x50\xcd\xf6\xcc\x6e\xba\xf4\x2e\x1f\x38\x16\xbe\x91\xef\
+\xb9\xbf\x14\x4e\xfd\xce\xc6\x25\x1d\xff\x0e\x8f\x08\x3d\xc5\x2a\
+\x26\x0c\x23\x27\x25\xf4\x64\x7a\x13\x5e\x7f\xd7\x67\xc9\x9a\xe1\
+\xa0\x43\x18\x46\x0c\xca\x2d\x8b\x55\xc1\x6a\xb9\xe1\xbb\xa5\xc7\
+\x78\x5c\xb1\xac\x0a\xc6\x5e\xe0\xba\xf3\x96\x4b\x8f\x07\x55\xc5\
+\x43\x42\x16\x14\x84\xf3\x94\xce\x68\xe8\xf4\x73\x1d\x28\xcb\x5a\
+\x79\xe4\xeb\xa3\xa0\xd3\xb1\x3b\x51\xf7\x4c\xc6\x6d\x30\xaf\x3d\
+\xfc\x63\x8a\xce\xf0\x35\x90\x27\x3a\x3e\xe9\xca\xcd\x51\xbd\xea\
+\xb7\x20\x95\x8d\xa0\x4e\xd4\x00\x30\xc6\x3b\x8e\x1a\xa7\x24\x00\
+\x5c\x20\x9e\x46\xd8\xa7\x0f\x6c\xf2\x47\xfc\xe9\xb3\x7f\xca\xe8\
+\x57\xe1\xd1\xf0\x77\x4f\x24\x44\x13\xa8\xe7\xc0\xdc\xbc\x6d\x1f\
+\xff\x35\xfe\x39\xd3\xd1\xb7\x34\xcf\x34\xda\x3e\x12\x79\x47\xb7\
+\xdb\xef\xf7\xd3\xab\x47\xfc\xd2\xc3\x2f\xf8\x8d\x5f\xfa\x75\x7e\
+\xe7\x77\xfe\x4b\x56\xb3\x90\x77\x79\x4e\x3f\x5e\xb7\x42\x3f\x00\
+\x4f\x7d\x78\xf2\x38\xe2\xdf\xff\xb5\xdf\xe6\xeb\xdf\xfe\x4f\x98\
+\x7e\xfe\x9f\xf2\x1f\xfd\xce\xef\xf0\xdb\xff\xdd\x7f\xc3\xb3\x2f\
+\x7e\xc6\xdf\xbe\x0c\xf9\xc3\x9f\x87\x7c\xff\x5e\x31\x5e\x4a\x3c\
+\xf1\x59\x4b\x72\x58\x66\xb5\x60\x76\x7a\x36\xe8\x73\x59\x6c\x5d\
+\x88\xc8\x5e\x9f\xcd\xbb\x54\xb3\x3e\x53\x6f\x8a\xdf\xd7\x00\x9a\
+\x7a\xd3\x13\x0f\xf9\x9e\x47\x3c\x1c\x3f\x74\xe5\x6b\xfd\x47\x57\
+\xf4\x47\x5f\xe9\xe7\xa9\xbe\x9e\xef\xb6\x5b\x12\xcf\x77\xac\x37\
+\x07\x0e\x1f\xef\x79\xfd\xc3\x2d\xab\x37\xf7\xbc\x5c\x7c\xcf\x76\
+\x7f\x07\x1b\xed\x1f\x6f\xfc\x3e\x6b\x3c\x96\x4b\x8f\xd2\x68\x7f\
+\x7b\x26\xd0\x65\x55\xb0\x5c\x7a\x1c\xe6\x4b\x3e\x7a\xfa\xbb\x9d\
+\x8c\xf4\xdf\x76\x58\x79\x14\x71\x61\x1c\x8a\x76\xcf\x9e\x23\x84\
+\x9b\xd7\x94\xd1\x25\x65\x74\xc9\xe4\xe6\xb5\xf3\x8a\xad\x4f\x2c\
+\x5a\xf6\x5c\xe6\x16\x8c\x7a\x8c\x55\x53\xdb\x02\x3d\x95\x91\x89\
+\x18\x5f\x35\xa6\xfb\x98\x98\x64\x60\x9e\x13\x08\x71\x54\xf6\xad\
+\x90\xaa\x06\x70\x20\x84\x9b\xa1\x66\x27\xf8\xc4\x45\xd5\x2a\x61\
+\x7b\xdb\x0a\xb6\xd2\x55\xf6\x22\x35\xe1\x3d\xff\x84\x47\xc3\xdf\
+\x75\x0c\x7c\x8e\x71\xdd\xc2\xf9\x08\xcc\xf6\xf6\xf1\xf5\x41\xfe\
+\x3d\x9b\xfc\x57\x8d\x8f\x6c\x22\x97\x94\x27\x76\x9d\x95\x1b\x5b\
+\xb5\x60\xb0\x6d\x3f\xf6\x60\x1c\xf0\x54\x5c\xf1\xea\xc3\xcf\xd9\
+\xf6\x86\x75\xeb\x51\xfc\x18\xfa\x70\xd9\x1d\x21\xfe\x2e\x7c\xfd\
+\xac\x47\x67\xf6\x80\xc7\x0f\xea\x91\xa4\x6f\xff\xf3\xff\x9a\x5f\
+\x7c\xf3\xcf\xf8\x97\xbf\xf7\x27\xfc\x3f\x3f\xbf\xe5\x5d\xfe\x97\
+\x3c\xfe\xfa\x92\x87\xe3\x87\x2c\x46\x82\xc3\x8d\x72\x8b\x40\x2b\
+\x2b\x66\x8b\x3b\xee\xa7\x17\x8e\x75\x67\xf3\x2e\xf7\xd3\x3d\x97\
+\x05\xee\xba\x77\xbf\xe5\x7e\xa6\x65\x86\xd6\xce\x7b\xed\x66\x5c\
+\x3e\x00\x1e\x98\x00\xcf\x7b\x6e\x96\xf0\x70\xfc\x90\xcf\x86\x07\
+\xde\xab\x90\x17\xc5\x1d\xd5\xeb\x19\xde\xf2\x9e\xc5\x66\x06\xa3\
+\x1c\x56\x21\x25\x1f\xb9\x9e\xc3\xd5\x14\xa6\xe3\x0b\x18\x78\x3c\
+\x0f\xc6\x30\xe8\xba\x12\x6f\x9e\x4b\xa6\x93\x21\x17\x93\x17\x6e\
+\x42\xd0\x33\xcb\xf0\xe6\xc4\x8f\xeb\xdd\x03\xe2\x4c\xa2\x26\x5a\
+\x72\x0c\x67\x03\x9d\x68\xdb\x6e\x29\xfa\xfd\x86\xab\xd1\xee\x0c\
+\x59\x5c\x3e\x67\x7d\x0b\xcf\xcb\xd7\xce\x2b\x56\x37\xbb\xb6\x26\
+\x76\x85\x12\x9d\xc3\xe8\xc4\x45\x7d\xf6\x24\x0b\x60\xcb\xb0\xb1\
+\xd2\xfe\x6f\xd1\x00\x6c\xa0\xa2\xf3\xb6\x93\xd5\xc2\x8d\x60\x50\
+\x64\x16\x82\x36\x47\xe1\x6d\x2b\xb2\xc3\x0e\x2f\xa8\xf0\xb6\xc6\
+\x37\x6e\xb4\x2a\x79\xdb\x8c\xbc\x1f\xf1\x0b\xfe\x21\xac\x39\x01\
+\xb2\x05\x65\x13\x9c\x4d\xf0\x66\x2f\x55\x4b\x72\xb8\x7d\xfd\x87\
+\xdf\x65\xfb\xe5\x3f\x25\x1c\x97\xe4\x4b\x0f\xc4\xe9\x79\x3b\x74\
+\xdf\x5d\xec\x5c\x8e\x3e\x11\x1f\x56\xaf\xd8\x7a\xb7\x88\x43\x42\
+\xd5\x19\x51\x36\xce\x67\xb1\x10\x6b\x9e\xfa\x75\x4b\xd0\xcd\x34\
+\x87\xb9\x8f\xff\x2a\x60\xf9\x17\xff\x8a\xde\xd5\x13\x66\x2f\x4a\
+\x61\xbb\xb5\x57\x00\x00\x20\x00\x49\x44\x41\x54\xae\xa2\xa7\x8c\
+\x7e\xeb\xa7\x5c\x7c\xf9\x1d\xbf\xfe\xe2\x1f\xf1\xd5\x97\xff\x90\
+\x3f\xf9\x9f\xff\x57\xfe\xa7\x7f\xf6\x47\xbc\xfb\xc5\x5b\xf8\xfa\
+\xd4\x53\xbe\x1c\x6d\x99\xcd\xa7\x0e\xc0\x96\x99\xf5\x22\xcf\x30\
+\xf3\x68\xce\x6c\x3e\xa5\x33\x06\xcc\xc2\xaf\x66\xf5\x48\xeb\x70\
+\xf4\x22\xf2\x9e\x47\x5c\x46\xef\x29\x81\x9b\xfc\x73\x7e\x63\xb5\
+\xe3\xe3\xea\x5b\xf6\xd9\x94\x0f\xd5\x82\x08\xf8\xdc\x9b\xc2\xb8\
+\xc2\x1b\x7f\xc1\x97\x9f\x4f\xd8\xc6\x92\x7e\x16\xb5\x86\x77\x5b\
+\x00\xd7\xdb\xfb\x56\xe3\x28\xe8\x89\x43\xd5\x62\x0d\x4c\x58\xa3\
+\x98\x02\xfb\xed\x96\x43\xe5\xd1\x5d\x0f\x5c\x34\xd3\xfa\xcb\x82\
+\x98\x45\x26\x98\xfa\x35\x61\x0c\x1f\xc2\x4a\xf6\xb4\xac\xe8\x3d\
+\x61\x75\xa4\x89\x2d\x1b\x37\xab\x7e\x49\xbf\xa3\xe7\x4e\xf4\x1b\
+\x3e\x30\x4a\x9a\x74\x9a\x6e\x51\xda\x2a\xe9\xdc\x04\x17\x8a\x57\
+\xb2\x66\xe3\x46\x7a\x8d\x08\xe7\x74\x1c\x07\x81\xe2\x4e\x0f\x0a\
+\x5c\x27\x47\x9f\x08\x5b\xc7\x8b\x44\x45\xa0\x3c\x54\xf5\xdd\x59\
+\x5b\xed\xac\xd5\xf6\x5f\x88\x13\x90\x1f\x3f\x0f\x20\x5d\x7f\xcf\
+\x46\xfd\x8a\x61\x5a\x6b\xb5\x35\xcf\x2b\x12\x21\x54\x66\x66\xbb\
+\xd5\xc2\x63\xf1\xcd\x77\x4c\xff\xf1\x18\x8a\x05\xf3\x72\xc4\xcb\
+\x6f\xff\x98\xff\x97\xb1\x37\x0b\x92\xe5\xbe\xce\xfc\x7e\xb9\x55\
+\x65\x66\x65\xd6\xd6\xdd\xb7\xb7\xdb\xb7\xef\x0a\x10\x0b\x09\x82\
+\x94\x48\x88\x04\x29\x8a\xa3\x65\x28\x5b\x33\xf6\x84\x2d\xc6\x48\
+\xb2\x3c\x96\x46\xa1\xa7\x79\x72\xf8\xc1\x0f\x8e\x90\xdf\xec\x07\
+\xdb\x31\xe1\x07\x4d\x8c\x6c\x86\x56\xca\xb2\x3d\x5a\x47\xa4\x16\
+\x8b\x82\x28\x40\x24\x38\x20\x81\x0b\x5c\x2c\xbc\x6b\xef\xcb\xed\
+\xee\xda\x32\x2b\x33\xab\x72\xf3\xc3\x3f\xf3\x5f\x59\xdd\x17\xd2\
+\x54\x44\x47\xd6\xd2\x6b\xf5\xc9\x93\xdf\xf9\xce\x77\xbe\xe3\x3f\
+\xda\x65\xe3\x23\xab\x60\x8f\xc8\xed\x75\x8e\xba\x09\xf9\x91\xca\
+\x51\xb0\x4b\xf0\x28\x12\x8d\x8f\x91\x98\xce\x78\xf9\xda\x0a\xcf\
+\xbc\xb7\xcf\xb5\xa7\x6f\xd1\xf8\x44\x9d\x1f\x7b\xe1\xa3\x5c\xb9\
+\xfc\x4f\x68\xae\x6f\xf0\x6f\x7e\xf5\x77\x99\x1c\x4d\x2e\x74\xd9\
+\x54\x6b\x09\x86\xa9\xc8\xac\x5d\x47\x64\xe4\xce\xa2\xe4\x8f\x4b\
+\xb6\x62\xa5\xd5\x93\x70\x43\x7e\x5d\xb5\x4b\x17\xde\x46\xb5\x96\
+\x04\xed\x56\xfc\x1b\x94\x60\x1f\xea\xab\x2c\xb5\x6e\xf2\xfc\xad\
+\x9b\x1c\x6a\x53\x1a\x76\x1d\x2f\xd0\x64\x61\x97\xe1\x63\x43\x61\
+\xa2\xf2\x84\x2e\xa3\xad\xa3\x07\xc5\x4e\xbd\x71\x63\xee\xd8\x19\
+\x37\xd8\x56\x73\x94\xe8\xf0\x9c\xcd\x17\x4c\x73\x9f\x86\xe3\xc8\
+\xa6\x47\x6a\xa7\x44\x04\x58\xb6\x22\xd9\x89\xce\xd1\x36\xc3\x56\
+\x9d\x81\xb7\x42\xf3\x92\x28\xee\x5a\xc3\x59\x26\x8e\x0b\xae\xd9\
+\xac\x64\xe3\x88\x40\xe8\x89\xb5\x50\xc1\x2f\xf8\x61\xdf\x0a\x71\
+\xfd\x1c\x4d\x53\x29\x5d\x1b\x34\x14\x52\x22\xe2\x02\xf5\x36\x8b\
+\xc9\x8f\x38\x12\xba\xe2\x18\x4b\x2c\x65\xac\x32\x18\x73\x10\x25\
+\xac\x74\xf1\x66\xca\x63\xbf\x38\x6a\x58\xf4\xcb\xd5\x04\xe1\x3c\
+\x26\xae\x06\x63\x15\x23\x97\xcf\x3d\x29\xc8\xcf\x7f\xae\x7f\xe3\
+\x7a\xa5\x30\xb0\x3e\x24\x13\x2b\x17\x5c\x95\xde\x1b\x9d\x31\x79\
+\xf3\xeb\xd4\x59\xe6\xbb\x5b\x31\x7b\xfb\xe1\x1c\xbd\x05\xc0\xc3\
+\x43\xc2\x7e\x24\x33\x5f\x3c\xec\x62\xb4\x7a\xc4\xa3\x88\xdf\xfa\
+\xee\x5b\xb4\xde\x7a\xc4\x0f\x5c\x49\x78\xf9\xc5\x4f\x30\xfe\xcc\
+\xdb\x98\x9f\xfb\x29\x9e\xfb\xe2\x02\x3f\xb3\xff\x32\xaf\xfd\xe5\
+\x5f\x31\x39\x4a\x59\x5b\xb1\x24\x5f\x9c\xb5\x04\x27\xac\x9c\xc1\
+\x4a\xdb\x27\xce\xd7\x80\xe9\x5c\x26\x5e\xe8\xd5\xa0\x35\xc3\xcb\
+\x47\x9a\x23\xdb\xd0\x2b\xa9\x5f\xfc\x0e\x48\x86\xa2\xca\x13\xbf\
+\xd9\x3f\xa4\xf1\x7d\x0d\x77\x71\x49\x0e\x8f\xaa\x40\x69\x53\x6c\
+\xc6\x16\x91\x51\xe8\x4f\x8a\xd6\x74\xd9\x8d\xd3\x5a\x19\x8c\x93\
+\x0b\x2c\x45\x79\x1c\x4d\xa6\x24\x67\x03\x0c\x16\xe9\x2e\xa8\xb8\
+\xc5\x82\x1b\x9f\x84\x4e\x4b\x63\xea\xfb\xe0\x38\x73\xf0\xad\xdf\
+\x33\xa9\x0d\x4f\x24\x9c\x10\x93\x21\x47\xb4\x8e\x26\x98\x9b\x37\
+\x38\x66\x4f\x66\xe2\xb2\x59\x22\x5c\x87\x02\x4c\x02\x89\x89\xd5\
+\x52\x2f\x6c\x15\x81\x7c\x5e\x7a\x59\xbe\x1e\x9e\x2b\x8e\xc2\x22\
+\x80\x0d\x42\x01\x43\x42\x85\xf3\xdb\x23\x7c\x19\xac\x52\x0d\x21\
+\x77\x52\x68\xa6\x39\x73\xdb\xac\x60\xf2\x57\xef\x7c\xe9\x43\x39\
+\xcf\x6a\x40\x97\xb7\x77\xf8\xd2\x85\xe7\x5b\xcf\xc3\xf8\xca\x2f\
+\x33\xbe\xf2\xcb\xc4\xfa\x73\xe8\xd2\x15\xe8\x09\x05\x5e\xa1\xa8\
+\x22\x0a\xa5\xb7\x45\x58\xec\x50\xf6\x92\x35\x72\xb7\xcb\xc9\x83\
+\x37\xd9\x1e\x3e\xb8\xd0\x91\xdb\xcd\x90\x6a\xb2\xb9\x6c\x0a\xb4\
+\xda\x57\xe9\xb6\x2c\x1e\x0e\x5d\xde\xf9\x46\xca\x5f\xbc\xb6\xcd\
+\x5f\xfe\xc5\xd7\x98\xf6\xde\xa7\xfb\x42\x1b\xe7\xda\x06\xdb\x61\
+\x9d\x2c\x3c\x91\x05\x5b\xc9\x50\x2c\x17\xac\x44\x2f\xef\xcd\x15\
+\x79\x25\x4b\x51\x16\x79\xe5\x73\xc7\x83\x59\xf7\xf0\xac\x3b\xe5\
+\x78\x30\xfb\x3d\x56\x2c\x81\xdf\xfd\x60\x56\xdc\x79\xa7\x27\x74\
+\xe2\xc2\x6d\xa7\x68\x3b\x97\x41\x0b\xe0\xe4\x5d\x19\xbc\x25\x0f\
+\xac\x8c\x05\x7d\x56\xed\xc6\x95\x8f\x47\x93\x01\x83\xc1\x00\x86\
+\x3a\x6b\x9d\x84\x8e\x9a\x12\x0f\x15\xfa\xc3\x74\xae\xf1\x51\xe5\
+\x93\xcb\x42\x7a\xda\x5a\x92\x9a\x94\xce\xd1\x36\x03\x6f\x85\xfe\
+\xca\x26\x87\x93\x84\xd6\x70\x32\x47\xa7\x09\x8e\x79\xe6\xad\x37\
+\x8f\x89\x0b\x3c\x6b\x59\x39\xfd\x92\x22\x2b\xe9\xb4\xbe\xe8\x82\
+\x35\x11\x6b\xa6\x47\xe7\xa4\x38\x71\xa8\x88\xe5\xe6\x73\x19\x78\
+\x9e\x0f\x08\xe2\x09\x16\xb6\x80\x29\xc5\x66\xa4\xb9\x56\x6e\x81\
+\xa1\xaf\x18\xf0\xf5\xec\xaf\x78\x99\x7f\xf8\x36\xbc\x23\x82\xb5\
+\x6c\x8c\x54\xb3\xf2\x9d\x07\xff\x92\xda\xda\x75\x3c\xbd\xc0\x52\
+\x91\x52\x09\xe0\xb0\xe8\x4f\xce\xae\x0a\x22\x13\xe7\x33\x2f\x37\
+\x60\x6b\x3f\x00\x8e\xf1\x81\x81\xb7\x22\x03\xb4\x64\x27\xf6\xfc\
+\x7d\x16\x86\x11\x47\x15\x46\xc0\x68\xc1\xe4\x68\x86\x69\x8d\xa6\
+\x08\xc2\x3b\x1c\xb0\xb6\xbd\xc4\x35\x1e\x72\x7a\x3b\xe1\x7e\x07\
+\x94\x65\x03\xf7\xe1\x61\x51\xbd\x77\x61\x8e\x27\x16\x8f\x97\xdb\
+\x70\x7c\xe6\x73\xb4\xe0\x54\x20\x46\x54\x14\x76\xb0\xa0\x9e\xd2\
+\xcb\x4d\xd1\x31\xcc\x7b\xb2\xe0\x5b\x6e\xcf\x32\xf1\x59\xcb\x24\
+\x0b\x9a\xf2\xf7\xbe\x7f\xa4\x70\xed\x69\xe8\x3f\x36\x20\x0c\x51\
+\x34\x17\x02\x95\x49\x2a\x7e\x57\x45\x73\x19\xd9\x03\x6c\xad\x2e\
+\xdb\xc8\xfe\xd4\xa3\x11\x4c\xc1\x15\xef\xcd\xd8\x50\x69\xf4\xd2\
+\x42\x6f\xe2\xd0\xd0\x62\x1a\x41\xce\xb8\xd5\xc1\x01\xe2\x61\xb1\
+\x88\xb1\xdb\x90\x0c\xc5\x88\x94\x06\x62\x0f\x75\x56\x19\x44\x2b\
+\x33\x71\x89\x87\xdb\x1c\xc9\xe0\x19\xb6\xea\x4f\x16\x4e\x15\x90\
+\xc4\x84\x8b\x2a\x36\xc5\xcf\xe5\x3e\x66\x67\x2c\xf4\x13\xb6\x51\
+\x87\xa8\xb0\xb2\xc2\x91\x6b\x99\x9a\xb2\x13\x25\x96\x38\x96\x54\
+\xdc\x05\xb9\x64\x45\x83\xe1\x14\xd4\x5b\x58\x48\x2f\x4b\x41\x50\
+\x58\x60\xd4\x07\xe1\xd6\x1c\x14\xf8\x8f\x09\xe4\x5f\xcf\x6a\x73\
+\x30\xe3\x7b\xfc\x32\x93\x4b\x3f\x4c\x9c\x5c\x17\x2e\x99\xf2\xac\
+\xb7\x3e\x54\x0b\x21\x56\x25\x08\x58\x64\x12\x72\x96\x8b\x77\xf1\
+\x83\x37\xee\xf1\xdd\x3f\xf8\x4d\x6e\x9f\x7c\x5b\x34\x1e\x2c\xf0\
+\x83\x26\xbb\x19\xa2\x81\xc1\x9a\x0c\x60\xd5\x5a\x92\xfa\x86\x95\
+\xd4\x07\xe5\x60\x4e\x69\x76\x14\x42\xb2\x13\x71\x90\xee\x90\x1f\
+\xa9\xb4\x07\x21\xf9\x82\x73\x11\xef\x16\x59\xb9\x7c\x9c\x2f\x08\
+\x6c\x7c\x3c\x10\x54\x5c\x2f\xab\x00\x9f\x5c\xfc\xfc\x32\x63\x97\
+\xd4\x5b\xb5\xfb\x57\xd2\x6b\x65\x26\xb6\xdb\x1a\x93\xbd\x01\x4a\
+\xda\x03\x2f\xa7\xdf\xef\xd3\xef\xf7\x19\x8c\x12\x06\xbb\xd0\xef\
+\xf7\x89\x0f\x7c\x74\xdd\x22\x48\x35\xfc\x69\x44\x7c\x10\x33\xc8\
+\x53\xf0\x72\xc6\xa9\x41\xa3\x27\xb2\xa9\x53\x5b\xa4\x11\x4c\x69\
+\x69\x0e\xe3\xbc\x43\x43\xe9\xe3\x17\x06\xe4\xee\xb5\x26\x9d\x96\
+\x86\xa2\xb6\xc8\x2a\x30\xc2\x53\x1d\x49\xb5\x59\x76\x34\x97\x89\
+\xa9\x24\x8c\x92\x2b\x2e\x31\xb1\xea\xfb\x92\x67\xae\xca\x3c\xc7\
+\x7e\x8c\x9a\x5a\xb9\xd8\x5e\x64\x99\x72\xa6\x4e\xeb\x47\xf8\xd3\
+\x33\x88\x74\x31\xed\x61\x76\x65\xb6\x8d\x11\x03\x95\x71\xe1\x0a\
+\xa4\x95\xc7\x50\x91\x4a\xb7\x92\x27\x76\xe6\x66\xd4\xc2\xf9\x76\
+\x74\xa1\x66\x4b\x09\xb1\x22\xf1\xb5\xee\xc1\x16\xf6\xce\x0f\xf3\
+\xeb\x59\xed\x3f\x2a\x88\xcb\xcf\x7b\x07\x01\x41\x0e\x46\xbf\x5c\
+\xd1\x1f\x5b\xf2\xb2\x25\x3a\x72\x33\x71\x92\x98\xdf\x8b\x8a\x20\
+\xcf\x99\xf8\xe1\xac\x03\x54\x14\xac\xa3\xc7\x62\x60\xf3\x78\x64\
+\xcc\x4d\x59\x94\x19\x2d\xab\x5f\x92\x9d\xb0\xd2\x67\x62\xae\xd5\
+\x9c\xaf\x49\x01\x4f\x19\xe8\xdb\xb5\x75\x8e\x47\x86\x1c\x08\x2d\
+\x1b\x1d\x65\x93\x63\x2e\xdb\x14\x3f\x53\x64\x74\x73\xae\x90\x2b\
+\x3f\xbf\x97\xf7\x24\x5f\x5c\x3e\x5e\xe8\x9f\x62\x14\x85\xdf\x8a\
+\x35\xe3\xb2\xd5\xc9\x63\x82\xbe\x48\x50\x8f\x3b\x1d\xf2\x62\x51\
+\x62\x5b\xd1\xe8\x74\x3a\x74\x3a\x1d\x36\xaf\x3a\x6c\x76\xda\x74\
+\xda\x9b\x24\x89\xd0\x0e\x5f\xae\xad\x72\xe3\xc5\x75\xba\xd7\xaf\
+\xd1\x69\x6f\x72\xb9\xb6\x8a\xd2\xde\xa4\xd3\xde\x04\x3a\x28\xed\
+\x4d\x86\x03\x0f\xa7\x93\xa2\xb4\x9b\x05\x9b\x92\xa3\xa8\xad\x82\
+\x57\x2e\xf4\xc8\x85\x29\x84\x9b\xf9\x32\x8b\x7a\x86\xc5\xd1\xe9\
+\xd9\x9c\x30\x5e\xc2\xb2\xa2\xf1\x51\xf2\xc4\xb3\x13\xa1\x51\xd4\
+\x37\x36\x71\xa0\x89\x4c\xac\x99\x33\x0b\x14\xb9\xaa\xb6\xd3\x01\
+\xd3\xc2\x3f\x27\x92\xb7\xca\x9d\x64\x45\x86\x4b\xcb\x59\x8c\x42\
+\xbe\xa9\xf8\x02\x57\xeb\xa1\x28\x10\xc3\x7e\x84\xd5\xd7\x84\x25\
+\x40\x38\x2b\xf2\x6c\x3f\x28\xd8\x8b\x50\x66\x6a\x13\x13\x6f\xed\
+\x2a\x1f\x78\xdf\x62\xe7\xdd\xda\x3f\x98\x8d\x7f\x3d\xab\xb1\xf3\
+\xae\xf8\x90\x75\xd6\xce\x0e\xd1\x9a\x5a\x74\xe8\x66\xab\x74\x4b\
+\x56\x62\x5e\x64\x6f\x8a\x93\x71\xac\x51\x77\x8a\xe9\x90\x73\x3f\
+\x63\x6f\x3f\xe4\xe1\x41\x84\xff\x68\x97\xe5\xf6\x0c\x07\x5f\x76\
+\xd6\x65\x70\x9c\xc7\xc2\x17\x5a\xa9\x45\x96\x5e\x75\x14\xa9\x61\
+\x38\xaf\x3a\x2b\x71\xec\x4a\xea\xcb\x63\x99\x8d\x7b\x79\x8f\x23\
+\x4d\x04\x6a\xd9\xa5\xeb\xe5\x3d\x19\xb8\x0b\xbd\x9a\xcc\xc4\xcb\
+\x6d\x64\xa6\x2e\x8b\xba\x4e\xd4\xe4\xf1\xe0\x31\x07\xbd\x13\x8e\
+\x42\x21\x8e\xbf\xd4\xef\x33\xb6\xa7\x28\xed\x26\x69\x65\xcf\xc8\
+\xa8\xe8\xcc\x96\xf4\x5a\xd2\x1f\xb2\xab\xf6\xd8\x79\x38\xc6\x3b\
+\x3e\x62\x57\xed\xb1\x37\x3d\x04\xfa\x0c\xe8\xa3\xdb\x21\xba\x1d\
+\x62\xac\x5d\xa2\xe9\x1a\xb4\xe9\xa0\x77\x44\xf0\x96\x7a\x89\x86\
+\xcd\x9c\x9f\x5b\xe6\x38\x73\xf4\xdc\x95\xc2\xde\x61\xf4\x58\x64\
+\xe1\xb6\x3b\xeb\xda\x55\x31\x71\xc9\x2f\x6b\x41\xb9\x3b\x31\x10\
+\xdf\x53\xe8\x89\x43\xd1\x55\x3b\x27\x69\xb4\x2c\x53\x8c\xe0\x9b\
+\x16\xb9\x15\x48\xbf\x09\x2a\xd9\x56\x0b\x15\x69\xc4\xcd\x28\x16\
+\xc6\x28\x51\x28\x9c\x7e\xe2\x09\x49\xa0\x73\x9c\xf7\xc9\x23\xa1\
+\x8c\x3b\xe9\x47\xe8\x61\x48\xa0\xa9\x28\x7e\x40\xd8\x37\xb0\xd3\
+\x8c\xb0\x9f\x90\x0f\xb6\xd8\xe8\xc7\x8c\x57\x27\xbc\xf3\x76\xfd\
+\x43\xb3\xf1\xf0\x0e\xfc\xeb\xb7\x45\xf0\xde\xc9\xc6\x8c\x57\x67\
+\x7f\xe8\xf5\x2b\x57\xb0\x8d\xcf\xcc\x4f\x83\x48\x43\xc1\xf0\x82\
+\x88\x24\x8a\x14\x8c\x46\x4a\x3c\xd6\x64\xb3\xa3\xc4\xc4\x67\xe1\
+\x2e\x71\x78\x20\x29\xb0\x12\x5f\x6e\xa8\x82\xae\xea\x44\x4d\x09\
+\x27\x00\x96\xb5\x53\xb2\xf0\x44\x04\xab\xb5\x24\xb3\xe1\x6a\xa1\
+\xad\x56\x6a\x8b\x4f\xfc\x7b\x26\x47\xa9\xec\xd8\x1d\x0f\xb8\x70\
+\x5c\x6e\x8b\xa2\xad\x5a\xe4\x55\x03\xb9\xcc\xc6\x00\xf1\x28\x9a\
+\x3b\x56\x27\x3b\x0e\xf7\x52\xb2\xf0\x84\x61\xab\x4e\xb8\x7e\x95\
+\x89\x1f\x72\x3a\x0d\xd8\x3f\x1c\xd0\xef\xf7\x39\x9d\x06\xf4\xfb\
+\x7d\x0e\xa6\xa2\x73\x27\xd2\x66\x8d\x8e\x69\xd1\x5e\x37\x30\xdb\
+\x35\x3a\xed\x3a\xed\x95\x26\x7a\xb7\x56\x38\x06\x09\x65\x59\xa9\
+\x3f\x56\x3b\xe9\x1c\x6c\x68\xa2\x31\x0e\x98\x19\xb1\x14\x01\xdd\
+\xb0\x0b\x53\xc7\x61\xce\x4e\x2c\x10\x6d\xdb\x3d\xa2\xed\x1e\x49\
+\x38\x71\xfe\x56\x85\x13\x65\x46\x2e\x23\x56\xad\x96\x38\x98\xf9\
+\x6c\x73\x7d\xa9\x03\xb6\x72\x49\xaf\x11\x46\x62\xea\x23\x54\xf0\
+\xfb\x7d\xfc\x52\xe9\x66\x5a\xc2\x24\xa5\xea\x3f\x61\x5a\x34\x5b\
+\x1a\xcb\xad\x4b\xe2\x44\x70\x14\x1c\xd3\x22\x29\xa4\x9c\xbe\xd6\
+\x10\xcb\x6b\x34\x15\xf0\x38\x1d\x2f\xb2\xdb\x31\x78\x66\xe9\x65\
+\x94\xe7\x7b\xec\xbc\x5b\xe3\x5f\xbf\xfd\xe4\x8c\x5c\x06\x30\x80\
+\x77\xf7\xe7\xe4\xf3\xb7\x13\x95\x38\x3f\x38\x27\x96\xaf\xee\xfc\
+\x50\x66\x27\x6b\x41\xeb\xc5\xc5\xd6\xa6\xb2\x5a\x2e\xc7\x9d\x86\
+\xc9\x2d\x0c\x6b\x0d\xe5\xcc\x97\x01\x59\x36\x39\x72\x7b\x9d\x41\
+\x5b\x78\xaf\x95\x7a\xdd\x43\x3f\x67\xd5\x51\x38\x4e\x17\xc9\xc2\
+\x13\x9e\x1f\xac\xc9\x00\x5e\xd6\x4e\x9f\xf8\x8f\x31\xac\x35\xce\
+\xba\xd3\x39\xec\x5c\x66\x54\xe5\xcc\x27\x5f\x70\x64\x40\x57\xdb\
+\xca\x5d\xb5\x08\x52\x65\xa6\x6b\xee\xaa\x11\xbd\xcc\x64\xb9\x8d\
+\x84\x1f\xcb\xda\x29\x47\x61\x31\xba\x94\x8f\x58\xeb\x2e\xb1\xdc\
+\xbe\xcc\xc6\x92\x41\x77\xa3\xcd\x62\xcd\x66\x7d\xb5\x8d\xbe\xd0\
+\xa6\x6e\x5a\x74\x3a\x1d\xb1\xac\xd1\x36\x09\xd2\x59\x72\x68\xd6\
+\x6b\x98\xa6\x49\x33\x17\x1f\x25\xaf\x5c\x15\x0f\x25\x49\x38\xe7\
+\x22\x94\x24\x21\xa9\x9d\x4a\xaa\xad\x2a\x92\x97\x57\x29\x7b\x76\
+\x7f\xe0\xad\xcc\x65\xe2\x12\x4e\xc8\x02\xd0\x71\x64\x46\x8f\x8b\
+\x8c\x1c\x81\x98\x76\x9e\xf7\x98\x9c\x05\x74\x5a\x04\xad\x16\x2a\
+\x18\x84\x58\x15\x16\x42\xaa\x87\x8a\x06\x41\x69\xa6\x52\x7e\x84\
+\x08\xa3\xc0\xa0\x30\x48\x29\x9d\x35\x2d\x2b\x97\xd3\x1e\xaa\x95\
+\x0b\x45\x9c\x65\xe2\x03\xef\xef\xef\xc2\xe3\x1b\xd4\xf2\xa7\x04\
+\xce\x7d\xbb\x3e\x87\x7b\xab\x85\xdc\x9d\x6c\x4c\x7e\x47\xfc\x53\
+\xdd\xa7\x7e\x7b\x16\x14\xfa\x55\x3a\xd6\xf5\x4a\xf0\x7e\x88\x77\
+\xdb\xdc\x88\x53\x5d\x42\x9d\x30\x8a\x20\x8a\x48\x4e\x5d\x5a\xfa\
+\x3d\xe2\xf0\x80\xd5\xd5\x19\xa6\xdd\xcd\x40\x29\x6c\x54\x85\x6b\
+\x8f\xe8\x8e\x3d\x7b\x68\x08\xfb\x2a\x3f\x97\xd9\xf8\x4e\xfb\x80\
+\xc3\xa2\x7d\x7d\x9c\x8a\x2c\x6c\x77\x4c\x59\x18\xaa\x93\xc7\x42\
+\xe9\x96\xfa\x12\x26\xcc\x06\x24\x45\xa0\x56\x9f\xaf\x66\x62\x59\
+\xdc\xe5\x6b\x17\x9e\x2b\x83\x3e\x0b\x4f\xe4\x09\x75\xea\x9d\xd0\
+\x6d\x59\x3c\xff\xe2\x47\xa8\x2f\xd6\x08\xf4\x06\x69\xde\x40\xef\
+\xd6\x30\xb1\xe9\x98\x16\x1d\xd3\x42\xe9\xb4\xe5\x68\x12\xd8\x72\
+\xca\xa3\x9c\xc3\x4b\x92\x90\x91\x12\x09\xf1\x7c\xbd\x26\xc7\xfc\
+\x47\x93\xa9\x18\x1a\x2d\xf4\xc7\x49\x12\xd2\x6a\x5a\x8c\x03\x91\
+\x91\xcb\x2c\x5c\xc2\x09\xd5\xf7\x81\x06\x99\x21\x30\x5a\xb9\xc2\
+\xa1\x74\xbf\x1f\x78\x2b\x73\x22\xa0\xf3\x90\x22\xb5\x53\x89\xab\
+\xc7\xea\x14\x75\x6c\x65\x33\xea\xa9\xf8\x27\xa6\x15\xac\xca\x39\
+\x3a\xad\x54\x13\x39\xa6\x25\x82\xba\x90\x66\x6a\x17\x2c\x51\x28\
+\x3c\xdd\xaa\xcc\x72\xb9\x70\x3c\xaf\x28\xe6\x20\xd4\xeb\xe8\xab\
+\x6d\xe8\x36\x69\xad\xdc\xa2\x3d\xbc\x89\xf2\x7c\x8f\x3f\xfd\x5d\
+\x97\x7f\xa1\x4e\x2f\xe0\x60\x00\xe5\x79\xf1\x4f\xfd\x49\xe5\x27\
+\x79\xf9\xf9\xaf\x73\x37\xfc\x9f\x41\xb9\x01\x91\x52\xe8\x84\x0b\
+\xe1\x4f\x21\xa9\x94\x59\xb8\xa2\x81\x2e\x2d\x60\xc5\x54\x4b\x51\
+\x08\x86\x17\x47\x8d\x54\x6b\x09\xd5\x5a\xa2\x7b\xb2\x47\x3e\x5d\
+\xe7\xc6\x25\x03\x65\x25\x93\xa6\x25\xef\xad\xc6\x73\x83\x9a\x65\
+\xf0\x96\x99\xb9\xcc\xd6\xbb\x99\x28\x0c\x17\x86\x11\x47\x21\x1c\
+\x1e\x9e\xc8\xa0\x2b\x9b\xb7\x17\x02\xf5\xef\xb9\x9d\x87\x18\xcb\
+\x6d\x24\xb4\x50\xad\x25\x26\x47\x29\x87\x7b\x22\x0b\x3f\xf3\xe2\
+\x2d\x96\xdb\x97\x59\x6e\x5d\xa2\xdd\x6e\x63\x4b\x81\x79\x25\x40\
+\x26\xe2\x6f\x0f\x52\x8d\xb4\x2e\x32\x6e\x1f\x95\xa6\x25\xbe\xa7\
+\xa7\x37\xb0\xe3\x9c\xd1\x64\x4a\xaf\x3f\x62\xe7\xf8\x31\x23\x2f\
+\xc6\x09\x2c\x6c\x2d\x95\x1c\xb2\xae\x8b\x00\x2e\xb3\x70\x19\xc0\
+\xe5\x63\x4f\x75\x80\x31\x6a\x2c\xfe\xf8\xd2\x3c\x3c\x18\xa4\x4c\
+\xb5\x75\xda\xee\x11\x6a\x78\xc4\x61\x3e\xcb\xec\xd3\x02\x4e\x94\
+\x90\x42\x0b\x84\x8f\x6b\xc3\x31\x50\x1b\xa1\x2a\x2b\xf5\x52\xd4\
+\x5e\x06\xb0\x9d\x66\xd8\x69\x86\x1e\x9e\xb3\xb1\x2a\xb2\x6f\x19\
+\xb8\x17\xd6\xe6\x16\x81\x20\x97\x2f\x9a\x22\xdb\x96\x46\x85\x69\
+\x71\xa2\x94\x5f\xdb\x75\x15\xae\x2d\x76\xb1\x2d\x8b\x4e\xd6\xe4\
+\x0b\x9f\xff\xe2\x5c\xe0\x96\x90\xa2\x84\x11\x6f\xbf\x29\x84\x07\
+\x1f\xef\xfc\x02\xfb\x0b\x2b\x1c\x8c\x7e\x19\x4f\xbf\x2e\x5c\x3a\
+\x4d\x93\x64\x30\x28\xe8\xb2\x73\x53\xd2\xe7\x94\x6a\xf2\x14\x33\
+\x73\x4c\xd3\x14\xac\x85\x25\x0a\xdd\xf1\xa9\xc7\x61\xfc\xd4\xdc\
+\x3c\xdc\x5b\x7b\x39\xe3\xe3\x3d\x54\xee\xf1\x63\x2f\x3f\xc5\xad\
+\x97\x3e\x8a\xbb\xfc\x31\x39\x82\x54\x06\xf2\xf1\x40\x60\xd0\x9d\
+\xfd\x0e\x59\x78\xc2\x19\x6b\xd8\x1d\x81\xa7\xcb\x06\x49\xb5\x71\
+\xe2\xf9\x95\x69\x72\x3f\xbd\x10\xd4\xe5\x73\xe2\xd8\xff\xd0\xa0\
+\x3e\x1e\xcc\x98\x8b\xc9\x51\x2a\x83\xbc\xdb\xb2\x58\x6e\xc6\xd4\
+\x17\x6b\xac\x6c\x26\x42\x4f\x1c\xa9\xc2\xc2\xb5\xd0\xf8\x96\xbe\
+\x10\xe5\x73\x79\x7f\xc0\xfe\x78\xca\xc9\xf1\x01\xb7\x1f\xee\xf3\
+\xfa\x07\x77\xb9\xfb\xc1\x07\x7c\xf7\xfe\x2e\x0f\x0e\x0f\xd8\x9d\
+\x84\x44\x64\x82\x9e\xa3\x7f\xa1\x39\x32\x0b\xd6\x99\x87\x85\xa7\
+\x8a\x2c\x5c\xfa\xb8\x95\x16\x5a\x67\xe1\xae\x84\x11\x1f\x76\x53\
+\x9b\x22\x70\xcd\x39\x6a\x54\x50\x6c\x7a\x18\xcd\xfb\x12\x6b\x28\
+\x85\x07\xb1\x27\xc9\x31\x3f\x56\x70\x4a\xf1\x4c\x91\x79\x4b\x5d\
+\xb1\x71\xce\xab\xb8\x2c\x0a\xcb\xc5\xe3\x61\x18\x91\x72\xb1\x19\
+\xe2\x54\x2e\xed\x21\x16\x5a\xa7\x58\xb4\x68\xc1\xb5\xe6\x0f\xf0\
+\xf1\x4e\xc2\xd6\xc6\x37\xd9\x79\x77\x02\x1f\x9d\xf2\xea\x9d\x2f\
+\x71\x27\xfb\x33\x00\x3e\xf6\xe2\x3d\xda\xc3\x9b\x5c\x7d\x41\xe7\
+\xd9\xcd\x97\x85\x01\x92\x9c\x30\x89\xf8\xce\x77\x1e\xb1\x5a\xdf\
+\x25\x5b\x58\xc2\x6e\xc0\xae\x1f\xb2\xe1\x58\x2c\x75\x8a\x00\x0d\
+\x23\x82\x7e\x8f\xb8\x63\x16\x89\x7a\x42\x4c\x9f\x28\x99\x51\x71\
+\x83\xb6\x45\xfe\xf8\xb6\xcc\xd0\x0b\xbd\x1a\x3d\xe0\xad\xbd\x1e\
+\x8d\xe5\xcb\xfc\xd0\x0b\x2a\x57\x3e\xf5\x0c\x2b\x1b\x47\xfc\xed\
+\xff\x73\x83\xbf\x7b\x5f\x83\xfc\x35\xba\x47\x45\x3b\xd7\xd1\xa8\
+\xaf\x68\xac\x58\x4b\x64\x85\x41\x8a\x1f\x34\x89\x07\x8f\x99\x1c\
+\xef\xd2\xcb\x4c\x32\x3f\x65\xcc\x14\xd7\xb1\xe8\x67\x03\xf4\xc0\
+\xc4\x75\x34\xa0\x4f\xe6\x37\x51\x9d\x4e\x11\xb4\x85\x13\x10\x53\
+\x5c\x3a\x78\x7e\x88\xeb\x5c\xd4\x36\x2c\xb7\x41\xb5\x34\x0e\xa6\
+\x8e\x5c\xed\xad\xe6\x23\x36\xaf\x3e\x45\xa3\x2b\x4e\xfc\x47\x7b\
+\x09\x56\x3a\x00\x06\xc5\xea\x62\x70\x6a\xe2\xb8\xaf\x0e\x68\x16\
+\x5a\x06\xe1\xe9\x51\x9c\x58\x51\x48\xa7\xd3\xa4\x5e\xd0\x96\x1d\
+\xd3\x22\xad\x17\x54\xe4\xb0\x8f\x47\x4e\xb3\x08\xde\x20\xd5\xb0\
+\x99\xd9\xc8\xba\x99\x2f\x83\x17\xd5\x21\x73\x1c\x86\xa3\x90\xe5\
+\x26\x8c\x6d\x81\xbb\x17\xac\x0d\x06\x1e\xd4\xd8\x97\xc1\x3c\xf0\
+\x56\xe4\x4e\x12\x80\x24\x73\xd0\x64\xe7\xae\xd0\x26\x17\x7c\xb3\
+\xf4\x27\x0e\xb1\xa4\xbd\x2a\x51\x02\x08\x97\xf4\xf3\x2a\xfa\xf2\
+\x72\x6b\x22\x96\xc8\xb4\xc6\x0d\xfc\x62\x75\x58\xc9\x1d\xfb\x85\
+\x49\x77\x79\xa4\x32\x2c\x5a\xf5\xa8\x28\x67\xec\xac\x88\xd9\x65\
+\x1f\x70\x8d\x3a\xff\xd5\x47\x3f\xc2\xee\xf5\x67\x78\xe5\xe1\xfb\
+\xfc\xf4\xed\xaf\xf0\xbc\xfa\xb7\x02\x37\x0d\x6f\xf2\x85\xcf\x7f\
+\x91\xd6\xca\x2d\xd6\xeb\xcb\x72\xd4\xdf\x2a\x0b\x52\x33\xa4\x7e\
+\xf3\x19\x0e\xef\xbf\x0f\x27\x3a\x6b\xdd\x26\xd7\xcc\x70\x6e\xa8\
+\x54\xb5\x72\x74\x4b\x74\x97\xc4\x89\xd9\x21\xf2\x32\xfa\xb1\xc5\
+\x52\x57\xe7\x23\x2f\x75\x69\x3f\x7d\x99\x77\x6e\xff\x07\xb6\x5e\
+\x7f\x0f\xff\xd1\xee\xec\xd2\xed\xc1\xfb\x6f\xde\xe3\x6b\x03\x8f\
+\x1f\xfc\xcf\xee\xf3\xc9\x4f\x7c\x9a\xab\xbf\xf4\x73\xdc\x7a\xe7\
+\x36\x6f\xbc\x7a\x1d\x9f\xf7\x71\x8e\x37\x50\x96\x0d\x89\x9b\xc5\
+\x7f\x77\x24\xfd\x8b\x7b\x99\x89\xe7\x87\xc4\x4e\x0d\xc3\x17\x99\
+\xb8\xe3\xe4\x78\x45\x56\x6e\xd0\x44\x75\x46\x32\x90\xc7\x84\xb8\
+\x95\x2c\xd1\xa0\x46\x8f\x94\x2e\x33\x2d\x71\x95\x1b\x06\x0b\x56\
+\x80\xbb\x22\x6b\x5f\xbf\x76\x8b\x2b\x37\xaf\x73\xe9\xc6\x66\x31\
+\xc2\x50\x38\x3e\x15\xff\x4b\xbd\x48\x4c\x5d\x20\x9d\xb6\xd0\x6a\
+\x43\x3a\x99\x22\x18\x08\x33\x93\xc5\x5b\x75\x25\x18\x64\xf4\x51\
+\x51\xa2\x09\x4e\xcd\x94\x01\x0c\xa0\x7a\x0e\x74\x52\x19\xc0\x79\
+\x63\x8c\x37\x76\xc4\xe3\xc0\x41\xd7\x2d\x22\x1a\xa8\x81\x29\x33\
+\xf1\x8d\x4b\x06\x03\x6f\x1d\x06\xfb\xd8\x6d\xad\xc0\xc7\xf3\x58\
+\x58\x14\x85\xce\xdc\xf0\xa9\xdc\x63\x27\xc5\xec\x16\x28\xa1\x82\
+\x6a\x26\xb3\x82\xc8\x32\x71\xc2\x48\x76\xe4\xe2\x0a\x56\xd6\x42\
+\x05\x5f\x0d\xb0\xac\xfc\x82\x2d\xab\x66\x9a\xa4\x51\x24\x8f\x16\
+\x33\x75\x5c\x5a\xd1\x50\x94\x41\x1d\x86\x0a\x76\x9a\x0b\x89\x26\
+\x26\x53\x7d\x99\xe5\x16\x7c\xe1\x3a\x6c\x7d\xe3\x26\xbf\xf5\x78\
+\x99\x17\x6f\xbd\xc6\x8f\x7e\xe1\x5f\xb1\x79\x6b\x1d\x3b\x2a\xf6\
+\xdd\x45\x9c\x9b\xc1\x52\x58\x30\x15\xb2\x67\xae\x8a\xb3\xbc\x5b\
+\xc7\x2a\xf7\x89\x16\xda\x08\xcb\x34\xcf\x95\x7c\x39\xb0\x80\xdb\
+\x1f\x01\x36\x86\xe2\x89\xa5\x8f\x4f\xe2\x7d\x95\x26\xbd\xe1\x88\
+\x3f\x7e\x4b\x8c\xee\x7b\x67\x47\x18\xcb\x9f\xe3\xc7\xaf\x2d\xf2\
+\x89\x8d\x0e\xdb\x7b\x1d\x8e\x0f\x0e\x51\xc3\x23\x1e\xaa\x22\xd3\
+\xe4\x47\x2a\x0f\x0f\x22\x26\xc7\xbb\x9c\x8e\x0c\xc6\x14\x12\x4b\
+\x5f\x1c\x5d\x27\xc2\x2b\x24\xaa\xe2\x3e\xb8\x88\xe0\x6d\xf8\xb5\
+\x27\x66\xdd\x6e\x65\x4f\x5c\x2f\xef\xb1\x0c\xac\xac\x3e\x87\x6d\
+\x8f\xb8\xb6\xbe\xce\xa3\xfb\x0f\xe8\xf5\x15\xbe\xf8\x99\x0e\x37\
+\x57\x72\xdc\xee\x0a\x0b\x56\x9d\x34\xb7\x30\xea\x1d\xb4\x49\x84\
+\x55\x0c\xd5\x96\x59\x55\x9b\x44\x60\x4e\x49\x8b\xd7\xc5\x7b\xa6\
+\x0a\x0b\x40\x2d\x9d\x33\x53\xa1\x92\xe6\x3c\x35\xa7\x59\xb0\x18\
+\x49\x12\xe2\xdb\x21\x76\x92\xd2\x47\xa3\xab\x6a\xe4\x5e\x8e\xa7\
+\xce\xe0\xc5\xf9\x9b\xcc\xc4\x45\x81\x57\xb2\x14\xab\x4a\x32\x27\
+\xdf\xd4\x82\x96\x1c\x46\x4d\xed\x14\x83\x27\x6c\x14\xbd\x70\xb3\
+\x4c\x39\xae\x54\xbe\x65\x9a\x55\x32\x17\x8a\x1c\xeb\x11\x2e\x98\
+\x79\xa5\xbd\x6c\x49\x09\x67\xd9\x6e\x0e\x0b\xef\x8a\x92\x97\x4e\
+\x2b\x30\x26\x2c\x27\xac\xe3\x09\xf6\x48\x63\x94\xa7\xe8\x76\x82\
+\x6d\xd4\xd9\xcb\x6a\x74\x9e\xdd\x42\x7b\xa8\x70\x9c\xff\x2c\x97\
+\x17\x4d\x16\xc8\xc0\x9c\x59\xbf\x5a\x91\x22\x8a\xd2\xb2\x33\x17\
+\x28\xa8\x5a\x83\xfa\xa4\x47\xd4\x1f\x48\x08\x24\x3b\x75\x4f\x5a\
+\x8a\x16\xf6\x19\x8d\x43\x9a\x45\x76\x4e\xc7\x27\x6c\x6f\xdd\xe3\
+\xdd\xf7\x1e\xe3\x9a\xf3\x05\x54\xb7\x65\xf1\xa8\x77\xc4\x1f\xbf\
+\xf5\x88\x3f\x7e\xeb\x11\x1f\x7f\xe6\x11\xef\xdf\x5a\xe6\xe6\xa6\
+\x8d\xaa\x7d\x9a\xcb\xf9\x1e\xf7\x07\x0a\x0c\x0e\xd9\xcd\x60\xf2\
+\x68\x97\xe3\x01\x78\x7e\x8e\xeb\x8c\xc0\x37\x49\xec\x09\xf9\x28\
+\xc7\xd0\x4d\x19\xc0\x02\x1f\x8b\xfb\xfd\x6c\x40\xc7\x69\x8b\x23\
+\x6d\x09\x21\x24\x04\xa9\x24\x8c\xae\x1a\xf1\xe9\x85\x15\x8c\xb5\
+\x16\x76\xbb\xcb\x83\xc7\x31\x2b\x16\x1c\x76\x72\x1a\xcb\x97\x49\
+\xcd\xab\x74\xac\x19\x3c\x88\x27\x3d\xb4\xca\xb8\xbe\x36\x11\xc2\
+\x1a\x0d\x5b\x14\xee\x93\xf3\xdb\xa9\x32\xce\x39\x6c\x8b\x91\xa6\
+\x89\x38\x09\x95\x68\x02\x8d\x99\x78\x9e\x54\x58\x5d\xe1\xd6\x18\
+\x91\x92\xbb\x0a\xc5\x8c\xa9\xcc\xce\x42\xe0\x3e\x9f\x89\xcb\xcc\
+\x5b\xf2\xc5\x2d\xb6\x67\xed\xe5\x00\x1a\xc5\x74\x88\x9c\x12\x29\
+\x8a\x3c\xdd\x2a\x27\x94\xad\x52\xe7\x10\xce\x63\xe4\x48\xd0\x68\
+\x46\x45\x7d\xe6\x44\x96\x5c\x18\x63\xa7\x19\x9e\xa3\x14\x7b\x3f\
+\x66\x25\x93\x53\x1d\x5f\x2a\xe6\xed\xca\xad\x19\x56\x14\x51\x6e\
+\x75\x88\xc2\x10\x2b\x35\x45\x00\x17\x2e\x3b\x4d\x25\x23\x34\x73\
+\xea\x96\xc5\xb3\x5a\xc4\xfd\xad\x9f\x27\xdf\x3c\xe6\x27\xba\x75\
+\x0c\xb3\x0f\x74\xa4\x5b\x50\xd5\x2e\x36\x2c\x32\x31\x40\x43\x09\
+\xa1\xd3\x91\x85\x80\x45\x58\x08\x93\x8a\x1d\xd1\x61\xb9\xca\x61\
+\x16\x0c\x4a\xab\xce\x58\xab\x95\x12\x3c\xf2\xe3\x18\xd7\x3c\x94\
+\x4d\x85\xf2\x76\x3a\x32\x68\xb5\x5b\xe0\x41\x2f\x85\xbf\xb9\xf3\
+\x88\xb7\xf6\xca\xae\xd9\x43\xd9\x70\xe8\x65\xe1\x5c\x80\xba\xf9\
+\x2c\xe3\xea\x41\x5d\x2e\x2c\x8a\x93\x08\xa3\xb0\x53\x4d\xec\x09\
+\x7a\x50\xa7\xa3\xb6\x0b\x9c\x5c\x27\x23\x95\xb8\xb9\x85\x5b\x64\
+\x66\xf1\x3e\x74\xd5\x08\xa3\x69\xd2\xb0\x2f\x71\x65\x25\x07\x12\
+\x82\x9a\xca\xdf\x85\xd0\x6d\xde\xe0\xc5\xce\x2a\x37\x37\x0d\x1c\
+\x7d\x4c\x4e\x1d\x3d\x50\xd1\xed\x4c\x14\x74\x72\x99\xa4\x2d\xbb\
+\x60\xe7\xe7\xd8\x6c\xad\x4e\x50\xbc\xa7\xd5\x2c\x2c\xda\xd2\x16\
+\x03\x90\x70\xa2\xba\x85\xb4\x67\xe7\x98\x05\x3e\xee\x78\x39\xfd\
+\x4c\xbc\xe6\xa9\x0e\x49\x12\xa2\x05\xb3\xac\x3c\x3e\xf5\x18\x58\
+\xcf\x4a\x0c\x1c\x0c\x52\xda\xed\x23\x0e\x07\x3a\x3f\xa6\x05\x24\
+\x99\xf3\x44\x48\x21\xdb\xce\x8a\x1f\x40\xa4\xe3\xfa\x79\xe1\x9f\
+\x36\x7f\x4b\x09\x65\x03\x40\x2b\x98\x85\x12\x0a\xd8\x46\x5d\xfa\
+\x53\xa4\x17\xa4\x9a\x4f\x30\x9e\xaa\x70\xb4\xae\x9f\xa3\xf8\x39\
+\x56\x6a\x12\x6a\x11\x4a\x49\xbb\x35\x0d\x68\x1a\x58\xa9\xc9\xc4\
+\x0f\x09\xb1\xb9\x7a\x45\xe7\x85\xee\x9f\x8a\x4b\xb0\xb2\x36\xe7\
+\x16\x54\xde\x0f\x2b\x98\x37\x4b\xc7\x60\x89\x25\x07\x96\x69\xd2\
+\x31\x4d\x30\x3b\x73\x3c\x38\x96\x39\xa3\x11\x73\xf1\x77\xbb\xae\
+\x8d\x6a\x07\x9c\x45\x19\xbd\xdb\x03\x76\x46\xce\x05\x2a\x6b\xe0\
+\x88\xa2\xcd\xf3\x4d\x3c\xe3\x59\xba\xed\x0e\x69\x7b\x83\xde\x00\
+\x86\x83\x21\x77\xdf\x7a\xc8\xab\x6f\x3d\xe2\xf5\x87\x87\xf4\x06\
+\x02\x1e\xc8\x2c\xab\xcc\x02\x35\x4e\x22\xe2\x24\x2a\xf8\x6d\x13\
+\x37\x8f\x64\x70\x27\xf6\x44\x64\x60\x35\xc7\x75\x2c\xc6\x4c\xf1\
+\xfc\x90\x56\xe0\x56\x58\x8a\x59\x00\x7f\x7a\xa1\xcd\xf2\x52\x01\
+\xcf\xcc\xab\x92\x27\xde\xbc\xa6\x61\x6e\xde\x90\xfa\xe1\x34\x6f\
+\xa0\xdb\x99\x18\x0e\xb5\x33\xf4\x40\x9d\x9b\x59\x33\x2f\x4c\x14\
+\xdb\x04\xe9\x64\xae\xb9\x71\xfe\x96\x9b\x75\xfc\x69\x34\x37\x01\
+\x22\xdc\x2b\x6d\xec\x20\x2c\xae\x2a\xb3\xf4\xe6\x66\x42\x5c\x94\
+\xda\xb3\x9f\x56\x2e\x65\x2f\xa9\xb6\xea\xed\x30\xb5\xd1\x55\x1f\
+\x37\xf3\x19\x91\x4a\x0d\x45\x49\xb5\x8d\xfd\x18\x5d\xec\xd0\x98\
+\x10\xc4\x00\x13\xd1\x75\x2b\x60\x82\x53\x66\xd1\xca\xf8\x52\x89\
+\x85\xd3\xc2\x38\x5b\xc2\x85\x62\x1c\xdf\x2a\xee\x5b\x55\xc6\xa0\
+\xc2\x4c\xa4\x73\x6b\x09\x98\x1b\x22\x0d\xac\xc9\xec\x22\x37\x8a\
+\x09\x3b\x29\x9d\xa2\xc3\x77\xd4\xff\x4f\xa1\x53\x4a\x39\x43\xc2\
+\xc2\x26\x40\x40\x89\x19\x33\x21\xbc\x36\x8b\x8c\x62\xe6\xf4\xfb\
+\x03\xa9\xb6\xd3\x0a\xcd\x44\x29\x3e\xc2\x2a\x1d\x3d\x33\xc6\xa1\
+\x45\x03\x11\xf0\x47\xe3\x87\xc2\xae\xea\xf4\x8d\x0f\xc5\xa2\xb1\
+\x53\xa3\xcb\x7b\xe2\xf2\xe7\x37\x41\x2f\xd8\x84\x36\xb4\x80\x1e\
+\x29\x86\x3f\xc5\xf3\x9f\xf0\x8f\x2f\x60\x44\x35\x0b\x97\x01\x5e\
+\xc5\xc7\x5e\x91\x0e\x5c\x27\x2a\x8a\xbc\xb2\xd8\xd3\x8a\x4c\x6c\
+\xb1\xd6\x5d\xa2\x61\x77\xa8\xaf\x2e\xc8\xb1\x7c\x50\x58\xeb\x2e\
+\xcd\x35\x37\xce\x27\x94\xa4\x08\xe0\xf3\x9b\x57\xab\x33\x6c\x60\
+\x4b\x49\xe6\x93\x6e\x65\x61\x57\xcd\xce\xba\x6e\x61\xc7\x62\x0d\
+\x46\x99\x8d\xd7\x8d\xa9\xcc\xc0\x9e\xee\xc8\x79\xb9\xb3\x22\x9e\
+\xce\xef\xad\xb6\xdb\x1a\xc1\x20\x65\x55\x49\xa4\x8a\xad\x6c\x63\
+\xa7\xa4\xa8\xbe\x4f\xe6\x38\x32\x90\xd5\xb2\x55\x2c\x47\xd6\xcb\
+\x82\x26\x0a\x45\xa6\x2c\x2d\x58\x4b\x21\xbb\x29\xba\x73\x8e\xa4\
+\xd3\x84\xd9\xb6\x2c\xd0\x2a\x19\xb2\x0c\x5a\x2b\x52\xb0\xa2\x08\
+\xfb\x34\x94\x43\x98\xaa\xe2\x10\x68\x2a\xb9\x23\xcc\xae\xcb\x6c\
+\x1c\xc4\x93\xb9\xe5\x34\x61\x91\x2d\x57\x3a\xff\x9e\xb5\xcd\x87\
+\x52\xca\x59\x9e\x24\xe5\xb6\xd1\xb4\x82\x75\xad\x64\x22\x03\x35\
+\x26\x60\x74\x16\x72\xb6\x17\xe1\xf7\xfb\x78\xfd\x03\xa2\x28\x62\
+\x2f\x88\xe8\x13\x32\xee\x4f\x88\x22\x85\x2c\x1d\x33\x0e\x22\xa2\
+\xfe\x80\x47\x7b\x3e\xf9\x71\x7c\xa1\xdd\x5b\x75\xb9\xec\xa2\x91\
+\xf9\x4d\xf0\x40\x75\x46\xa8\xf9\x88\xcc\x4f\xf1\xfc\x50\x06\x70\
+\x99\x5d\x65\x51\x98\x1c\x3f\x59\x1f\x9b\x44\x17\x30\xb1\xeb\x44\
+\x73\x59\xbc\x2c\x06\xcb\xf0\xe9\xaa\x16\x57\xd6\x2c\x36\x94\x58\
+\x66\xe1\xd5\x8a\x66\xe2\xfa\x35\xd1\xdc\xb8\xb4\xbe\x8c\x65\xd5\
+\x45\x16\x0e\xc4\xba\x86\x24\x88\xd0\x6d\x93\xa4\x92\x8d\xa3\x39\
+\x18\x81\x84\x0f\x65\xfb\x39\x48\x27\x04\x86\x72\xa1\x39\x92\x9b\
+\x75\x9c\xda\xac\x4d\x5d\xe5\x89\xf5\x40\xc5\xd6\x52\x19\xc0\xe5\
+\xd8\x7f\xc9\xb1\x2c\xcc\xef\xdf\x9a\x5d\x07\x06\x22\x38\x0f\x73\
+\x7d\xe6\x8a\x59\xb4\xac\xcb\x2e\xa0\x9c\x76\x06\xd4\xb2\xf5\x8b\
+\x65\x8a\x0e\xdc\x39\x0b\xd4\x28\x0c\xa5\xc8\xa7\x0c\xd4\xb2\x79\
+\x51\xbe\x5e\x85\x1e\x56\xa4\x10\xa0\x16\xde\x6b\xa2\x71\xa2\xf8\
+\x81\xcc\xbe\x0b\xb9\xd8\xa3\x91\x36\xb2\x62\x0b\xa9\x60\x40\x72\
+\x6c\x49\xfd\xc8\x5f\xba\x02\x3f\x9e\x57\x1b\x1c\x6c\x5f\x97\xc1\
+\x29\x57\xe5\x56\x27\xb0\xab\xcd\x8c\x02\x22\xd8\x96\x45\x73\xbd\
+\xc7\x71\xfa\x06\xdf\xf7\xbe\x0a\xfa\x9b\x8c\x03\x85\x86\x2d\x4c\
+\x62\xfa\x39\x78\x9e\x90\x03\xb6\xfa\x23\x46\x67\x21\xc9\xde\x23\
+\xe2\xf0\x00\x2f\x5a\xc5\x68\xf5\x58\x5d\x5d\x92\xed\xe7\xd5\xd5\
+\xa5\x59\x57\xcc\xd1\xc0\xed\xe0\x45\xcf\x92\x29\x4d\x09\x15\x0c\
+\x7f\x2a\x03\x30\x4e\x22\x19\xbc\xaa\xbe\x4c\x9c\x44\x68\x0c\xe7\
+\x82\xb7\xcc\xca\x25\x6e\x4e\xec\x09\x78\x22\xa0\xdd\x3c\x9a\x73\
+\xdc\x15\xc1\xdc\xc1\x68\x9a\x28\xb5\x45\x1a\xf6\x25\xea\xab\x97\
+\x59\x1d\x45\x1c\x36\x4d\xc6\xc7\x29\x76\x5b\xc3\x5c\x5d\x67\xe9\
+\xa9\x45\xec\x92\x7a\x8c\x14\x92\xca\x25\x3c\x2a\x82\xcc\x53\xf3\
+\xb9\xbd\xd7\x65\x20\x27\x81\x3a\x17\xc0\xb6\x56\x97\xef\x6f\x55\
+\x57\x01\xe0\x4f\xa3\xbf\x37\x63\x97\x81\x5d\x16\x75\xe5\xe3\xb3\
+\xa2\x71\x33\x3e\xf5\x64\x16\xae\x76\xf0\xec\xb6\xc6\xaa\x16\xc8\
+\xef\xe1\xa9\x0e\x0d\x5b\x7c\x9f\xaa\x12\x4e\x8f\x8a\x0e\x9b\x9c\
+\xce\xb0\x2a\xc6\x29\x9a\x0a\x56\x77\xbe\x0d\x1d\x4e\x24\x37\x25\
+\x16\xd3\x98\x78\xc5\xc4\x47\xc7\x34\xf1\xa3\x90\x7a\xd1\xcc\xa8\
+\x0f\x8e\x50\x8a\x3d\x64\x81\x95\xa1\x98\x39\x5b\x96\x85\x43\x26\
+\xa8\xae\x28\x92\xd8\x59\x29\xb7\x29\x99\x39\xa3\xde\x08\xa5\xdb\
+\x04\x84\xcb\xbc\xae\x3e\xc7\x78\x75\xc2\x33\x4b\x0f\x81\x2f\x14\
+\xdb\x94\x94\x73\xeb\xc1\x22\x89\xc6\x75\xd3\x82\xa8\x47\xdf\xdc\
+\xe7\xdd\xdd\x3f\x83\xf4\x35\x00\xde\xef\x89\xbf\xf1\xb9\xa5\xcf\
+\x22\xfc\xf5\x2c\x3a\xb6\x49\x98\x5b\xdc\xed\x8f\x21\xab\x73\x7c\
+\xf8\x16\xc3\xe4\x16\xf0\x80\x9b\x2b\x87\xb2\x95\x6c\x58\x6b\xac\
+\x71\x20\x0d\x00\x0f\x8a\x6e\x82\x72\xe6\xd3\x48\xf6\x64\xa6\x2c\
+\x31\x6d\x6f\x00\xdd\x36\x68\x83\x21\x29\x2d\xd2\x4a\xf1\x56\x3e\
+\x2e\x03\xb8\x84\x14\x71\x12\x41\x1b\x0a\xef\x6b\x12\x7b\x82\x17\
+\x08\x26\xa3\x15\xd4\xc8\xfc\x1a\x6e\x3e\xa2\xab\x2a\xac\x3a\x16\
+\xd7\x36\x35\x16\xb4\x36\x93\xc3\x3d\x0e\x57\x2f\xcb\x69\x88\x35\
+\x33\xc1\x59\xde\xc7\xb4\xae\x91\xb2\xc0\x70\xd8\xc2\x69\x0e\xd0\
+\xbc\x13\x52\x77\xe6\xdd\x90\xd8\xe0\x06\x2a\x04\xc5\xff\xd6\x36\
+\x99\xd9\xbb\x22\x03\x53\xf0\xbf\xa9\x74\xcd\xbc\xe4\x19\xf8\xae\
+\xc8\xd4\x83\x82\x27\x16\x81\x6d\xcb\xe2\x2f\x09\x22\x9a\xe4\xc2\
+\x80\xbb\xd0\x58\xf4\x93\x10\x5d\x9d\xf1\xcd\x79\xbf\x28\xc2\x17\
+\x5d\xa6\xda\x3a\x67\xe1\x2e\xab\x35\x75\x2e\xa0\x0f\x53\x9b\x85\
+\x51\xb1\x6a\xb7\xe0\x99\x1b\x8e\x03\xc1\x0c\x17\xab\x06\xa1\x98\
+\xce\xc0\x22\x0e\x15\xfa\x05\x4e\x09\x34\x55\x72\xc3\xe5\xe4\x72\
+\x75\x49\xa2\x16\x2a\xf2\xd2\xaf\x87\x82\x9a\xb2\xa2\x08\xd7\xcf\
+\xd1\xc3\x10\xe5\x60\xca\xe9\x78\x91\xbc\xf7\x50\x16\x81\x66\xa7\
+\x23\x9c\x30\x9f\xd0\x02\x2e\x0b\x44\xd3\xb2\xb8\xb4\x7e\x95\xc4\
+\xb2\xa4\xa6\xe1\xda\xe5\x90\x56\xf0\xf3\x1c\x6c\x5f\x17\x2a\xb5\
+\x48\xe1\x71\xd8\xe3\x9d\xed\xbf\xe4\xfb\x93\x2d\xfc\xa8\x3f\xd7\
+\x8a\xf4\x92\x8c\x1d\xf5\x88\x77\xb7\xfe\x07\xde\x3f\x79\x55\x06\
+\xaf\xbc\x64\x27\x19\x53\x42\x82\xa8\x47\x18\xf6\xa1\xd0\x8f\x1c\
+\x9d\x9e\x31\x7a\x0c\xde\xf1\xdb\x73\x1a\x61\x63\xc5\x94\x73\x74\
+\x6b\x35\x4b\xb6\x8c\x95\x33\x5f\x52\x5e\x73\xf4\x53\x50\xa7\xab\
+\x41\x6f\x20\x02\xf6\x49\xb0\x41\x14\xca\xc3\x39\x66\x42\x69\x2a\
+\xf4\x33\x05\x75\x34\x00\xb7\x60\x30\x98\x1d\xc7\x4c\xe9\xb6\x2c\
+\x8c\xa6\xc9\x95\x7a\x8b\xfa\x69\x93\x83\x74\x47\x66\xe2\xea\x6d\
+\xa9\x75\x93\xd5\x85\x18\x27\xf6\x69\xeb\x23\xb9\xba\xa1\x84\x0f\
+\x26\xd0\x0d\xce\xd9\xd8\x06\x62\x61\xa2\x5d\x3e\xef\x09\x61\x8f\
+\x1d\x84\x22\x48\xbd\x29\x76\x6f\x82\x4f\x82\x3a\x39\x12\xc1\x3d\
+\x6e\x90\xa7\x9e\xc4\xd8\xd5\xa6\xc7\x79\x46\x63\x3e\x33\x8f\x59\
+\xec\xb4\x65\x26\x06\x61\x81\xf0\x24\x58\xa1\x36\x05\x84\x28\x33\
+\xf1\x38\x10\x22\x7b\xd5\xf7\x05\x3b\x11\x63\xc9\x81\x4f\x2c\x93\
+\xe6\x13\xd8\x89\xaa\x07\x9b\x55\xc2\x0f\xc1\x42\x91\x04\x3a\x56\
+\x2a\x2a\xfd\xb0\x1f\x31\x1a\xa6\x58\x7d\x8d\xe3\xbc\x4f\x53\xc9\
+\x88\x6e\x6c\xca\xc5\x8c\x73\xad\x67\x33\x2f\x4c\xb4\xc5\xd1\xb2\
+\x04\xcd\x56\x62\xe0\x52\x34\x5f\x42\x99\xa1\xfd\x9b\x22\x10\xa2\
+\x0e\x29\x21\x5b\x8f\xbf\xcb\x1f\xde\xfe\xb7\x7c\xf3\xce\x7f\xcf\
+\x7b\xdb\xaf\xe2\x85\x33\x06\x21\x1f\x4e\x38\x39\xfe\xd3\xb9\xe0\
+\xad\xde\x37\xf5\x08\xb3\xd3\xc6\xe9\x74\xb0\x3a\xe2\x32\xd9\x31\
+\x42\x76\xa3\x43\xb1\x5e\xab\xd5\x9b\x5b\x49\x50\xfa\x0f\x67\xe1\
+\x89\x14\xed\x94\x01\x3c\xb4\x3d\xdc\x7c\xc6\x34\x94\xc7\x5e\x3a\
+\x1f\xac\x4f\xba\x95\x01\x5e\x32\x15\xf9\x28\xa7\xa3\xe6\xa8\xfa\
+\xf2\x1c\x35\x57\xb6\x8f\xdd\x5c\xb0\x11\x6b\xdd\x25\xce\xda\x2e\
+\x93\xc5\x11\x6b\xda\x15\xc6\xc7\x29\x87\x85\xfc\x32\x18\xa4\xdc\
+\x3b\x78\xc4\x64\x6f\xc0\xe5\xf6\x0d\x6a\xed\x53\xc8\x66\x7c\x6b\
+\x9e\x7a\x12\x2e\x8c\x2a\x7b\x33\x66\xcf\x47\x8c\x50\x64\x20\x27\
+\x41\xc4\x70\xe0\x11\x1f\xf8\x0c\x07\x1e\xc3\x81\xc7\xe8\x6c\x9b\
+\xfe\x63\x83\x24\x88\x38\x53\x4f\x18\x8c\x12\xf2\xc1\xa8\x08\x76\
+\x4d\xb2\x12\x81\x9d\xcf\x69\x2a\x3a\x6a\x3a\x87\x99\x8f\xb3\xf9\
+\x93\x48\xee\xa8\xae\xdc\xaa\x70\xa2\x84\x11\x25\x53\xe1\xa9\x8e\
+\xb0\xb1\x32\x08\xe5\xe8\xbd\xc1\x6c\x4c\x47\x21\x90\x10\x22\xaa\
+\xd0\x66\xe5\x06\x24\x2c\x13\xc7\xb4\xd0\xed\x44\x70\xbc\xe9\xfc\
+\x2f\xe0\xda\x2d\xd4\x56\x87\xdc\x12\x70\x22\xd4\x22\x29\x34\xaa\
+\x1a\x4b\x95\x38\xdb\x27\xc4\x2a\xb4\x0d\x61\x18\x11\x86\x82\x4b\
+\xb6\x2c\x93\x38\x9a\x15\x00\x86\xd9\xe7\xbd\xed\x57\xb9\x7d\xfa\
+\x15\xa1\x05\xd8\x4f\xb8\x7d\xfa\x15\xee\x9e\xfc\x2e\x3b\x93\xad\
+\x42\xfa\xf8\x06\xef\x9f\xbc\xfa\xa1\x18\xcd\x30\xfb\x95\x6a\xdd\
+\x22\xc2\xe2\x74\x30\x60\xc3\x5c\x2d\x34\x9f\x5d\x28\xda\xb8\x07\
+\xd3\x90\x83\x69\xc8\xfe\xbd\x23\xee\xef\x85\x73\xc5\xd5\x98\x29\
+\x7a\x50\xc7\x53\xcc\x19\x1c\x28\x82\x52\x63\x38\x07\x1f\x3e\x2c\
+\x90\x65\xa1\xa8\x21\xb3\x77\x19\xd4\x55\x1a\xae\x6c\xb2\xac\x3a\
+\x0a\x1f\x69\x74\x58\x6e\xc6\xac\x69\x57\xd0\x33\x31\x6c\x3a\x39\
+\xdc\x93\x9f\xf7\x68\x3b\xe5\x7f\xfc\x3f\xfe\x6f\xfe\xe8\xab\xbf\
+\xc3\x5a\x57\x5c\xa5\x9c\xe4\x54\x0c\x85\x7a\x39\x79\xea\x89\x8f\
+\xc1\x48\x7c\xa4\x9e\x78\xbe\x7c\x3c\x18\x31\x4c\x7d\x46\x28\x34\
+\xc9\xe5\xd8\x51\xab\xed\x16\xc5\xee\xa2\xc4\xc2\x6a\x14\x63\xb0\
+\x28\x5f\x8b\xbd\x93\x4a\x16\xae\xcf\x4d\x48\x97\x54\x5b\x19\xd8\
+\xba\x3a\xdf\x44\x3a\x9f\x89\xed\xb6\xc6\x59\xc7\x44\x2f\x78\xe2\
+\xb2\xa0\x2b\x27\xa7\xdd\xcc\x17\x23\xfb\xf1\x39\xf2\x45\x0b\x15\
+\xcc\x62\x3a\xa3\x1c\x10\x35\x08\xe9\x17\xa3\xf9\x17\x6e\xc5\x42\
+\xc6\xc0\xb1\xc5\x0a\xad\xae\x41\xb0\xd6\x82\x4e\x07\xbf\x58\x38\
+\x5e\x2e\x61\xec\x17\xcd\x94\xf4\x1c\xe3\x21\x99\x0d\x98\xe3\xaa\
+\xa5\x9a\xce\xb2\x68\x05\x3f\xcf\xd0\xfe\x4d\x3c\x7f\x55\x06\x6f\
+\x79\x7b\x6f\x38\xe6\xfd\x93\x57\x19\x1e\xdd\x63\x67\xb2\xc5\xd6\
+\x4e\x32\xf7\xfa\x05\x36\x20\xea\xcc\xf1\xca\x7a\xa7\x49\x72\xea\
+\x32\xda\x9f\x59\xb7\x32\xec\x4a\xfb\x56\xe5\xcc\x67\xe0\x88\xe0\
+\xea\x0d\xfa\x92\xa7\x6d\x30\x6b\x09\x97\x4c\x44\x57\x9b\x65\xd9\
+\x38\x89\x18\x28\xf9\x85\x40\x2e\x9f\xab\x06\x70\x2f\x85\x61\x3a\
+\x9c\x2b\xf4\xca\xa3\x9b\x47\x74\x5b\x16\xd7\x5b\x1e\x57\xea\x2d\
+\x26\x8b\x23\x09\x25\x76\x72\xc1\xa2\xd4\x57\x2f\xcf\x7d\xcf\xfb\
+\x5b\x11\xaf\xff\xc6\x9f\xf1\x27\xbf\xfd\x7d\x8c\x56\x46\x9e\x77\
+\xc9\x07\x23\xc6\x76\x0d\xbc\x5c\x7c\x80\x98\x60\xf6\xf2\xd9\x24\
+\xb3\x5d\x34\x7b\x8a\xd7\xcb\x40\x6e\xb5\x5d\x70\x6b\xb4\x36\x16\
+\x38\x53\x33\x5a\x6d\x17\xa7\xb6\x8a\xd5\x71\x49\xdc\x06\x7a\x4f\
+\xb4\xe4\x5a\x9a\x43\x60\x5b\xb3\xc9\x8f\x0f\x29\xf4\xb4\x40\x23\
+\xc9\xba\x12\x13\x97\x38\xb8\x9a\x8d\x83\x41\x4a\xbd\x7f\x89\x44\
+\xf5\xe7\x98\x8d\x5e\x52\xe1\x2d\x47\x0a\xba\x59\x76\xa3\xc3\x88\
+\x18\x05\x2d\x0a\x49\x02\x5d\xb4\x7d\x43\x55\x58\x3f\x15\x7b\xe8\
+\x64\xfe\x54\x02\xc1\x2f\x16\x63\xfd\x3d\xec\x02\x8e\x88\xa0\xec\
+\x17\xcb\x5c\x3a\x45\x9f\x3b\x04\x52\xcb\x22\xe9\x0b\xa1\x91\x63\
+\xe5\x85\x6e\x19\xe9\x3e\x24\x79\x64\xb2\x42\x46\x54\x6a\x76\xcc\
+\xd9\x04\x09\xc2\x27\x78\x6b\x67\x3e\x40\x9f\x6d\x35\x78\x6f\x38\
+\x06\xbe\xc2\x0b\xfc\x02\x5b\x5b\xdf\x84\x96\x08\xf4\x6b\xeb\x17\
+\x3b\xeb\x7b\xa7\x11\x8b\x49\x0f\x55\x6b\xd0\x98\x4c\x79\xe4\x3f\
+\xe4\xd1\xfd\x77\x8a\xe5\x8a\xd0\x67\xb6\xf5\xb3\xf9\xa1\xce\xa2\
+\x00\x00\x20\x00\x49\x44\x41\x54\xcf\x1a\x9b\x3f\xb4\xc9\x95\xe3\
+\x98\x38\x3c\xe0\xee\x23\x9d\x31\xe0\x72\x28\xcd\xfc\x44\x37\x6d\
+\x02\xa3\x7c\x0e\x46\x9c\xc7\xbf\x29\x2d\x06\x4a\x4e\x3b\x9f\xbf\
+\x8c\xf6\xd2\xd9\xeb\x55\x48\x12\x27\x11\x5d\x8d\x82\xf9\x88\x49\
+\x1a\x62\x9a\xf2\x78\x64\xb0\x10\x3c\x46\xc7\xa4\x7e\xda\x84\x65\
+\x18\x1f\xa7\x34\x96\x35\x29\xd4\x87\x7b\xfc\xd1\xde\x19\xfe\xd7\
+\xfe\x98\x6b\x4f\xdf\xc2\x5d\x54\xa1\x09\x8d\x51\x07\x5c\x05\x45\
+\x73\xc9\x53\x4f\x64\xe7\x36\xa2\x08\x5b\xcb\x59\x0b\x14\x46\x45\
+\x07\xae\xcc\xd0\x07\x76\x8d\x86\x16\xe3\x8f\x1d\xdc\x4c\xa1\xd5\
+\x76\x19\xa6\x3e\x8a\xa6\x30\x0e\x23\x16\xac\xc7\x64\xdd\x0d\xa0\
+\xf7\xa1\x38\xb8\xda\xae\x2e\xa7\x3e\xf4\xa0\x27\x31\xf1\x74\xe3\
+\x59\x59\xd8\x55\x6f\x0e\x3b\xc0\x75\x92\x24\x44\xd1\x5b\x24\xc9\
+\x2c\xa0\x3d\xd5\x99\x37\x4f\x31\x81\xa4\xd8\xf3\xac\xdb\x89\x64\
+\x14\x88\xc2\x79\x5f\x89\x73\x78\x19\x20\x33\x67\xff\x94\x7e\x14\
+\x51\x37\x33\xea\xa5\x1d\x7d\x81\x7b\x35\x2c\xb9\x0f\x3a\xec\x47\
+\x72\xa8\xb4\xc4\xbf\x5a\xa8\x08\x0e\x38\x8c\x24\xa4\x98\x1b\xa8\
+\xdc\x7c\x88\x77\xf7\xe7\x48\xb2\x77\x49\x86\xbf\x07\x20\x03\xf4\
+\xd1\x7e\x22\x03\x79\x6b\x27\x61\xd0\xba\x3f\xbb\xb4\x3e\x21\x23\
+\x5f\x5e\x34\x51\xb5\x06\x1d\x05\x46\x63\xbf\x22\xfa\x3f\x60\x7b\
+\xf8\x00\xff\xd1\x2e\xdb\xc3\x07\xbc\xf5\x78\x9b\x38\x3c\x60\x5d\
+\xd7\xf9\xdc\x67\x9e\xe2\xd6\x17\x7e\x94\x9f\xf8\xb1\x4d\x9e\x7b\
+\xf6\xd2\x1c\xd5\x56\x16\x5f\x55\xaa\x4c\x63\xc8\x40\xc9\x59\xc8\
+\x47\x0c\x94\x5c\x06\xe8\xf9\x00\xae\x06\xf8\x93\x20\x47\xa6\x34\
+\x59\x6c\xc6\x5c\x59\x13\x19\x7f\x67\x32\xfb\x9c\xe3\x91\xc1\x64\
+\x71\x84\x9e\x1d\x62\x5f\x3e\x65\x7c\x3c\x0b\x9e\x9b\x9b\xd7\x71\
+\x17\x37\x79\x63\x47\xe7\x95\x3f\xfa\x6d\xe8\x17\xfc\x7d\x77\x8a\
+\xa2\xb9\x24\x76\x86\xa2\xb9\x45\x07\x4f\x64\xdc\x24\x50\x8b\x2c\
+\x9a\xa1\x17\xaf\x1b\x6b\x0e\x4e\xcd\x44\xd1\x5c\x94\x68\x82\x3f\
+\x15\x18\xb9\xa5\x39\x78\x6a\x8e\x1a\xc5\xe4\x66\x9d\x8c\x1e\x81\
+\x9d\x4b\x03\x42\x89\xe5\x3d\xe7\x89\x74\x1b\x34\xe6\xd8\x89\x5a\
+\xba\x7f\x21\x80\x57\x95\x04\xbf\xb3\x39\xd3\x6a\x90\x0a\x96\xa2\
+\x80\x16\x49\x12\x8a\x4c\x5c\x95\x81\x39\x66\xb1\xe3\xc8\x2c\x3a\
+\x5c\x85\xc8\x47\xc3\x22\x0e\x23\x34\xcb\x9a\x2b\xf6\xca\x72\x6d\
+\x12\x05\xa5\x4e\x4c\x14\x86\x51\x50\x74\xc7\x66\x66\x24\x32\x53\
+\x47\xb3\x8e\x1c\x56\x86\x92\xd6\x09\xe2\x44\xb6\x8d\xe4\xe2\x46\
+\x39\x6d\x91\xe3\x14\x13\xd9\x49\xf2\x2a\xf0\x45\xf4\xd6\x97\x09\
+\xe3\x5f\xe5\x51\xc1\xc4\x5c\x5b\xd7\x79\x6f\x38\xe6\xd9\x56\x83\
+\xb7\xf6\xbf\xc2\xdb\x6f\xde\xe2\x63\x2f\xde\x9b\x0b\x74\x39\xab\
+\x95\x3f\x85\xdb\xe9\x60\x91\x11\x46\x0a\x9b\x37\xdb\x6c\xd2\xe6\
+\xf2\xa2\xc9\x4b\x67\x9f\xe2\x2c\x0f\x49\x0e\x07\x72\xed\xed\xf6\
+\xf0\x01\x93\x57\xef\xf2\xe8\xfe\x03\xae\xdd\xbc\xc1\xb5\x4f\xa9\
+\x2c\xbc\xf3\x14\xb7\x4f\x7a\xb0\x53\x71\xc3\x29\x34\x0f\xe5\xed\
+\x4c\x69\xa2\xa4\x1e\x67\x5a\x93\x85\x7c\x34\xc7\x52\x68\x0c\xe9\
+\x65\x0a\x2d\xb5\xf9\xa1\x01\x5c\xc2\x92\x6e\x33\x96\x33\x73\x92\
+\x2b\x3e\xde\x23\xa8\x2d\x62\x03\xb5\xd1\x63\x76\x9a\x97\xb8\xb2\
+\x03\x8d\x55\x0d\x8e\xc4\xc9\x78\xea\x9d\xb0\xe8\x2e\xd1\x1b\x8d\
+\x38\x7a\xbd\xcf\xdb\x1f\xf9\x16\x9f\xfc\xc9\x97\x60\x0c\x89\x9d\
+\x11\x45\x21\x4e\x31\xfe\x1e\x16\xa6\x7e\x4a\x34\xc1\x2c\x82\xda\
+\x84\x4a\x8b\x5a\x50\x72\x6b\xd4\x19\xa1\x90\x07\x53\x86\xa9\x8f\
+\x65\x37\xe8\x99\x06\x6e\xa6\x10\x14\x63\x4d\xea\xe4\x88\xac\x58\
+\x28\xa3\xeb\x16\x49\x31\x39\x5d\x35\xe3\x2e\x19\x6f\xa5\xa3\x5e\
+\xc8\xc4\x55\x6c\x5c\x4e\x76\x64\x23\x31\x0d\x9a\x24\x21\xa5\x53\
+\x4a\x13\x4d\xe4\xfd\x66\x5e\xf0\xc4\x72\x70\x31\x87\x50\x21\xb4\
+\x72\x0c\x59\xd0\x39\x18\x84\x84\x16\x72\x71\xf9\x6c\x1a\x4f\x3c\
+\x6e\x9e\xc3\xca\xa5\xdc\x32\x2e\x9c\x34\x4d\x29\xd5\x01\x8a\xac\
+\x1d\x10\x02\x2e\x81\x96\x60\x39\x3a\x61\x98\x14\x5d\xc0\x59\x6b\
+\x58\x37\x33\x32\x9a\xd4\x8a\xe0\x1b\xb4\x5e\x01\xbe\x48\x32\xfc\
+\x3d\xac\xac\xce\xb5\x75\x9d\x47\xfb\x02\xff\x3e\xbb\x2e\x32\xb1\
+\x45\x5d\x06\xf0\xf9\xdb\x33\x5d\x85\xd6\xca\x2d\x08\x1b\xf4\x95\
+\x00\xc2\x08\x6f\xff\xa8\x70\xfb\x11\x96\xfb\xc9\x24\x81\xe5\x7d\
+\x7e\x64\xfd\x69\xec\x8f\x76\xc9\xc6\xbf\xc4\x07\xdf\x7e\xc8\xdf\
+\xfe\xcd\x5f\xb1\xb7\x1f\xf2\x77\xbf\xe1\xb0\x6a\xbc\x22\xe9\xb6\
+\x83\x05\xc1\x54\xe8\x41\x1d\x37\x8f\x28\x4b\x15\x25\xf5\xc8\x35\
+\xf7\x42\x00\x0b\x38\xd1\xa2\xa5\xc2\x30\x1b\xa1\x07\x36\x0d\xe7\
+\x43\x8a\x3f\xb7\x03\x44\xc4\xa3\x88\xc3\x0a\xc4\x5a\x75\x14\xf2\
+\xe9\x29\x41\x7f\x91\x40\x69\xa2\x37\xcb\xe0\x4e\x4b\x89\xb8\xa0\
+\xfd\xbc\x13\x16\x9b\x37\x78\x5b\x39\xa0\x7b\xf0\x88\x6b\x0f\x6e\
+\xe1\x5c\x5b\x64\x1c\x8a\x55\xc0\x5e\x34\x9b\x7a\x51\x08\xc8\x4d\
+\x9b\x28\x0a\x30\x4d\x8b\x24\x50\x49\xec\x0c\x93\xa0\xa0\xcf\x54\
+\x02\xdb\xa4\x1d\x58\xf4\x19\xd1\xd2\x1c\x46\x41\x97\x66\x31\xf8\
+\x59\x76\xf7\xec\x69\x97\x32\xa3\xc9\xac\xeb\x4d\xb1\xcf\x65\xe8\
+\x71\x00\x49\xd6\x65\xb4\xbf\x3b\x87\x89\xab\xd9\xb8\x2a\xc5\xac\
+\x4e\x8b\xb8\x99\x4f\x2f\xd3\x68\x35\xad\xc2\x64\xbb\x12\xc0\x31\
+\x16\xe1\x79\xdd\xb0\x99\x12\x87\x0a\x56\xa8\x30\x31\x85\x54\x4f\
+\xc3\xfa\x7b\x2b\xed\xf2\xc4\xc8\x4c\x45\x32\x1e\x73\xf2\x4e\x20\
+\xed\x98\x44\x1d\xbd\xe8\xda\x95\x8d\x13\xf1\x7d\xc7\x56\x46\xcd\
+\x74\x51\x69\x52\x37\x67\x99\xb4\x3d\xbc\xc9\xee\xc1\x26\x7a\xeb\
+\xcb\x73\x50\xa1\xcc\xb6\x96\x2f\xde\xbd\xb7\xdf\xbc\x45\xe8\x4c\
+\x2e\xfc\x5e\x35\xf5\xbf\xc1\x9a\x5e\xe2\xc4\x3f\x65\xb4\xd7\x67\
+\x74\x16\xb2\xb5\x1f\xf0\x68\x7b\x97\xec\xf6\x6d\x1e\x6d\x6d\x13\
+\xee\xff\x2d\xea\x96\xc6\xde\xfd\x3f\x67\xe1\x83\xbf\xe3\x73\x37\
+\x1e\xf3\x33\xff\xf2\x13\xfc\xea\x6f\xfd\x77\xfc\x4f\xff\xe6\x7f\
+\xe7\x67\x7f\xea\xd3\x18\xd6\x1a\x77\x1f\xe9\xdc\x7d\xa4\xe3\x6f\
+\x9f\x48\xa1\xba\xa7\x98\x73\x81\xd8\xce\x67\xae\x8f\xe7\xe1\x03\
+\x40\x4b\x6d\x5e\xa0\xdc\x4a\x96\x02\xb7\x33\x9b\x6a\xfe\x30\xf1\
+\xcd\xf4\x94\xb3\xb6\x2b\x70\xf1\x13\x6e\xca\x66\x4b\x4c\x44\xe7\
+\x6b\xd4\x4f\x9b\xec\xe5\x6d\xc2\xa2\x59\x55\xf2\xc6\x4a\x34\x41\
+\x21\xc0\xc9\x1a\x58\xa6\x58\x38\x5f\x72\xc9\x7a\xa0\x4a\xfe\xb7\
+\xec\xf6\x0d\xe8\xa3\xb4\x9b\x45\x21\xd7\xc7\x60\x71\xd6\xd5\x2b\
+\x68\xb9\xf3\x1d\xbd\xf3\x10\x23\x48\xc5\xd8\xbe\x36\xec\xd3\x5c\
+\xdf\x98\xe3\x89\xab\x85\x5d\x75\xc6\xae\x4a\xd1\x8d\x5c\x85\x8e\
+\x2a\x6c\x00\xc6\xea\x14\xed\x17\xff\xeb\x2f\xff\x8a\x0e\xa8\x89\
+\x82\x9e\x24\xd4\x0c\x71\x22\xd5\x12\x05\x3d\x0a\xd1\x93\x04\xc5\
+\xd5\xd1\x0c\xd0\x93\x18\x8d\x84\x29\x86\xa4\xe5\x94\x22\x1b\xab\
+\x18\xe4\x24\x92\xaa\x8b\xb1\xa8\x25\xb3\xcf\x51\x99\x71\xc5\x96\
+\xa1\x93\x62\x54\x8c\xe0\x22\x62\x55\xc1\x30\x74\x30\x4d\x6c\x1d\
+\x14\xea\xd4\x4d\x9d\x20\xb3\xc8\xb5\x3a\x5e\x36\xe2\x71\xfe\xef\
+\xb8\xba\x92\xe0\x0d\x3b\x1c\xbe\xb1\x8d\x72\xa9\x18\x25\xf2\x32\
+\x3a\x4d\x95\xc3\x3c\xc4\x98\xea\x2c\xaf\xf6\x30\xa6\xfa\x1c\x66\
+\xfe\xcc\x8d\xcf\xd3\x5d\x79\x89\xae\xbd\x44\xbd\x6e\x50\x37\x14\
+\xb2\x85\x36\x76\xb6\xc6\x7e\xf2\x01\x77\xb6\x15\x26\x83\x6d\xa6\
+\x6a\x9d\xfe\x60\x80\x91\x65\xec\xbd\x99\xf3\xc6\x5f\xff\x21\x6a\
+\xf8\x3a\x6b\xa9\x4f\x67\xc1\xe3\xb3\x3f\xb4\xc6\x17\xfe\xe9\x97\
+\x59\x79\xee\x29\x06\x93\x6d\x1e\xef\xe8\x4c\xa3\x13\xe2\x72\xb7\
+\x71\x26\x7e\x66\x3a\x56\x09\xf5\x31\x2d\xb5\xc9\xd8\x8f\xa9\xd5\
+\x04\x3e\x48\xfd\x84\x7a\x2d\xc6\xf7\x35\xac\x9a\x2f\x77\xb4\x69\
+\x0c\xd1\xf5\x36\x75\x37\xa1\x6b\x59\x84\xb9\x8e\x55\xc9\x44\xd9\
+\x24\x91\x1f\x43\x2f\xa1\x55\xac\x9f\x5d\x4d\x14\x8c\xc6\x21\x8e\
+\xd9\x64\xd8\xee\xa3\x9b\x8b\xf8\x9e\x4a\xcf\x88\x51\xce\x7c\x2c\
+\x25\xe1\x99\x4f\xac\xb0\x70\xe3\x32\x2d\xd7\x66\xd5\x5d\xa6\x96\
+\xe5\xc4\x9a\x82\x12\x65\xc5\x32\x4a\xa8\xe5\x35\xd4\x58\xa1\x5e\
+\xc1\xec\xbe\x3a\xa6\x96\x8b\x00\xcc\x8c\x29\x09\x31\x6a\xdc\x25\
+\x1f\x3c\xa6\xd6\x71\x38\xeb\xeb\x9c\xa9\x27\xb4\x8c\x04\xd7\x76\
+\x19\x4d\x5b\x44\xe9\x09\x79\x6a\x52\xaf\x6b\x04\xe9\x04\x63\x9c\
+\x41\x79\x5f\x15\xef\x8d\xa1\xe6\xa4\xa9\x81\x5f\x5f\xe0\xcd\x6f\
+\x7e\x93\xe1\xe8\x84\x49\xbd\xc6\xc2\xd9\x19\x43\xd3\xc2\xd5\x14\
+\xf2\xec\x21\x6b\xaa\xcb\xc6\x33\x9b\xb4\xad\x0e\x51\xae\x12\xe5\
+\x85\x47\x45\x9c\xc9\x8c\xfc\x6b\xff\xe7\x1f\xa1\x0b\x6b\x53\x87\
+\x04\x5f\x98\xc1\x61\x61\x11\xcc\x74\x0b\xa6\x45\x1c\xce\xb2\x68\
+\x35\xb3\x96\xc1\x1a\x57\x38\xd7\x27\x57\xe6\xd6\xdc\x72\x9b\xb0\
+\x92\xad\x6b\xa1\x32\x6f\x08\x57\xb9\x1d\x4c\x32\xd6\xcc\x33\x0e\
+\x22\x91\x05\x1a\x87\x75\x0e\x82\xeb\x5c\xbd\xa2\xf3\xe7\xcf\x7d\
+\x89\x65\x7e\x67\xae\x80\x7b\x76\xbd\xc1\x23\x3f\x99\x7b\xee\xda\
+\xba\xce\x4f\x7e\xfc\x0b\x2c\x2d\xff\x27\x5c\xaa\x5f\x2d\x76\x74\
+\x44\xf2\x0a\xd0\x6f\x4c\x66\x45\xdd\x51\x4a\xef\xf6\xdb\x2c\x6f\
+\x74\x08\xba\x4b\x40\x1f\xbb\xb6\xce\x07\xbf\xb7\xc7\xdf\xd5\xff\
+\x3f\xae\x6f\xbe\x0e\xc0\x47\x3e\xb3\xc6\x27\xd7\x6e\xb1\xf1\x8f\
+\x3f\xc3\x6b\xee\x21\xb7\x4f\x74\xde\x7a\x73\x0b\xc3\x9f\xce\xb1\
+\x0f\x25\xe6\x05\x9b\xb1\x1f\x93\xd8\x21\x2d\xa7\x49\x4a\x8b\xa6\
+\x33\x94\x99\x57\x64\xab\x56\xf1\xae\x74\x8a\x63\xff\x43\xdf\xcf\
+\x72\xa2\xba\xf4\xb5\x98\x36\x2f\x09\xaa\xad\x07\x70\x0f\x75\x22\
+\x0c\x59\x0e\xfd\x14\x9a\xb0\xdc\x8c\x59\x6e\x5f\xe6\xc6\x66\xca\
+\x38\x99\x5c\xd0\xc7\x34\xe2\x0c\xb4\xf3\x97\xed\x1c\x37\x6b\xe0\
+\xa9\xb9\x94\xbd\x8a\x0c\xdd\x07\x57\x11\x8d\x92\xc6\x18\xb5\x1f\
+\x33\xb6\x6c\x8c\x54\xa3\x49\x0f\x34\x87\x51\x01\x21\x12\x54\x90\
+\xf3\x95\x36\x78\xa1\xc8\xca\xde\x94\xc6\xba\x45\x6f\x5f\x70\xd8\
+\x49\xfb\x13\xac\xd6\x1e\xb0\xdd\xee\x4a\x38\xa1\xa8\xd7\x39\xcc\
+\x61\xc2\x31\x70\x4d\xb2\x1a\x1d\x35\x95\x7c\x71\x3f\x2b\xd6\x1d\
+\xa4\x1d\x13\xc2\x14\xbd\xf0\xee\x4d\xa2\x10\xaf\xd2\xc9\xd1\x41\
+\x42\x0c\x2b\x8c\x88\x2d\xeb\x42\x73\xc4\xac\x48\xfa\xce\x5f\x00\
+\x8d\x8a\xb2\x38\x0b\x15\x72\x2b\x90\x01\x3f\xb3\x69\x61\x7e\x2b\
+\x53\xc9\x48\x98\x11\x07\x91\xc9\x42\x9e\x31\x6d\x5d\x63\xaf\xbf\
+\xca\x20\xfb\x0a\xbb\xf7\xbf\xc4\xf2\xc2\xd7\xe7\x0a\xb8\xf2\x76\
+\x6d\x5d\xa7\x15\xfc\xfc\x5c\x97\xaf\x96\x3f\xc5\x7a\x7d\x79\x26\
+\x12\x2a\x30\x77\x33\xea\x73\x82\xc9\x60\xef\x69\xe0\x51\x65\x6a\
+\xb8\x4f\x3c\x8a\x88\x2e\xf5\x78\x6a\xba\xce\x71\xba\xc8\x71\x00\
+\x3b\x77\xf7\x50\x6a\x8b\xfc\x7e\xff\x80\x1f\x68\x6f\xd3\xe8\xde\
+\xa2\xd7\x9a\x70\x39\x5c\x27\x5e\x8d\x78\xf7\xf0\x08\x86\xa2\x62\
+\x6e\x34\x0d\x81\xd7\xba\xcb\x6c\x5c\xb6\x8a\x89\x66\x97\x2c\x39\
+\xa6\xa5\xb5\x80\xd6\x6c\xbe\xc7\x2d\x27\x34\x2c\x7a\x59\x9f\x5e\
+\x56\xdc\x1f\x86\xe0\x96\xcf\x9b\x52\xbd\x56\x8a\xee\x71\x2c\x76\
+\x26\x43\xae\xec\xc0\x6e\x6e\x90\x4f\x4f\x39\xf4\x73\x8e\x07\x42\
+\x73\xac\x3a\x1a\xbd\x6c\x84\xa2\x5e\xe7\xd9\x4f\x6a\xb8\x8b\x9f\
+\x20\x88\x54\xc2\x48\xc1\xcd\x14\xbc\x22\x38\x7d\x03\xdc\xac\x0c\
+\xdc\x2e\xd0\x17\x81\x1b\x08\xad\x76\x29\xa4\x8f\x0a\xd5\x9b\xa2\
+\xb9\x15\xe8\x98\x57\xc4\x43\x8a\xa4\xe6\x02\xb7\x81\x4e\x4e\x80\
+\x8d\x4d\x3a\x5f\xd4\xb9\x35\xe1\x0c\xd4\x12\x05\x7b\x4b\xbf\xc7\
+\xe1\x14\x36\x07\x3d\xb6\xdb\x5d\x09\x2d\x56\x95\x84\x3a\xcb\x73\
+\xf8\xba\xaa\x88\x93\x3c\xb1\xc4\xc3\x61\xb9\xdb\xcd\x22\x26\xc0\
+\x28\xd4\xfe\xfd\x0a\xbd\x16\x5a\x79\x91\x27\xac\x8b\x58\xf7\x5c\
+\xe6\x45\x1a\x70\xcf\xa8\x38\xd5\xca\x49\x8b\x6c\x3f\x1b\x37\x14\
+\x5b\x4a\xcb\x5d\xce\x16\x30\x54\x72\x3a\x39\x1c\x44\x26\x6d\xa3\
+\x41\x3f\xde\x23\xed\x9f\xd1\x79\x76\x8b\x6f\xfe\xfb\x5b\xc0\x7d\
+\xd8\xb9\xf5\xa1\x3f\xff\x6a\x7d\x13\x96\xf7\x99\x2a\x2f\x73\xb0\
+\x7d\x9d\xcb\x9b\x2f\x17\xeb\xc8\x84\x6b\x8c\x19\xaa\x58\x56\x46\
+\x88\x45\x3b\xe8\xd3\xd2\xef\xd1\x2b\xc4\xef\xdd\xd6\xec\x77\x0b\
+\x8e\x2c\x76\xd4\x90\x5e\x76\x57\x9c\x14\x2b\x21\xad\x74\x91\xe5\
+\xe9\x1e\xaf\xeb\x21\xda\xc0\xe0\x8a\xb9\xcf\x6e\xb4\x3e\x87\x83\
+\xc7\xea\x94\x06\x06\x5a\x73\x80\x9b\xb7\x00\x4b\x4e\x63\x64\xfe\
+\x06\xe4\x23\x32\xa5\x89\x8a\x06\x6e\x5f\x06\xf0\xe9\xc8\x60\xb1\
+\x09\xbd\x61\x48\xcf\x35\xc1\x0d\x81\x0e\xbd\x61\xbf\xb8\x2f\xfc\
+\x28\x4a\xac\xbc\x73\x10\x62\x34\x4d\x0e\xfd\x81\xb4\xae\x3a\x1d\
+\x19\xa8\xce\xa8\xe0\x89\xfa\xe0\xc1\x83\xef\x7f\x8b\xef\xbf\x96\
+\xb3\xfe\xdc\x2a\xa1\x16\xe1\x45\x0a\x0e\x2e\x69\x60\x11\xdb\x01\
+\x35\xb3\x26\x0b\xd2\x5e\x69\x09\x30\x84\x86\x65\x62\x4e\x8b\xeb\
+\xa4\x9a\x42\xa4\xc9\x29\x0e\x80\x78\x1c\xa2\x07\x11\x8d\xc5\x18\
+\xa8\x31\xa2\x4b\x93\x1e\x8a\xe6\x62\x07\x82\x6e\x0b\x52\xe4\x5e\
+\xbb\x32\x0b\xe3\xd6\x04\xbb\x30\xec\x33\x5c\xd0\x61\x4f\x04\x6d\
+\x99\x89\x6b\x8f\x4f\x99\x5e\x5a\x64\xd8\xaa\xcb\x4c\x0c\x42\x04\
+\xe4\x5d\x18\x58\x05\x3d\x2e\x38\x62\x2a\x05\x9d\x4b\xe1\xda\x13\
+\x2a\xd2\x97\xb8\xea\x00\x64\x86\x11\x69\x31\xce\x54\xce\xdc\x95\
+\xa3\x97\xd5\xcc\x6b\x5e\x10\xd2\x17\x99\xbb\x42\xbd\x95\x59\x58\
+\x2c\x83\x34\x2f\x64\xe2\x49\x98\xd1\xa1\xc5\x59\x32\xa0\x71\x78\
+\x51\xee\x57\x7a\x50\x7c\xec\xc5\x7b\xb3\xe6\xc6\xf2\x3e\xba\xfa\
+\x1c\x64\x70\xf5\x0a\xe8\xfb\xc7\xec\x2c\x42\x27\x6b\x62\x60\x13\
+\x11\x11\x45\x30\x3a\x13\xfb\x9a\xcb\xc2\x62\xb9\x0d\xc7\x03\x53\
+\x8e\xfe\xe0\x85\xf4\xdc\x70\x2e\xa8\x03\xee\x32\x5c\x09\x79\xf6\
+\xbe\xc1\x6e\xbe\x8b\xb8\x0e\xec\x72\xa4\x39\x28\x99\x37\x33\x27\
+\x18\x29\x33\xff\x5b\x99\x41\x2d\x7a\x4e\xa9\x81\x1d\x81\x27\x5a\
+\xc9\xbd\x61\x48\x8f\x10\xd5\x0d\x39\x1d\x35\x51\xdd\x10\xbc\x7e\
+\x91\xa9\xfb\x32\x53\x0b\xa8\xd1\xa7\x97\xcd\x8a\xbe\xe3\x81\x08\
+\xd4\x4c\x69\x16\xe3\xff\x5a\x45\x38\xdf\xa1\xdb\x8a\xd8\x39\x08\
+\xf9\xf3\xbf\xf9\x36\x3f\x6a\x5e\xe5\xfa\x3f\x5a\x27\x39\x55\x21\
+\x4c\x50\xcc\x84\x1a\x35\x99\x60\xb2\x50\x41\x35\x2d\xb2\x28\xa4\
+\x99\x29\xa4\xc0\x59\x18\xd0\xb0\x4c\xb4\xb3\x29\x69\x23\x23\xee\
+\x87\x0c\x06\x43\x74\xdb\x22\x09\x42\x74\x3b\x11\x41\xab\x19\x40\
+\x4f\x76\xf8\x02\x3b\xc7\xf6\xa6\x42\x5e\x6f\xe7\xd8\x81\x22\x8a\
+\x3f\xb7\x2e\xf6\xdc\xad\x2b\x0c\x4e\x12\x5a\x67\x09\x3b\xa7\x1e\
+\x87\x8b\xae\xcc\xc4\xab\x97\x16\x39\x9c\x66\x7c\x62\x28\x32\x71\
+\xd9\xae\xee\x67\x1a\x64\x33\x83\x96\x8e\x9a\x8a\x41\x51\xbd\x17\
+\x93\x48\x6d\xc4\x19\x16\x0b\xf8\x76\x42\xde\x13\x15\xb4\x62\xb7\
+\x30\x80\x04\xd0\x7b\x3a\xd8\x7d\x30\xad\x8a\x34\x33\x42\x43\x41\
+\xa1\x47\x8e\x2d\x7c\x2b\xe4\x88\x87\x78\x2d\xaa\x9c\x24\x5a\xa8\
+\x88\x0d\x9e\xf9\x03\x31\xbb\x67\xad\x41\xa8\x14\x1c\x74\x3e\x6f\
+\xce\x9d\x2e\xa0\xe1\x61\x53\xc3\xd4\x23\xf4\xd6\x97\xf9\xa8\xf1\
+\x87\xbc\xfb\x5e\x4c\x76\x6b\x85\x5b\x9f\xbb\x83\xe5\xd7\x65\x20\
+\x03\x12\x4a\x04\xf9\x1f\xf0\xb5\xdb\xaf\x70\x6d\x5d\xe7\x36\xd0\
+\x7a\xf8\xf3\x5c\xbd\xa2\x73\xeb\xca\x75\xe2\xa8\x83\x12\x29\x1c\
+\x1f\x1c\xb2\x35\xd9\xa6\x3f\xd1\x67\x01\x51\x09\x96\x7e\x43\x81\
+\x0c\xd4\xd1\x80\x56\xbb\x45\x3f\x53\xe8\xa8\x39\xc1\x3d\x8b\xbf\
+\x56\x4c\x5c\x67\xa6\x9e\xf3\xfd\x90\x3c\xc9\x19\xfb\x31\x8d\xac\
+\x86\xd6\x14\x13\x25\xc3\x74\x48\xcb\x6b\x51\xb2\x6c\xc2\x33\xad\
+\xf4\x93\x80\x5e\x16\x16\x41\xda\x11\x01\xab\xcc\x9a\x1c\xaa\x37\
+\x2a\x68\xb6\xd2\x87\xa2\x2f\x7f\xb7\xed\x91\xd0\x1a\x7b\x8a\x09\
+\x0a\xb8\x8e\x46\x5c\x06\xa4\x53\x99\x84\x2e\x9d\x84\x0e\x42\xee\
+\xbe\xf2\x75\x5e\xfc\xe4\x2f\xf2\xec\xb3\x26\x7b\x87\x42\x28\x5f\
+\x62\x5d\x5f\x1d\x93\x9b\xf6\x1c\xb4\xd3\x81\xba\x69\x15\xd0\xc3\
+\x42\x07\x14\x26\xb4\x25\xdd\x53\xa3\xd3\xe9\x08\x3e\xd9\x9b\xca\
+\x00\x1e\xa1\x08\x28\x61\xe7\x42\xce\x99\x4e\x44\x16\x4e\x27\x82\
+\xb9\xb0\x61\x95\x7a\x11\x55\xf3\x98\x18\xa0\xf6\xf8\x14\xda\x5d\
+\x69\xb2\xdd\x51\x53\x19\xc8\xe5\xfd\xea\x94\x88\xf6\x5f\xfc\xf4\
+\x8f\xfc\x4a\x42\x88\x81\x4d\x42\x48\x42\x08\xf1\x04\x8b\x05\x01\
+\x29\x8c\x0c\x35\xd0\x89\xe3\x3e\x06\x36\xaa\x91\xe1\x27\x09\xd3\
+\x24\xa1\x96\x24\x78\x7a\x4c\x8e\x41\x14\x25\x4c\xf4\x98\x29\x31\
+\x71\x94\x00\x06\x89\xfc\x35\x21\x4b\x14\xb2\x44\x41\xb1\x72\x32\
+\x0c\xe2\xe4\x4d\x3e\xd8\xff\x36\x0b\xcd\x65\x74\xe3\x92\x1c\x63\
+\xb2\x30\x88\x8d\x9c\x3a\x53\xb4\x54\xc1\xa6\x46\x6a\x66\x4c\x26\
+\x3e\x63\xe5\x1b\xdc\x7b\xfb\x98\x93\x93\x4c\xec\x55\xde\xb9\x44\
+\xf3\xd6\x21\x9f\xfb\xd8\x98\xab\xfa\xbf\xe0\xa5\xa7\x7f\x90\xcd\
+\xa7\x9f\x26\x0d\x56\x89\xf9\x80\x7b\x47\x5b\x0c\xbc\x8c\xc3\x3c\
+\x64\x2f\x7b\x83\x3b\xfd\xef\xb0\xa8\x83\x37\x9e\xd2\x4e\x1b\x0c\
+\xec\x2d\xfa\xdf\x07\x6d\x1a\x31\x6d\xa7\xc4\x6c\x31\xad\x5f\x47\
+\x09\x85\x88\x3d\x19\x9b\xb4\xea\x09\x66\x6c\xc2\x14\xa6\xd1\x90\
+\x49\x34\x21\x74\x2d\xd2\x30\x91\x8f\x83\xc8\x44\x53\x75\xb2\x2c\
+\x21\x9e\x66\xc4\x4a\x4a\xbd\x36\x2b\x77\x4d\xd5\x24\xac\x25\x58\
+\x8a\x81\xd1\x34\x71\x4c\xa8\x4f\x15\xc2\x5a\x42\x57\xb5\x08\x73\
+\xb7\xc8\xb8\x1d\x16\xcc\x29\xe1\x28\x41\x71\x6d\xb2\xb8\x86\x52\
+\x1b\x02\x1d\xfc\xe9\x84\xfa\x24\xa1\x6f\x4c\x48\xc6\x85\xb6\x42\
+\xb1\xa9\xa1\x11\xda\x01\xc9\x38\x27\xd7\x03\x42\xc5\xc0\x3a\x57\
+\x2a\x8b\xe9\x14\x97\xb7\xb6\x1f\x92\x3c\x7a\xc4\xf2\xd3\x4b\x58\
+\x96\x42\x10\x66\xc4\x7e\xc8\xd4\xc8\x69\xc4\x19\x5a\xc3\xc0\x0c\
+\xc7\xd4\x95\x3a\x53\x45\x4c\x87\x5b\x53\xc1\x17\x5b\x53\x15\xcd\
+\xca\x31\xb3\x4b\x58\x16\x58\x96\x85\x65\x59\x34\xc9\x31\x62\x85\
+\xc0\xce\x71\xe2\x99\xd6\xc2\x88\x15\x62\x03\x8c\x71\x46\x6c\x40\
+\x9c\xa7\xd8\x81\x78\x0e\x6c\x54\x4b\x25\x1f\x2b\xdc\x79\xff\xfb\
+\x78\x8f\xdf\x66\x52\xaf\xb1\x39\xe8\x31\x34\x2d\x86\xa6\xc5\x8a\
+\xbe\xc5\xd2\xd4\x61\xe3\x99\x4d\x14\x12\xf2\x22\x60\xa3\x5c\xa5\
+\xa3\xa6\x44\xb9\x4a\x96\x25\xfc\xd6\x57\xfe\x10\xd5\x62\x01\xd7\
+\x6e\x11\xd9\x09\xae\xdd\x62\x59\xe9\xe0\xda\x2d\x74\x3b\x41\xb7\
+\x13\xc1\x5c\x74\x0d\xc2\x5c\x7c\x0e\xa6\x45\x6e\xe6\x58\x1d\x13\
+\xc5\xcc\x31\x8a\x49\x00\xdd\xb4\x30\xb0\x31\xb0\xd1\xcd\x99\xfa\
+\x21\x89\x42\x4c\xc0\x8c\x42\xcc\x28\x44\x09\xed\x19\x9e\x4e\x5f\
+\xe3\xde\xce\xc3\x62\x0a\x44\x29\x67\x92\x69\x84\x2a\x2a\x4d\x6c\
+\x12\xd2\xa2\x7d\xed\x98\x1d\xf6\x5f\xbf\xc9\xfe\xc1\x4c\x20\x74\
+\xeb\x73\x77\x24\x0b\xf1\xc2\xa7\x9e\xe1\xd6\xe6\x3f\xe1\x52\xfd\
+\x2a\x97\xd5\x29\x07\xdb\xd7\xe7\xba\x75\x96\x5f\xc7\xf2\xeb\x7c\
+\xed\xad\x57\xf8\xc3\xdb\xff\x96\xbb\xe9\x9f\xb2\xb5\x93\x30\x3e\
+\xf5\x78\x3c\x78\xcc\xe9\xe1\xeb\xb4\x94\x17\x58\xab\x59\x2c\xb7\
+\x3b\xe4\x0b\x1b\x73\xe3\x45\xa5\x26\x42\xd5\x97\xe9\x8c\x73\x94\
+\xa6\x42\x4b\x6b\x15\x45\x1a\x9c\xa4\x21\x03\x25\x27\x76\x75\x9a\
+\xce\x6c\xec\xa0\x7c\xfd\x82\x92\xae\x69\xce\x15\x6c\x42\x1f\xd1\
+\xa7\x37\x0c\xe5\x7d\x31\xf2\xd4\x14\xe3\xfa\x45\xd6\xed\x8c\x73\
+\xc9\x4b\xcf\xae\x3e\xae\x3c\xb6\xfd\xf3\x56\x58\x45\x07\xb1\x3b\
+\xa5\xdb\xbc\xc1\xab\x8f\x8e\xf8\xcb\x5f\xfd\x0e\x4d\x7f\x97\x56\
+\xc3\x43\x35\x81\x48\xc3\x37\x1c\xa2\xc1\x94\xb1\xa1\x12\xa8\xa7\
+\xb8\x99\x82\xe6\x09\x51\x8f\xe6\x8d\x69\x92\x17\x8f\xfb\x52\xe9\
+\x56\xc2\x06\x79\xe5\xb4\x73\x9a\xe4\x0c\x0b\xab\x5a\x5b\xab\xcb\
+\x6c\x6c\x07\x8a\xe4\x8b\xed\x20\x84\x20\x61\x90\xcc\xff\x9e\xdb\
+\xed\x2e\x4a\x20\xda\xcf\x47\x89\x18\x78\x9d\x70\x4c\xab\xf4\x7e\
+\xf6\xa6\xe8\xba\x45\x3f\xd3\xe6\x70\xb1\xaa\xdb\x09\x3e\x60\x06\
+\xe2\x1f\xde\xb3\xc4\x6e\x0d\x1f\xc4\x0a\x00\x53\x00\x7a\xbb\x31\
+\x73\xc1\xb4\x2d\x21\xa0\x4f\x2c\x6b\x0e\xc5\x1a\x56\x8e\x61\xe5\
+\x98\xc5\xe5\xc8\xb4\x4c\x9c\x4e\x47\xf8\xfe\x9a\x16\xe0\xa2\x12\
+\x12\x84\x21\x77\xf3\xff\x55\xd0\x43\xca\x5d\xe2\xfc\xa0\x70\xf0\
+\x11\x05\x9e\x6e\xe6\x4c\xa3\x79\x83\xef\x99\xf1\x21\x64\xb7\x56\
+\xf8\xd8\x8b\xf7\x64\x60\x86\xce\x84\xdb\xdf\x79\x9f\xa4\x7f\x80\
+\xe7\x05\x6c\xed\x07\x24\xc3\xdf\xbb\x80\xa1\xab\x0d\x90\xaf\xbd\
+\xf5\x0a\xca\xde\x1b\x38\xcf\x37\xb8\xfe\xf2\x35\x3e\x7e\xeb\x9f\
+\x61\xac\xcc\x3b\xb2\x8b\x4b\x79\x87\x7e\x43\xa1\xad\x37\x51\xf5\
+\x65\x31\xc8\xa9\x98\x74\xd4\x1c\x4f\x99\x0d\x78\xb6\x73\x45\x52\
+\x6b\x23\xdf\x96\xcd\x8b\x52\x99\x86\x27\xa0\x83\xf4\x10\x2e\x9c\
+\xe0\x05\xb6\xed\xc8\x21\xd0\x4c\x69\xa2\xe6\x23\x7a\x03\x71\xe2\
+\xa8\xf9\x88\x38\x11\x3f\xb3\x2a\xcb\x1c\x33\x65\xcc\x14\x35\x1f\
+\x49\x51\x7e\xf5\xb9\x6a\x20\x1b\xad\xde\x9c\x1b\xfd\x9f\xbf\xfb\
+\x36\xbf\xf3\x17\xc7\x4c\xb3\x45\xda\xed\x36\x0d\x2d\x46\x89\x26\
+\xe4\x66\x9d\x1c\x1b\x3b\x5b\xc4\x57\xc7\x28\x9a\x2b\x8f\x23\x14\
+\x52\xb7\x41\x93\x99\xfa\x6d\x54\x42\xc5\x73\xc3\xa7\x33\x9e\x6e\
+\x3a\xd7\xfc\x28\x1b\x22\x81\x7d\x8e\xe2\x5b\x9c\xb1\x1d\x57\xa6\
+\x16\x87\xd3\x4c\x52\x6d\x25\x3b\x51\x16\x86\x25\x4b\x51\x1e\xc7\
+\xea\x14\xd5\x9f\xfb\x25\x74\x12\x7c\x72\x33\x27\xd4\x45\x00\xf8\
+\x51\x48\x82\x2f\x46\x7e\x0a\x86\x22\x0e\x15\x6a\x85\x68\xc7\x8f\
+\x42\x92\xa2\xfb\x53\x32\x1c\x51\x18\x11\x59\xa6\x38\x16\x18\xcb\
+\x04\x22\x33\x11\x8f\xf5\x37\x61\xbf\x25\xb3\x71\x9c\x6c\x31\xee\
+\x4f\xe4\x40\x7d\x52\x14\x7d\x7e\xb9\xfe\xd4\x6e\xa0\x16\x93\xd5\
+\xed\xa5\xcb\x7c\xfe\x7a\x3e\x17\x94\x65\xa7\xee\xfb\xde\x57\x85\
+\xca\x6d\xb2\xcd\x9d\x6c\xcc\x9d\x6c\x4c\xe8\x4c\xe4\xeb\xe5\xb1\
+\xfc\xba\x37\x1b\x62\x82\xe3\xea\x15\x9d\x5b\x2f\x7d\x94\xab\x1f\
+\x79\x99\xeb\x2f\x5f\x63\xf3\x4a\x87\xfe\xd9\x90\x87\xc3\x1e\xbb\
+\x7b\x8f\xd1\x83\x3a\x63\xa6\x85\x7d\x54\x73\x6e\xa0\xb3\x1a\x58\
+\x4f\x52\xa8\xa5\xb4\x64\xa0\xe3\x09\xe6\xe1\x78\xd0\xe7\xd4\x3b\
+\xe1\x74\x64\x14\xde\x14\x21\x78\x30\x48\x46\x0c\x92\x11\x0f\xb3\
+\xfc\xc2\x15\xa0\xbc\x2a\x9c\x0f\xe6\xf3\x8f\xdd\x3c\x92\xc1\x5f\
+\x1a\x15\x1e\x0f\x90\x8b\x69\xc8\xd7\x20\x5f\xe3\x4f\xff\xe0\x2f\
+\xf9\xf6\x6f\xfc\x11\xb6\x3f\xa4\xbe\x64\xe1\xe8\xc7\x4c\x10\xb3\
+\x86\x83\xa4\x89\x93\x35\xf0\xd5\x31\x4e\xd6\x98\x1b\xfc\x2c\xb3\
+\xac\xd0\x2f\xcc\xe4\x9a\xe5\xe3\x11\x0a\x0b\x43\x45\x66\x66\x91\
+\x79\x95\x0b\x5d\xbb\xb9\x04\x55\x14\xd6\xe3\x53\x4f\x66\xe3\xa3\
+\xc1\xae\x7c\x7d\x58\x9a\x2f\x16\x27\x85\xcc\xc2\xde\x54\x2c\x63\
+\x0c\xc6\x88\x2c\x6b\x27\x24\x81\x4e\x30\x86\xa6\x69\x63\x14\x57\
+\xe2\x50\xaf\xe3\xea\x2a\x5e\x92\x15\x60\xdf\x2d\xce\x79\x11\xbc\
+\x66\xa0\x13\xd9\x09\x49\x14\xe2\x98\x56\x31\x32\x1f\xcd\xfc\xa5\
+\x8a\x63\x64\x99\x85\xdc\x33\xb8\xf0\x47\x6c\x1d\x64\x3c\xbb\x19\
+\x10\x16\xd6\x54\x94\x36\x01\x66\x0e\x4a\x80\xe7\x5b\x50\x04\xf1\
+\xe6\x95\x0e\x3f\xf2\x85\x7f\x0e\xc0\x77\x1f\xff\xb7\xf4\xf7\xaf\
+\xd2\x79\x76\x0b\x02\x38\xd8\xbe\xce\xd5\xba\x28\xa8\xfc\x37\x5f\
+\xc2\x79\xf1\xdb\x32\x70\xcb\xe0\x2d\xb3\x77\xf9\x58\xd9\x7b\x03\
+\xae\xbc\xc4\xfd\xad\xdb\x5c\xcf\xea\xa8\xd7\x5f\xe0\xea\x15\x9d\
+\x1f\xf9\xd1\x7f\xcc\x2b\xaf\xbe\xc9\xd6\xdd\x0f\xe8\x9f\x0d\x45\
+\x23\x23\x19\x61\xf8\x17\xf9\xec\xb1\x1f\xd3\x70\x0c\x19\xc0\x0d\
+\xc7\x28\xda\xcd\x23\x5a\x6a\x53\xe8\x90\x2b\x6a\x35\x06\x14\x9c\
+\x0f\xc5\xfd\x99\xe6\xe2\xc3\x4e\x88\x32\x98\xcf\x4f\x90\x9c\x1f\
+\x7d\xea\x8d\x14\x68\x0a\x49\xa8\xa1\x97\xde\x6e\xa5\x21\xcc\x10\
+\x9a\x33\xac\xfe\xd5\x6f\x7c\x93\xb3\xe3\x01\x3f\xfc\x4f\x3b\x74\
+\x9f\xf9\x0c\xab\x78\x0c\xc7\xa0\xd5\xce\xf0\x58\x40\x89\x34\xa8\
+\x95\xfc\xb1\x22\x8e\xb8\xe4\xc5\xef\x2e\x82\x37\x9f\x0d\x96\xda\
+\x19\xcd\x00\xce\x5a\xb9\x54\x8b\x88\x39\xbd\x69\x25\x0b\xe7\xd8\
+\x41\x48\xa2\xa5\xe8\x5e\xc6\x43\xcf\x94\x9d\x5b\xc7\x1e\x41\x30\
+\x62\xa5\xbd\x51\xb4\x9f\x45\xcc\x65\xf5\x15\x49\xcd\x05\xa9\x26\
+\x1c\x86\x0a\x0f\xa3\xb1\x1f\xa3\xdb\x0d\x70\xcd\x9c\xb8\x67\x10\
+\x72\x46\x57\x59\x90\xdf\x34\x02\x5c\xbd\xe8\xa3\xbb\xe5\x1b\xea\
+\x4b\x52\x7b\xd6\x53\xf7\x67\x9a\x89\x32\x78\x2d\xb3\xb0\x29\x2c\
+\xec\x0a\x8b\xe7\x13\xcb\xe2\xe1\xce\x07\x73\x63\x43\xcf\x2c\xdd\
+\x25\x08\x3f\xc9\x25\x6b\x26\xfe\x91\xbb\xed\x2c\x18\x26\x6f\xb1\
+\x3f\xed\xb1\xe7\xef\x73\xd9\x59\xe7\xda\x62\x39\x46\xff\xbf\xc0\
+\x25\x48\xb2\x77\x79\xe5\x9b\xdf\xe0\x70\xfd\x5d\x86\x76\x03\x6f\
+\xef\xe7\xd8\xbc\xd2\xe1\xf4\x4e\x97\xe8\xa5\x43\x09\x39\x9e\x14\
+\xd0\xb1\xfb\x00\x78\x89\x9b\x57\x5f\x20\xc9\xde\x25\xcb\xde\x85\
+\xe3\x75\x92\xe5\x77\x79\xf9\xc6\x35\x2e\x5f\x56\xd9\xbd\x7f\x48\
+\x7c\x24\x9a\x19\x49\xe6\x49\xdf\x88\x93\x34\x04\x05\xda\xce\xfc\
+\xf8\xd5\x30\x1b\xc9\x8e\x9d\x10\xf9\x58\x45\x70\xb7\x24\x7b\x41\
+\xa1\xc0\x2a\x4f\x80\xea\x11\x57\xa7\x9d\x2b\x4f\xcc\xec\xd5\x00\
+\xd7\x18\x72\xa6\x34\xe7\x3f\xa7\x99\xc3\x48\x41\x6b\x0e\x88\x93\
+\x52\x70\x2f\xe6\xf8\x1a\xd4\x0a\x1e\x59\xa3\xab\x46\xdc\xdf\x8a\
+\xe8\x0d\x5f\xe7\xde\x5e\xc2\x33\x5f\xac\xf1\x23\xff\x68\x93\x56\
+\x0b\x86\x63\x17\x8d\x33\x2c\xad\x4e\x62\xd7\xc4\x30\x69\xa1\xb3\
+\xa0\x36\x7f\x12\x6b\xca\x18\xdd\x6e\x08\xc1\x50\xa0\x32\x2c\x34\
+\xc8\xb4\xcb\xc0\x16\x6c\x84\x1d\x08\xf8\xd1\x0c\x20\xb0\x2d\x6c\
+\x52\x12\xb7\xc1\x75\x37\x62\x67\x20\x78\xe2\xfb\xa7\x4d\x21\x06\
+\x7a\x7c\x8a\x52\x0b\x19\x5e\xba\x4a\xdb\x74\x60\x72\x44\xe6\xae\
+\xcc\x0d\xa3\x06\xe9\x84\xc0\xb6\x05\x13\xf4\x4b\x3f\xfb\xcf\x7e\
+\xc5\x1b\x8d\x04\x2b\x01\x18\xd8\x04\xca\x94\x2c\x31\x41\xcf\x25\
+\x84\xb0\x42\x85\x28\xca\x69\x64\x6a\x05\x50\x1b\x98\x7a\x4e\x4d\
+\x37\x98\x26\x09\x59\x92\xa0\xea\x86\x50\xc1\x85\x29\x86\x21\x9a\
+\x22\x13\x1c\x8c\x24\x2e\x06\x46\xa1\x37\x18\x93\xe6\x6f\x89\x81\
+\x46\x4b\x01\xf5\x0a\x0b\x8d\x8f\xa2\x1a\x16\x49\x92\x60\xe8\x3a\
+\x09\x70\x12\xbe\xcb\x69\xff\x5b\xbc\x7b\xff\x1b\x7c\xf0\xad\xaf\
+\xd2\x7f\xb8\x4c\xf7\xd9\x36\x37\x6e\x3c\x83\xe9\x3a\x2c\x2d\x98\
+\xb8\x8d\x26\x23\xcf\xe2\x7b\xfd\xaf\x62\x4c\x75\x06\x5e\x46\x50\
+\x7b\x0b\x3b\xbc\x45\xbd\x13\xe2\x7a\x97\x88\xcc\x99\x96\xa2\xd3\
+\x54\xe9\x34\x55\x96\xcc\x1a\x9d\xa6\xca\xdd\xd1\x84\xa3\xbb\x43\
+\xf2\xbd\x3b\x74\xd3\x4d\x9e\x6e\xe7\x9c\x3a\x1e\x5b\x3b\x09\xc3\
+\xed\xbf\x62\xab\x77\x9f\xcd\xeb\xcf\xd3\x55\x1f\x60\x2d\x5d\xa1\
+\x33\x99\x72\x96\x4d\x38\x8b\x62\xda\xb9\x82\x89\x08\xb6\xd4\x4f\
+\xa4\x3e\xc2\x54\xea\x4c\xf2\x09\x93\x7c\x82\x1e\x58\x24\x76\x88\
+\x1a\x1b\xc4\x85\xb8\x25\x6c\xf8\xa4\x89\x3a\x7b\xac\x8f\x51\x63\
+\x83\x5a\xa4\x13\x34\x0b\x48\xa6\x5c\xd4\x1e\x0f\xb3\x11\xa6\x52\
+\xc7\x44\x61\x98\x8d\xa8\x29\x2d\xf9\xf3\x4d\x14\xc1\x4d\xd7\x41\
+\xab\x0f\x49\x47\x6d\xa8\x43\x98\x8b\x40\x9e\x2a\x3a\x35\x34\xd4\
+\x7c\x04\x75\x8b\x4b\x2f\xbd\xc4\xca\xd2\x06\x7b\x3d\x9b\x93\x41\
+\xcc\x3b\x6f\xbd\xcd\x69\x3f\xc2\xe8\x8f\x68\x99\x1a\x8e\x69\xa0\
+\x28\x21\xea\x74\x04\xf9\x90\x3c\xd3\xa8\xa9\x19\xe4\x53\x5a\xb6\
+\xcb\x24\x9f\x42\x3e\x45\x49\x5c\xb2\x58\x21\x4f\x3d\x0c\xc7\xc0\
+\x4d\xeb\x4c\xa2\x29\x13\x23\x46\x51\xeb\xa8\x46\x2e\x33\xb0\x13\
+\x97\x9c\x71\x82\xde\x70\xe8\x07\xf0\x17\x6f\xec\xa2\x46\x87\x4c\
+\xea\x35\xe2\x60\x4a\x9d\x53\x06\xee\x32\x18\x4d\xae\x25\x09\x4b\
+\xb7\x56\xc9\xda\x4b\xe8\xc3\x9c\xd8\x00\x3b\x48\x08\xf4\x1a\xb6\
+\xa6\x62\xa8\x39\x5f\xf9\x77\xff\x2f\xba\x17\x0c\x99\x9c\x4e\xa5\
+\x97\x6f\x54\x92\x62\x66\x4a\x68\xe5\x24\x5e\x8e\x8e\x82\x97\x64\
+\xb8\xba\x2a\xf1\x6f\x5e\x30\x13\x11\x08\x88\x50\x39\x41\xad\x0a\
+\x87\x1c\xa3\x80\xe5\x63\x58\x14\x13\xd5\x17\x95\x59\xef\x9f\xbc\
+\xca\xd3\xee\xcf\x90\x5a\x42\x5f\x11\x02\x51\xf8\xee\xdc\xb8\xfd\
+\x9d\x2c\xc6\x9f\x86\xdc\xd2\x6f\x48\xfd\x43\x84\x82\x69\x9a\x34\
+\x2e\x4d\xf9\x78\xe7\x17\xf8\x56\xfc\xab\x32\xdb\xa6\xfa\x3d\xb4\
+\xe4\x16\xa9\x2e\xbc\x8c\x3b\xcf\x6e\xc9\x51\xa6\x6a\x46\x6e\x0f\
+\x6f\x72\xe9\x6c\x83\xef\x05\xb7\xf9\x93\xd7\xfe\x84\xf5\xb5\x80\
+\xc5\xd5\x4f\xf3\x03\xed\x98\x23\xfd\x53\x90\xbc\x22\x26\x45\x10\
+\xf2\x82\xfa\xb5\x0d\x9e\xbf\x15\xb1\xf7\x70\x91\xc1\xc9\x9e\xc8\
+\xca\x5e\x42\xec\xea\x0c\xd3\xd1\xb9\xa9\x67\x6b\xee\x98\xd8\x21\
+\x7a\x60\xc9\xc0\xae\xbe\x06\x30\x74\x86\x18\x9e\x55\x29\xde\x90\
+\x5f\xd7\x52\x9b\xe8\x81\xc5\xc0\x15\x42\xfb\x96\x2a\xb2\x3a\x88\
+\x2b\xc1\xd8\x8f\x69\x34\xcb\x8c\xde\x82\x66\x8e\x36\xe8\xd3\x5a\
+\xe8\xe0\x29\xa6\xf0\xc1\xf0\x22\x70\xe1\xb3\x9f\xdc\xe0\xa7\xff\
+\xf9\x17\x59\x59\xb9\xce\xeb\x6f\xbc\xc7\xb7\xbf\xf5\x1d\xd9\xe6\
+\x3d\x8a\x1e\xb1\xb6\xb7\x44\x6d\x51\x9c\x60\xf5\xfe\x25\xbc\xf4\
+\x14\xb7\xd8\x9b\x93\xe7\x5d\x89\x8b\xe7\xa6\x43\x4a\xec\x5b\x8e\
+\x3c\x15\x18\x39\x28\x47\x9c\x02\x24\x7f\xfc\x61\x37\xa7\xd8\x99\
+\xbd\x39\xe8\xb1\x53\x0b\x69\x5c\x11\x23\x57\xb6\x3f\xc4\xb7\x3b\
+\x12\x9a\x88\x4c\x2c\x06\x52\xc7\x7e\x8c\x6e\xb1\x00\x8b\x67\x34\
+\xbb\x39\x61\x41\x97\xc5\x04\x8c\x73\x0b\x95\x00\xdd\x55\xc8\x02\
+\x1b\x57\x9f\x15\x70\x12\x87\x15\xf8\xb6\xa4\xd9\xb0\x4c\xe2\xb0\
+\x87\x81\x2d\xb3\x77\x39\x64\x12\x87\x63\xa9\xac\xb8\xba\xa6\x72\
+\x77\x6f\x5e\xe7\xfb\x68\xf4\x06\xcf\x76\x5e\x16\xd6\x53\x51\x9f\
+\xbd\x9d\x87\x90\xbd\x26\xa7\x94\xf3\x3b\x5d\x1a\xc6\x5d\x36\xb4\
+\x44\x2e\x89\x29\x27\x4a\x26\xd6\x75\xae\x5e\xb9\xc7\x5b\xb7\x67\
+\xc1\x39\x68\xdd\xa7\x3d\x84\x6c\x6f\x83\x61\x7e\x1b\x10\x94\xcd\
+\x0f\x76\x0e\x41\x05\xbd\xf5\x65\x76\xef\x1f\xb2\xbd\xd3\x67\xff\
+\xec\x84\x7c\xe1\x29\xda\x4b\x00\x77\x39\x3d\x7c\x9d\xdf\x7f\xd3\
+\xc2\x5e\xf9\x1e\x4f\xdb\x2f\xf0\x78\x61\x97\x6b\xba\xcd\x23\x66\
+\x3a\x8d\x95\xd4\x47\x51\x73\xfa\x4d\x85\x58\xd1\x31\xbc\x84\xc4\
+\x9e\x0f\xe0\x32\x68\xcf\x07\x75\xf9\x7c\x62\x87\x44\xc9\x18\x33\
+\x98\x15\x4f\xcd\xc4\x67\x54\x70\xa2\x0d\xc7\x60\x98\x8d\xe8\xaa\
+\x39\xbd\x6c\x44\xcb\x69\x42\x2e\xd8\x8f\xc4\x1e\xd1\x75\x72\xc9\
+\x86\x94\x9f\xab\x63\x49\xec\xad\x2e\xae\x42\x51\x10\xf6\x06\x70\
+\xb3\x6b\xb1\x79\x75\x83\x9b\x57\x63\x56\xf3\x57\xb9\xd4\x35\xf9\
+\xe9\xff\xfc\x26\x2f\xbd\x20\xae\x20\x4d\x7f\x97\x83\xf4\x29\x9c\
+\xf8\x21\xf5\x7e\x8d\xc3\xd4\x66\x3a\x7d\x8d\xc9\xe3\x65\x98\x7e\
+\x1f\xd7\xfa\x2c\x63\x77\x42\x23\x10\x70\x28\x77\xbd\xb9\x40\x3e\
+\x98\x9e\xd2\xd0\xea\x2c\x0c\x15\xce\x5a\xa2\xc8\x23\x50\xd0\xed\
+\x8c\x51\xa0\x8a\xc2\x2f\x50\x19\x21\xbc\x90\x75\x6f\x3c\x6f\xc2\
+\x12\x34\x71\xd8\x67\xbb\xbd\x8e\x12\xec\x73\x10\xe9\x7c\xec\x43\
+\x02\xbe\xd4\x62\x34\x1c\x03\x35\xb2\x13\x8c\xee\x0a\x8f\x13\x93\
+\x98\x00\x2f\xc9\x48\x2c\x0b\xd5\x2e\x46\xa5\xbd\x9c\x2c\x1d\x13\
+\x13\x10\xea\x75\xf2\x8a\xb7\x5a\xc9\x0b\xcf\x04\xf5\x91\xdc\x8e\
+\x94\x05\x76\x25\x33\x8f\xe7\xf5\xc4\x8f\x6f\x80\xf6\xd9\x0b\xe3\
+\xf4\x23\x80\xfe\x84\xbd\xca\x34\x73\xa9\x5e\x7b\x27\x5e\x60\x1c\
+\x3f\xc5\xd6\x64\x1b\xf2\x07\x98\xa6\x89\x1a\x99\xc4\xb9\x4b\xbb\
+\xa3\xa3\xab\xcf\xf1\xf1\xce\x2f\xcc\xd1\x68\x83\xd6\x7d\x86\xf9\
+\x6d\xc6\xf1\x53\xf4\x77\x7b\xf4\x77\x7b\xec\xbc\xf3\x29\xf4\xb3\
+\xcf\x03\xf0\xb9\x2f\x6e\xf0\xc3\x3f\xfe\x53\xac\xff\x60\x84\x7f\
+\x75\x11\x7f\xfb\x84\xbd\xa3\x65\xf6\x8e\x96\xc9\x17\x36\x04\xe3\
+\x11\xdc\x26\xb9\x67\xf2\x60\x4b\xb8\xa5\x2c\x1d\x5a\x64\x7b\x1b\
+\xe8\xb7\x4a\xc5\xd9\xec\xb2\x9f\x6b\xae\xcc\xb4\xd5\xa0\x8d\x92\
+\xf1\xdc\xb1\xfa\xba\xa9\x37\xe4\x6b\x7a\x60\xd1\x6b\x6a\x73\x05\
+\x63\xae\xb9\xa4\xb4\xe4\xd7\x48\x35\x9c\xda\x94\x54\x5e\x62\x87\
+\x0c\x33\x51\x44\x36\x1c\x43\xaa\xe3\x4a\xe7\x21\xd7\x89\xf8\xe2\
+\xf3\x5d\xbe\xf0\xc3\x57\xf9\xf1\x1f\xba\xc9\x0f\x3d\xb3\x49\xef\
+\x24\x25\x7a\xf0\x1e\x83\xb7\xbf\x49\xd3\xdf\xa5\xe9\xef\x32\x8a\
+\x0e\x58\x2b\x46\x6f\xce\x3a\x26\xdd\xd6\x7d\xa8\x3d\x4d\xfd\xd2\
+\x31\xd4\x9e\xc6\x4b\x4f\x31\xf4\x87\x28\x69\x4f\x7c\x28\x3d\xf2\
+\xc1\x48\x4e\x4a\x37\x02\x31\x84\x7a\xd6\xca\x65\x26\x16\x0e\x9c\
+\x42\x40\x34\x42\x11\xd6\x59\xc5\xf4\x48\xe2\x36\x68\xe9\x22\x31\
+\x6c\x0e\x7a\x17\x02\xb5\x35\x9c\x08\x4c\x5c\x72\xce\x55\x9d\x72\
+\x51\xe8\x8d\xfd\x18\xbd\x0c\x4a\xc1\x40\x98\xa2\x90\xab\x24\x5c\
+\x8f\x1c\xdd\x55\x30\x42\x9b\x88\x8c\x28\x31\x71\x4d\x55\x36\x32\
+\xf4\x62\x01\x4d\x49\xaf\x59\xc5\x64\x48\x23\x0c\x67\xc5\xdd\xb9\
+\x25\x36\xc9\xfa\x32\xec\xcc\x67\xe2\xa9\x72\x17\x3d\xfc\x24\x5e\
+\x6f\xc4\x54\xb9\x3b\x17\xdc\x7b\xfd\x55\x3e\x6a\x9c\xb1\x7f\x10\
+\xa2\xec\x05\xa0\x7c\x89\x96\xe9\xd2\x32\x61\xdc\x6d\xc0\x3e\x1c\
+\x65\xef\x4a\x1a\xad\x9c\xf8\x00\xe8\x6c\x74\x19\x3f\x2c\xde\x14\
+\xe5\x05\xb2\xf0\x84\x37\xf7\x0f\x60\x1f\x94\x6b\x97\xd9\xfc\x0c\
+\x5c\xbb\xfc\xaf\xf8\x51\xe0\xfe\xf5\x4b\xec\xde\x3f\x64\xe7\xcd\
+\xb7\xe1\x6c\xc4\x78\xa1\xd8\xd9\x61\xde\xc5\x0d\x61\xb8\x2b\xe4\
+\x31\xe3\xb8\x41\x63\xb7\x07\x95\x3d\x76\x73\x7f\x9f\x1d\xd2\x55\
+\xf3\x22\x63\x86\x5c\x1a\xe5\xf4\xec\x10\x33\x68\xcc\x65\xda\xc4\
+\x0e\xe9\x8e\x52\x1e\xa3\xc8\x60\x3e\xff\x7d\x16\xf2\x9c\x5e\xa6\
+\xa0\x33\x9f\xd1\x35\x47\x48\x3c\x7b\x99\x42\xae\xb9\xf2\x44\xea\
+\x6a\x85\xfb\x66\x1e\xd1\x6a\xb7\x58\x6e\x77\xf8\xec\x8b\x2b\x34\
+\xba\xb7\x78\xea\x6a\xca\x92\x95\xb2\x6a\x6d\x30\x71\x84\x19\xcc\
+\x28\x3a\xa0\x69\x8a\xbf\xa3\x3c\xd6\xfd\x35\x70\x1e\x52\xf7\xd7\
+\x84\xef\x83\xb5\x21\x9d\x81\x0e\x0f\x76\x61\x4d\xc0\x0c\x3f\x69\
+\xd0\x70\x15\x5a\x9a\x23\xe6\xee\xda\xae\xec\xd8\x55\xa9\xb8\x79\
+\x88\xa5\x82\x2d\x5c\xe6\xf3\xbd\x5d\x86\xc9\x2d\x74\xbe\x27\x5a\
+\xce\x15\xaa\xcd\xb1\x91\x83\xaf\x92\x9d\xb0\x2b\x22\xa2\x0a\xc5\
+\xa6\x8a\x3d\x15\x02\x1a\xcc\x18\x08\xe1\x92\x13\x13\xa0\x6a\x0d\
+\x12\x2f\x97\xd0\xc1\xd5\x55\x99\xb1\xcb\x13\x20\x0e\x95\x39\xea\
+\xac\x8a\x89\xcf\x07\x30\x61\x84\x85\xc5\xd3\xee\xcf\xcc\x65\x63\
+\xd2\xd7\xe8\xab\x23\xb6\x92\x7b\x17\x3c\x23\x2e\x77\x0e\x19\xc7\
+\x4f\xd1\x51\x73\x6e\xbc\xfc\x8b\xfc\xc0\x0f\x76\x68\x2d\x6f\x62\
+\x77\x5b\x58\xbd\x43\xa2\xc1\xf7\xd9\x3d\xd8\x64\xf7\xfe\x21\xed\
+\xe1\xcd\x0b\x6f\x5c\xb9\xec\xf0\x60\x1a\xe2\x99\x07\xb8\xd1\x1a\
+\x2d\xe5\x05\xee\xbd\x9f\xf1\xf5\xff\xed\x1b\xfc\xd9\xaf\xfd\x1a\
+\xde\x1b\x7f\xc2\xd5\x2b\x3a\x9f\x7b\xee\x25\x3e\xfb\x5f\xfe\x04\
+\xf9\xc2\x06\xca\xd9\x2e\xca\xd9\x2e\xe3\xf8\x29\xa9\xab\x08\x8e\
+\xd6\x68\x18\x77\x09\x8e\xd6\xe8\x67\x83\xf9\x2e\x5c\x81\x8d\xf5\
+\xc0\x92\x59\x12\x90\x41\x0b\xf0\xb8\xca\xec\x8c\x32\x46\xba\x83\
+\xde\x54\x2f\x40\x8e\xf2\x7e\x2f\x53\xe6\xb2\x70\xa3\x60\x42\xce\
+\x14\x91\x75\x5b\x6a\xf3\x42\x01\x58\x8e\xf8\xbf\x78\xfd\x29\x3e\
+\xfb\xe2\x0a\xb7\xd6\xae\xf1\xd9\x67\xa6\x2c\x59\x29\xdd\x25\x4d\
+\x06\xb0\x0c\xd8\x22\x98\xcb\xdb\xc4\x99\x05\x76\xf9\xb9\x87\xe1\
+\x2e\x87\xe1\x2e\xab\xd6\x06\x0b\xfd\x08\x2f\x3d\xc5\xd1\xc7\x84\
+\xc6\x84\x7d\x75\xd6\xfc\x10\x7a\x11\x5f\x36\x48\x12\xe9\x87\x5c\
+\xb0\x5c\xc5\xfd\x0e\x19\xca\xe5\xf5\x0b\x5c\x71\xb5\xf9\x31\x3e\
+\x4e\x19\x44\x3e\xea\xe4\x68\x46\xd7\x79\x53\x02\x7b\xd6\x29\x1c\
+\xfb\xf1\x6c\xb8\xc2\xc0\xc6\x08\x91\x7c\xb0\xa0\x54\x14\x32\x5d\
+\x5c\x02\xa7\xf9\x02\xa6\x7e\x86\x97\x98\x72\x6a\x2e\x4a\x4c\xa6\
+\x9a\x25\x0c\xad\x8b\x13\xc1\xc0\xe6\x1f\xbc\x85\x11\x56\xc7\xa4\
+\x36\x7a\x8a\xa9\x86\x2c\xde\x3e\xd4\xec\xc4\xbb\xc1\xe6\x95\x0e\
+\x5c\xe9\x70\x79\xd1\x64\xf7\x9e\xce\xc3\x83\xef\x72\xf4\x1f\xfe\
+\x8a\x07\x8f\x63\xf6\xfc\x7d\x36\x54\xb1\xae\x76\x3b\xba\x47\xe3\
+\xb0\xce\xb5\xf5\xd9\xf8\x92\x6a\x2d\x41\x3e\xfb\x27\xa9\xd6\x12\
+\xc3\xfc\x36\x2e\x6b\x44\x97\x7a\x18\xd1\x1a\xbf\xff\xd7\xef\x63\
+\xbf\xff\x3d\x99\xbd\xd7\x6a\x1b\x1c\x54\x02\xb9\x0c\x60\xe8\x13\
+\x1c\x95\x26\xd7\x0a\xf9\x28\x97\xd8\x6c\xec\xc7\x18\x9e\xf8\x99\
+\x4d\x27\x98\x0b\x40\x3d\xb0\x04\xfe\xd5\x1b\x02\x3a\x34\x55\x49\
+\x15\x57\x03\xb7\x84\x16\xd5\xcc\xdc\x74\x82\xb9\x93\x22\x76\x05\
+\x06\xa7\x08\xe8\xaa\x3f\x45\xa9\x3f\x7e\xe6\xc5\x5b\xdc\xbc\x1a\
+\xb3\x62\x5e\x43\xff\x84\x06\xfd\x6c\x2e\x70\x27\xce\x81\xc8\xc2\
+\x8b\x6b\x73\xd9\xb8\x7a\xbf\xbe\x08\x9c\x8a\xcf\xbd\xba\xb8\x21\
+\x02\xdd\x87\xe1\x60\x93\xd5\xf6\x36\x67\x1c\x63\x27\xcb\x88\x66\
+\x6f\x5d\x62\xe3\xb2\xd0\x2b\x1f\x57\x03\xb9\x0c\xe6\x91\x12\x31\
+\xd8\x3d\x45\x1f\x7c\x4f\x06\xee\xf8\xd4\x13\x8b\xd4\x03\x91\x89\
+\xcb\xb6\xb3\xaf\x6f\x80\x2e\x54\x71\x12\x13\x17\x8c\x87\xa0\x7f\
+\x8b\x46\x46\x99\x61\xc1\xc4\x4a\x26\xb2\x63\x27\x05\x4b\xca\x19\
+\x06\x36\x53\x4d\xe0\xe5\xc4\xcb\x31\xf5\x08\x88\xf0\x12\x13\x53\
+\x17\x27\x42\x4c\x80\x11\xb9\xc4\xa6\xf7\xa1\x01\x6d\x58\x82\x2e\
+\xbf\xbc\xf9\x32\xde\xe4\x16\x27\x85\xe3\x69\x47\x7d\x30\x37\x2a\
+\xf9\x4c\x57\x61\xe7\xdd\x1a\x37\xd6\x2e\x91\x6f\xc1\xc3\x83\x88\
+\x0f\xfe\xe2\xbb\x7c\xe5\xbd\xff\x8b\xc3\xc3\x13\xb1\xbc\x25\x89\
+\xb8\xd9\xb9\xc1\xee\xc7\x1b\x6c\x04\xfb\x5c\xbd\xfe\x79\x39\xd2\
+\x2f\xab\xfe\x02\x17\x5f\xbe\x7e\xca\xde\xc3\xa7\x68\x15\x34\xed\
+\x91\xe6\x70\x79\xe3\xff\xe7\xec\x4d\x63\x24\x49\xef\x33\xbf\x5f\
+\x44\x46\x1e\x91\x77\x66\xdd\xdd\x55\xdd\x5d\xd5\xdd\xc3\x69\x0e\
+\x39\x33\xa4\x48\x91\xa2\xa4\x15\xe1\x7e\xba\x07\x00\x00\x20\x00\
+\x49\x44\x41\x54\xb5\xdc\x5d\xd0\xdc\xc5\x7a\xd7\xd2\xae\xbd\x6b\
+\x08\x82\x05\x08\x86\x77\x05\xfb\xc3\x2e\x20\xd8\x1f\x6c\xd9\x30\
+\x60\xaf\xe1\x05\x0c\xfb\x83\xf5\xc1\xb2\x56\xb0\x21\xcb\xd6\xb5\
+\xb2\x6e\xea\xe0\x50\x9a\xa1\x66\x28\x72\x86\x33\x54\x4f\xcf\x74\
+\x75\xd7\xdd\x75\x57\x9e\x11\x19\x79\xc4\xe1\x0f\x6f\xbc\x6f\xbe\
+\x11\x99\xd5\x43\x39\x1b\x8d\xc8\x23\x32\x2b\x33\xe2\x79\x9f\x78\
+\xfe\x77\x93\xa3\x9d\x32\xa5\xd5\x63\x06\xa7\x36\xc5\x55\x0f\x7f\
+\xbb\x00\x5c\x50\x2a\x1c\x53\x5b\x7b\x45\xbd\x5f\x82\xb9\x45\x15\
+\x23\xec\x63\xf6\x3a\xaa\xc0\x53\x1a\x57\x92\x1d\x74\x00\x2b\x2d\
+\x5c\x35\x19\xf6\x04\x80\xfd\x5e\x48\xc1\x2a\x31\xa9\x58\x04\xed\
+\x2e\x05\xab\xa4\x0c\xbe\x82\x25\x64\x47\xab\x9a\x11\x6c\x5c\xf4\
+\xb0\xe2\x85\x22\x19\xbf\x54\xce\xce\x74\xd3\x14\xe9\xa4\x0d\x7e\
+\xf4\xae\xc9\xb8\x3a\x61\xa5\x52\xa4\xbc\x60\xb0\xd4\x8e\xdb\xd4\
+\x2e\x65\x68\x5d\x04\x34\x97\x8e\x15\x98\x7b\x1c\x0b\x50\x3b\x24\
+\x18\x5a\x82\x39\xbf\x08\xce\xe5\xe7\xd9\xeb\x5e\x02\xf7\x58\xcb\
+\x0c\xa8\xd5\xf7\xb5\x90\x76\x48\x8d\x3e\x93\xae\x8b\x63\x2d\x02\
+\xd3\x28\x9f\x9e\x3c\xaf\x87\xa4\x1d\xd3\xe5\x56\x54\x25\x73\x23\
+\x8b\x5f\xff\x34\x56\xe7\x6d\xc5\xc4\x72\x00\xbc\x5a\x70\xac\x50\
+\xf6\xdb\x74\xc6\x0b\x74\x03\xd1\x2a\x40\x06\x56\x40\x4c\x14\xb5\
+\x26\x0c\xa8\x58\x45\xc5\xc6\x43\x62\x99\xe0\x8b\x68\x5d\xc1\x1a\
+\x32\xf4\x0b\x62\x3c\x96\x35\xc0\x2c\x46\x0a\xc0\xe3\x68\x81\x9c\
+\x71\xa5\x34\xb3\x64\x6f\x09\xe0\x34\x33\x67\xed\x88\x81\xe7\xb1\
+\xbd\xff\x6d\x95\x37\x91\x8b\x5e\x20\xc7\x0b\x31\xa3\xdc\x01\x76\
+\x78\xd0\x34\x78\xd4\x8a\x78\xd4\x8a\x28\x01\x2b\x95\x22\x4f\x98\
+\x30\x3a\x3b\xe4\x1b\xc0\xc3\xb7\xb6\xa1\x1a\x51\xb7\xaa\x74\x18\
+\xb2\xdf\x7f\x46\xf8\xb5\x33\x0e\xea\x35\xa2\xbd\x36\xeb\x5b\x6b\
+\xd0\x86\xcd\x8f\xef\xd1\xee\x0a\x66\xe5\xf0\x31\x47\x3b\x2f\x50\
+\xca\x3e\xa6\x1b\x09\x7d\x4c\xf6\x5d\xf5\x9c\x3b\x79\x81\xd5\xba\
+\xc3\xe9\x64\x43\x68\xe0\xe1\x0d\xb5\x00\x2a\xc3\x1b\x50\x78\x0c\
+\xab\x82\x8d\x9b\xb4\x69\xf5\xa6\xbd\xd4\x64\xb9\x91\xce\x96\xba\
+\x77\xc2\xaa\x9a\xe2\x31\x9e\x00\x6b\xbc\x95\x80\xcc\x5a\xa5\x19\
+\x46\xee\x59\x65\x2c\x2d\xb8\x29\xd9\xb8\x54\xce\x2a\x30\x27\x00\
+\x5c\x81\x57\xd7\x9b\x94\x56\xd6\xc9\xdf\x99\x70\xab\x52\xa4\xb9\
+\x30\xa6\x6e\x4f\x73\x28\x5a\x17\x81\x02\xef\x89\x77\x48\x73\xe9\
+\x58\xb1\xf2\x0c\x43\xc7\x6c\x5c\xb8\xfb\x71\x88\xee\xb3\xff\xf6\
+\xb7\x79\xfc\xf4\x9b\x9c\x76\x0e\x19\xb4\x87\x7c\xac\x71\xc5\x6a\
+\xed\x26\x0b\x9f\xda\xe0\xb3\x2f\xdc\x60\x52\xfb\x12\x74\x9f\x10\
+\x45\x4d\x9c\xac\x4b\x69\x12\x2a\xcf\x45\x2d\x53\x4e\xf4\x7d\x2b\
+\x87\x25\x7a\xa3\x31\xe1\xd0\x53\x4c\x3c\xe3\xa5\x28\xf6\x54\x2a\
+\xa6\x72\xd7\x55\x4a\xaa\x89\xfd\x90\xb8\x21\x62\x35\xc2\x32\x86\
+\x06\x7d\x2b\xc9\xc4\x12\xcc\xd2\xd8\x93\xcc\x3c\xf4\x45\x88\xd0\
+\xaa\x18\xe0\xc5\x63\x05\x2c\x12\xba\x57\x56\x86\x48\x00\x2b\x57\
+\x9b\x5d\x60\xe2\x0d\xd9\x3b\xff\x36\xe3\xf0\x17\xb5\x06\x7f\xaf\
+\xf3\xa0\x69\x40\xe6\x07\x79\x78\xf8\x98\x17\x6e\xbc\xc8\x6f\xbd\
+\x97\xf4\x25\x1a\x93\x15\x16\x3a\x8f\xc8\xaf\x6c\xc4\x8d\xfe\xb6\
+\xc9\x16\x3e\x8e\xeb\xef\x28\x36\x32\xad\x15\xba\x9d\x33\xc2\xd0\
+\xa0\x73\x01\x0d\x33\xa2\x7d\x58\xa5\x66\x08\x2f\xc3\x0b\x96\xcd\
+\x99\x61\x63\xae\x37\x09\x8f\x36\xe2\x16\xad\xaf\x50\x09\x2e\x98\
+\xb4\x9b\xb0\xfc\x98\x53\xa6\xc3\x17\xa5\x76\x3e\xcd\x94\xa1\xf0\
+\x98\xc1\xa9\x2d\x74\x32\x87\xb4\x43\x03\xa3\x2a\x3a\xbe\x4f\x23\
+\x72\xc5\x84\xac\xd0\xdd\x6b\x7e\x2f\xc4\x7a\xce\x88\x1f\x25\x0f\
+\x9e\x63\x24\xea\x75\x79\x69\xf6\xd5\x01\x7c\xef\x4e\x72\x42\x4c\
+\xc7\x7b\x46\xdd\x4e\x8e\x11\x10\x00\x16\xac\xbc\x66\x13\x6f\x37\
+\x12\x60\xa6\x20\x00\x5c\x28\x2d\x72\xef\xd3\x5b\x6c\x6d\xdd\xe1\
+\xbd\x6f\xdf\xe7\x7f\xfe\x7f\xdf\xe4\xcd\xf7\xff\x98\x3f\x63\x85\
+\xdb\xb6\xcb\xcb\x5f\xfd\x7d\xde\xff\xd4\x67\xf9\x7b\xff\xc9\x6d\
+\x6e\x37\x36\xd9\x6f\xef\x62\x52\x42\xd5\xed\x6b\xb9\x15\x51\xd0\
+\x27\x5b\x29\x31\xe9\xbb\x50\xc8\xa9\x5c\x62\x1d\xc8\x12\xc0\xd2\
+\x3b\x91\xf8\x8c\x81\x41\x2f\xd6\xd5\xd5\x38\x02\xa8\x34\xb1\x94\
+\x14\xb2\x3a\x5e\xea\x62\x09\x6a\x29\x2d\x0a\xd6\x90\xf1\x60\x21\
+\xd6\xc0\x02\xe8\x82\x79\xa7\x80\xb5\x3c\x4f\xb1\xb0\xa7\x97\x36\
+\x69\x33\xed\x66\x82\x1d\xad\x08\x78\x5d\x19\x78\x0f\x9a\x86\x7a\
+\x7e\xf3\xea\x2e\x23\xff\x28\xae\xd1\xbb\x10\x45\xa9\xd5\x08\xfc\
+\x1d\x35\x81\xc8\xa8\x1a\x58\x83\x3c\xa6\xb5\x42\xcd\x14\xe3\x02\
+\xfa\x40\xeb\x03\x78\x56\xdd\xa6\x61\x46\x84\xf5\x06\xf7\x1f\x5c\
+\x11\xad\xff\x0d\xb8\x03\xd9\xd8\x47\x4c\xa6\x4c\x69\x59\x48\x89\
+\xd2\xaa\xf0\x8a\x48\xe9\x50\xa9\x83\x71\x75\xc8\x20\xfe\xe2\xa5\
+\xec\x63\x06\xd8\x58\x83\xbc\xea\xb3\x56\x37\xab\x74\x2a\x11\x46\
+\xd0\x9f\x31\xca\x54\x40\x03\x21\x23\x0a\x83\x52\x02\xdc\xa5\x30\
+\x87\x6b\x8e\xe7\x02\x58\x0f\x8c\xb4\x8a\x1e\xd6\x60\x42\xb5\x3c\
+\x6d\xac\x22\x73\x29\x9a\x35\xd1\x31\xbe\xbc\x61\xb0\x5c\x10\x12\
+\x02\xa0\xb2\xb0\x4a\xeb\xea\x94\xca\xc2\x2a\x10\x70\xe1\x65\x58\
+\x9a\xc3\xca\x12\xd0\x27\x17\x87\xca\x2b\xd5\xf1\xde\xa4\xb5\x9d\
+\xe3\x07\x2f\xa1\xf0\x37\xff\x46\x9c\x45\x18\xf1\xf2\xf7\xbd\xcc\
+\xff\xd0\xa8\xf2\xcb\x2f\x2e\xf1\xf3\xff\xeb\xff\xc5\xbe\x97\xe7\
+\xd2\x2f\xb3\xf8\xf0\x3d\xdc\x7f\x7d\xce\x57\x7e\xf2\xef\x73\xeb\
+\xd3\x9f\x63\x70\x7c\x86\x1b\x64\x21\x18\x52\xce\x25\x03\x22\x7e\
+\x5c\xa3\x57\x8d\x0a\x5c\x5d\x66\xe7\x06\x3c\x9c\x41\x15\x73\x74\
+\x4e\xe9\xc5\x64\xf5\x6a\x14\xf4\x45\x7f\x65\x2d\x4f\xa3\x54\xce\
+\x92\xf9\x07\x3f\xf9\x4f\x7e\x6e\x1c\x46\xd8\xfe\x88\x61\x6c\xb0\
+\x15\xac\x21\x7e\x68\xe1\x87\x96\xba\x0f\x60\x99\x3e\x93\x20\xc2\
+\x34\x3d\x32\x64\x19\x87\x11\x56\xce\xc7\x18\x1a\x04\xd6\x04\xd3\
+\xf7\x15\x98\xf3\x7e\x0e\x3f\x0b\x96\xe7\x31\xb6\x2d\xe5\xb5\xa8\
+\xd6\x8e\xb8\xea\xbd\xc3\xe5\x35\x25\x7a\x97\x9e\x08\x45\x9f\xbc\
+\xf9\x80\xc2\xd5\x12\xd6\x55\x95\x76\x77\xcc\x5b\x57\x1d\x1e\xef\
+\xed\x91\x5d\xbc\x64\xbf\x56\x63\x6b\xa9\x45\xbf\x9f\x05\x31\x72\
+\x84\x30\xf4\xc9\x98\x16\xe3\xf1\x94\xf2\xc2\xd0\x87\x91\x48\x66\
+\x3f\xef\x44\x5c\x5c\x7a\x8c\x8f\x5b\x2c\xe4\x4f\xa8\xde\xf9\x18\
+\xb7\x22\x1f\x7f\x60\x30\xe2\x8c\x71\x7e\x8b\x5c\xe6\x4a\x80\xb9\
+\x26\x1e\x47\xf9\x3d\x26\xce\x32\xd1\xc2\x12\x86\xd7\x63\xe2\x64\
+\x69\x87\x06\x61\x36\x10\xe3\x4d\x62\x26\x68\xe4\x1c\x26\xee\x34\
+\xe0\x60\x8a\xcc\x6f\xc2\xac\x8f\x35\xb0\x19\x7b\x63\xac\xaa\xa9\
+\x1e\x97\xc2\x1c\x13\x23\x60\x62\xcc\xe6\xfd\x56\x7d\x07\xb7\x1c\
+\xf7\xe5\x9d\x64\xa9\x96\x07\x78\x91\x81\x39\xc9\xaa\xf2\x7e\xaf\
+\x6b\xd0\x2c\x4e\x01\xbc\x75\x7f\x85\x92\x55\xe2\xde\xed\xa9\x9c\
+\x19\x7b\x4e\x0c\x60\x38\x3b\x3b\x67\x7d\xc1\xe6\xc2\xcb\x50\xca\
+\x4e\x89\x65\xcd\xde\xc0\xf1\x7b\x78\x83\xe9\x73\x17\x5e\x86\xde\
+\x69\x95\x0f\xbe\x71\xc8\xd7\x7f\xe5\x6b\x5c\xee\x3f\xe1\x85\x4f\
+\xbe\x82\x5d\x76\x70\x4b\x36\x8d\xb5\x25\xb6\xee\x7f\x8c\xbf\xf3\
+\xf2\x8b\x7c\xf5\xe1\x11\x8e\x13\x50\xb7\x8a\xbc\x7d\x70\x89\xfb\
+\xf5\xd7\x29\xdc\xf4\x78\x61\xf5\x2e\x41\xc9\x20\x37\x09\x31\xcc\
+\x3c\xc8\x10\x75\x2c\x2f\x5c\xcb\xc7\xb0\xb3\xf4\x7a\x97\xbc\xf5\
+\xc6\xeb\xd8\xd6\xd4\xe8\x1c\x4f\xf2\x71\xf3\x19\x97\xd5\x5c\x8d\
+\xad\xcf\x6f\x60\x79\x6b\x8c\x30\xc8\x96\xb3\x54\x07\x06\x79\xc0\
+\x9b\x98\xe4\x81\xff\xe5\xdf\xfc\x3f\x64\x7e\xfc\x27\xfe\xf1\xcf\
+\x01\xf8\x71\x4f\x80\x8a\x9f\x25\xf2\x27\x64\xc3\x80\x6c\x18\x30\
+\xa4\x30\x03\xea\xa1\x5f\xc0\x34\x3d\xfc\xd0\x22\x34\x6a\x64\xb2\
+\x82\x89\x87\x51\x15\xc3\xe8\xe1\x4f\x6a\xe4\x0c\x1f\x7c\x8f\x71\
+\xb4\x40\xd6\xef\x91\xf7\x73\xb8\x91\xcd\x64\xb2\x42\x77\x74\xc5\
+\x52\xe1\x90\x25\xdb\x98\x01\xf3\x83\xa6\xc1\x37\x5e\xbf\x4d\xdd\
+\xbf\x03\x41\x95\xcb\xee\x05\xdf\xba\xff\x2d\x46\x2d\x9f\x83\xf3\
+\x90\x8b\x8b\x90\x4f\xfe\xad\x13\x38\xb7\xa9\x56\x26\xf4\x2e\x85\
+\x81\x13\x95\x03\xc2\x6c\x80\x39\x99\x82\xb8\x15\x4d\x28\x60\xe0\
+\x38\x19\x72\xb9\x0c\x97\x97\x13\xba\x83\x31\x4f\x9e\x9c\x72\xbe\
+\x73\x44\xb8\xde\xc3\xa8\xf6\xa8\x2c\xfc\x6d\xca\xb5\x0f\xb8\xba\
+\xda\x80\x62\x8d\x5c\xe6\x8a\x49\xb8\xc0\x24\x5c\xa0\x54\xdb\xc3\
+\xbf\x18\x08\x29\xe1\xf5\xb0\x0d\x18\x46\x06\x5c\x88\x3c\x85\x41\
+\xde\xa4\xc8\x08\xd7\xf2\x29\x18\x79\x02\xd7\xc4\x2f\x7a\x54\x46\
+\x25\x02\x5f\xdc\xcf\x05\x45\xcc\x49\x16\x73\x92\x55\xec\x7b\xdd\
+\x2d\x5f\xf5\x99\xb8\x62\x7f\xbf\xe8\xe1\xc5\xee\xb3\x4a\xbe\xa8\
+\x6a\xf7\x9a\x8d\x88\x95\x8d\x06\xeb\x0b\x59\xb6\xee\xaf\x50\x69\
+\x42\xde\x86\x72\x7e\xca\x6c\x95\x85\x55\x9c\xd3\x88\x5c\xd9\x20\
+\x5f\x2c\x33\xf0\xcd\x04\x13\x03\x38\x7e\x0f\x72\x1f\x83\xe0\x8a\
+\x0b\x2f\xc3\xf9\x91\x41\xfb\x69\xc0\x37\x8f\x8e\x79\xfb\xd1\x01\
+\x6f\x1c\xfa\xbc\xbb\x7f\xc6\xc1\xaf\x7f\x97\x85\xdb\x11\x77\x6e\
+\x3f\x80\x4c\x01\xdf\xce\x71\xab\xb1\xc8\xf7\xdf\x59\xe6\xd9\x38\
+\xc7\xc3\xed\x03\x26\x66\x95\x67\xe3\x21\xce\xce\x77\xa8\xad\x67\
+\x59\xb9\xd1\x24\x18\x16\x71\xfd\x88\xa5\x6c\x71\x9a\x6b\x91\xa9\
+\x90\xf5\x47\x50\x5c\x64\x6f\xcf\xe3\xfd\x47\x0f\x13\x20\x2e\x17\
+\x7b\x8c\x27\x79\x8c\xc0\xe5\xc1\x8b\x8b\x2c\x2d\xdf\xc2\xce\x07\
+\xe4\x02\x9b\xec\xc4\x50\xd2\x42\x26\xe4\xff\xca\x2f\xfe\xb6\x90\
+\x13\x51\x77\x84\x11\x8b\xe8\xbe\x35\x01\xf2\x6a\x78\x8b\x74\xa5\
+\x29\x39\x11\xbb\xda\x86\x7e\x41\x79\x27\x94\x7f\xcf\xf0\x70\x23\
+\x21\x37\xa4\x26\xce\x1a\x9e\xea\x4b\x11\x06\x2e\x05\x6b\x48\x2e\
+\x12\xae\xb5\x79\x3d\x84\xbf\xf1\xfa\x6d\xc2\xa3\x0d\x06\xf6\x90\
+\x62\xa3\xc0\xc5\x5a\x12\xe5\xe1\xfd\x55\xa0\xcf\x77\x27\x0b\x34\
+\x2f\x3c\x8c\xaa\xf2\xc3\x27\x7a\xa1\x4d\xfc\xa1\x9e\x6c\xa7\xf4\
+\xaa\x0c\xd3\xb6\xc2\x1e\xbb\x7f\xd8\xa3\x5e\xaf\xf1\x62\xf3\x5b\
+\x98\xf6\x06\xeb\x5b\x87\x71\x98\x3a\x96\x0e\xa7\x36\x03\x6c\xe5\
+\x33\x16\xc5\x8a\xb1\x5b\xad\x2a\x00\x95\x35\x27\xf4\x28\xd2\x2c\
+\x0f\x68\xc5\x61\x5f\x6b\x60\xcf\x00\x55\xc9\x88\x6a\xa4\xb5\x01\
+\x4d\xbe\x56\xf5\x45\x7b\x26\xb9\x0c\x65\x16\x5c\xcd\xac\xaa\xcc\
+\xb4\x5a\xa3\xc6\xab\x0f\x9a\xb1\x7c\x58\xa6\x12\x27\xf4\x49\x19\
+\x21\x6d\x08\x80\xc6\xea\x21\x76\xff\xd3\xf4\x2a\xd3\xe1\x2d\xa3\
+\xf3\x15\x11\x81\x53\xd4\xf7\x21\x17\x5e\x06\xe7\x34\x62\xfb\x78\
+\x97\x9d\xed\x33\x0e\x8e\x3d\x2e\x7b\x59\xee\xdd\xbe\x01\xc6\x31\
+\xbf\xb1\xf3\x3a\xc1\x7f\xf1\x88\x27\xff\xf1\x84\x1f\xfb\xf7\xff\
+\x19\xf5\xd2\x15\xbd\x46\x9e\x57\xbf\xf4\x2a\x3f\x7b\xe7\x36\xff\
+\x0a\x78\xf3\x6b\x7f\xcc\x62\x65\x89\x6f\x1e\xc2\x8d\x7f\xfb\x3e\
+\x4b\xb5\x7b\x34\xef\x82\xe7\x56\x38\x26\xa0\xcc\xd4\xed\xf6\xbc\
+\x9b\x33\x98\xed\x66\xd4\xce\xe6\x30\xc6\x86\x32\x12\x25\x80\xfd\
+\x81\x29\x3a\x00\xfd\xf8\x4f\xfc\xe3\x9f\x33\x62\x31\x1c\x75\x47\
+\xc8\xfb\xbe\x69\x29\x76\x96\x00\x1e\xfa\x05\xa2\x68\x02\xa5\x2c\
+\xe1\x18\xc5\xce\x7e\x68\x91\x37\xe3\x9e\x5e\x46\x8f\x0c\x59\x06\
+\x7e\x06\xd3\xf4\x18\xf8\x19\x6c\x33\x27\xf4\x75\x29\x4b\xde\xcf\
+\x51\x2d\x2d\xd1\x77\xc7\x34\x4b\x25\x96\x0a\x87\x5c\x7a\x22\x31\
+\xe7\x62\x34\x21\x30\x7b\xd8\x79\x8b\xe5\xaa\x8f\x91\xe9\x53\xae\
+\x1d\x70\x1e\x4d\x30\x96\x3d\xce\x1f\xe6\x31\x5a\x0e\xcb\x2f\x8d\
+\x59\xbe\x82\x9e\xdb\x24\xeb\x1a\x62\x1c\x97\x33\x62\x6c\x58\x62\
+\xd0\x4b\xe8\xc7\xd5\xd6\x86\x0a\x10\x74\x8c\x88\x8a\x65\x13\x86\
+\x22\xdb\xac\x64\x0c\xc9\x19\x35\x32\xa3\x2e\xdb\xad\x2e\xee\xd5\
+\x33\xce\x2e\x2d\x7c\xf7\x8a\x6c\xd9\xc7\x9d\xbc\x40\xa9\x76\xc6\
+\xc4\xc9\xaa\xad\x04\xb0\xcc\x26\x23\x0f\x93\x71\xa8\x3c\x07\x92\
+\x3d\xf5\x6d\x98\xf5\x15\x0b\x03\x2a\x73\x4d\xbf\xc9\xfd\x27\x41\
+\x49\xed\x27\xf7\xad\xe4\x8b\x8a\x7d\x0b\xb5\x02\xaf\xde\x9d\x05\
+\x30\x40\xc5\x5c\x87\x4c\x1c\xde\xcf\xb8\x8c\x3d\x07\xab\x78\x93\
+\x30\xff\x01\x21\x35\xaa\xfd\x45\xda\xe6\x90\x6a\xbd\x9f\x90\x0e\
+\x03\xdf\xe4\xc9\xde\x0e\xad\xf7\x43\x5e\x3f\x18\xd0\x3a\xbd\xa2\
+\xd5\xf5\x58\xa8\xae\xab\x16\x58\x3f\x52\x1e\xf1\xa7\xc3\x32\x7f\
+\xf0\xbb\xbf\x4d\xdd\x3b\xe6\xe3\x4b\x2f\x61\xaf\x2e\xc7\x95\x29\
+\x79\xbe\xf8\xea\x5d\x1e\x9e\x79\x3c\xdc\x3e\xe0\x46\x29\xcf\xdb\
+\x07\x97\x64\x4e\x0f\xd9\xfa\xf4\x3a\xd5\x8a\xc5\xb0\x6f\x32\xca\
+\xda\x4c\x46\x23\xf2\xd9\x12\xae\x1f\x51\xcc\x5a\x3c\x3b\x1f\xcc\
+\x30\xb1\x39\x3a\x27\xb2\x4a\x18\x81\x8b\xbd\xb4\xcc\xbd\xad\x9b\
+\x64\x73\x8b\x94\x27\x50\x30\x73\x74\x03\x87\xb1\x99\x27\x18\x3a\
+\xd4\xcc\x1c\x3f\xff\xcb\xbf\x4e\xe6\x27\xfe\xc9\xbf\xfb\x73\x12\
+\xac\x45\x2b\xc0\x37\x2d\xda\x13\x1b\x3b\x93\x34\x36\xa4\x2e\x2e\
+\x58\x43\xc2\xac\x00\x71\xc1\x1a\x62\x99\x3e\x7e\x68\x61\x9a\x1e\
+\xc3\xa8\x4a\xc1\x98\x66\xbc\x49\xdd\x6c\x9a\x53\x59\x91\x21\x4b\
+\x86\x2c\xc5\xc5\x5b\x58\x85\x1b\x94\x2a\x5f\xa2\x18\x8d\xd8\x3b\
+\x38\x22\x1b\xeb\xd9\xf6\xe2\x09\x95\x9b\x5d\x0a\x57\x4b\x84\xf9\
+\x36\xa5\x1b\x11\xed\xbf\xa8\x13\x3c\x9d\xe0\xe5\x4d\x4e\xc7\xb7\
+\x39\x0f\x8b\x94\x4f\x9e\x61\x98\x65\xaa\xe3\x0c\x8e\x61\x4c\x75\
+\xb0\x96\x77\x5b\x8d\xd3\x23\x87\x06\xe4\xc2\x80\x8e\x11\x31\x34\
+\xc0\x8b\x53\x1a\x23\x0a\x14\x8c\x3c\x8e\x93\x61\xdc\x17\xc3\x4d\
+\xba\x97\x65\x8a\x91\xd0\xc0\xd0\x60\xe2\xf8\xb4\xa8\xd2\x34\x46\
+\x78\x43\x18\x45\x23\x02\xd7\x24\x37\xb4\xf0\x4a\x42\x0f\x57\xcb\
+\x03\x5c\xcb\x57\x46\x9b\x04\xa3\xdc\x4a\x50\xa7\xf5\xef\xc8\xcc\
+\x4d\xf5\x6f\xac\x87\xa5\xec\x98\x18\x01\xb9\x5c\x46\xe9\xdf\x8f\
+\xdd\xac\xf2\xe2\x8a\x41\xa1\x94\x04\xf0\x4a\xa5\x38\x05\xb0\x26\
+\x27\x44\x5f\x0f\x01\x60\xaf\xf2\x36\x0b\x76\x59\x01\x77\xe0\x9b\
+\x38\xa7\x11\xfd\xed\x23\xbe\xf9\xc1\x84\x6f\x6f\x6f\x73\x76\xe2\
+\x31\x18\x65\x58\xa8\xae\xd3\x8a\x5a\x78\x91\x85\x87\x47\x2f\x73\
+\x83\x62\xbe\x44\x60\x65\xf9\xe3\xd7\xdf\xa0\x7f\xf2\x2e\x9f\xa8\
+\xaf\x53\xdc\x68\x60\xe6\xc6\x14\x16\x1a\x7c\xe1\x07\x3e\xc5\x07\
+\x7b\x1d\x25\x2d\xee\xf6\x73\x9c\x1d\x5c\xf0\xb9\x57\x6d\xfc\xea\
+\x3a\x13\xa7\x4f\x29\x63\xe0\xfa\x11\xa5\xcc\x84\x28\x58\xe4\xb8\
+\xf3\x98\xf7\xdf\xdf\x57\x20\x6e\x8f\x2c\x8a\xf4\x15\x88\xef\x17\
+\x2b\x6c\x7d\x7e\x83\x49\x2f\xcb\xd8\xcc\x33\x0c\x1c\x6a\x99\xb2\
+\xda\xf6\x30\xf8\xc5\x5f\xfe\x35\x61\xd8\x29\xa0\xc6\x60\x96\x00\
+\xd6\x99\x39\x01\xe6\xa0\x44\x3e\xd3\x17\x2e\xb7\x18\xc4\x96\xe9\
+\x13\x50\x24\x67\xf8\xca\xf0\x9b\x30\xc0\x36\x73\x84\x4c\x98\x04\
+\x11\x94\xb2\x0c\x87\x11\x79\x53\xe4\x26\x67\x83\x12\x76\x71\x15\
+\xb7\xd3\x66\x64\xbd\xcb\x49\xe4\xf1\xc2\x52\x01\xe7\x4a\xe4\xfc\
+\x0e\x17\x2e\xd8\x6c\xff\x30\xc1\x59\x91\x61\xc5\xa2\x91\x5b\x22\
+\x6b\x44\xac\xd7\x7a\xdc\x9b\x34\x58\xa8\xd7\x69\x56\xb3\x9c\xf5\
+\xc4\x84\x4e\x59\x71\xac\xae\x1e\x31\x13\x0f\xf2\x26\x0b\x51\x8f\
+\x88\x82\xca\xd3\xd5\xf3\x6f\xe9\x19\xe4\x2a\x22\xbf\xd7\xca\x89\
+\x96\x53\x41\x98\xc1\xf7\x0b\xe4\xd6\x1a\x18\x5e\x06\x9b\x2e\xed\
+\xd0\xa0\x33\x8e\xa8\x1b\x05\x26\xe3\x90\x5c\xc5\xa4\x60\xe4\xf1\
+\x2c\x97\x9c\x51\x23\x70\x67\x1b\x72\x55\xcb\x03\x46\xe3\xec\x5c\
+\x30\x4b\x00\xab\x4b\xbd\x99\x13\x00\x2e\x8b\x86\x78\xb9\x5c\x46\
+\x34\x18\xd4\x3c\x10\x3a\x80\x1b\xed\x2c\xb5\xe5\xd9\x4a\x13\x63\
+\xb2\x42\xa9\x7c\x48\x18\xbb\xe3\xc2\xfc\x07\xd4\xed\x9b\x5c\x78\
+\x62\x41\xf7\xaf\x4e\x19\x7b\x0e\x4f\x8e\x2e\xf8\x83\x0f\x26\x5c\
+\x3d\x3b\x54\xc9\xf2\x46\xce\xc4\x75\x1c\x0c\xad\x3b\xa5\x17\xff\
+\x5b\xc8\x2f\x12\x65\x3c\x3e\x3c\xed\x70\xfa\xfa\x1e\x2f\xdd\xbd\
+\xa4\x72\xe7\x53\x90\x29\x50\x2a\x98\xfc\xc8\x8b\x5b\x3c\x3c\xf3\
+\x38\xda\xdb\xe1\x70\x78\xc4\xc3\xc3\x1d\x16\x7d\x9f\x97\x3f\x96\
+\x21\x30\x8a\xb8\x81\x09\x85\x0c\xb9\x30\xc2\x30\x43\x4e\x5b\x59\
+\xde\x7f\xf4\x90\x61\x60\x62\x5b\x21\xc3\xc0\x64\xb1\x31\x51\x9a\
+\xb8\x76\x67\x95\xad\x1b\xeb\x80\x4d\xcd\xcc\x31\xea\x8d\x18\x65\
+\x27\x22\x57\x23\x70\xc8\x96\xb3\xfc\xc2\x2f\xfd\x7a\x72\x40\xb9\
+\x94\x0c\xea\x60\xd4\xe6\xcf\x26\x0b\x03\x57\x19\x7c\x52\x1b\x0f\
+\xfd\x02\x56\x65\x40\xbf\x2f\x06\x9a\xfb\x95\x08\xbf\x5f\x60\x48\
+\xa8\xc2\xd4\xd3\x28\x5f\xec\x53\x5d\x2a\xe1\x5e\xf4\x55\xc6\xda\
+\xc7\x6b\xa5\x44\x97\xcb\xfa\xe3\x8f\x93\x77\xaa\x2c\x2f\xc2\x32\
+\x90\xdf\xa8\x72\x70\xd7\xe3\xd6\xd8\xe6\x20\xe7\x69\x61\xe4\x21\
+\x27\x8f\x1f\xd3\xd2\x0b\x29\xe3\x5c\x5b\xbf\xe8\xb1\x94\x59\x66\
+\xe2\x0b\x40\xd7\xf5\x2a\x0a\x73\x2c\xf4\xa9\x09\xa5\x5e\x4e\xf4\
+\xbe\x95\x2d\xa8\xa4\x5b\x67\xbf\x8b\x51\x16\x85\x9b\xdd\xb0\x8b\
+\x21\x9a\xe3\xa8\x84\x1c\xd7\x99\x40\x11\xd5\x73\x4d\x0f\x4c\xf8\
+\x45\x2f\xf6\xeb\x4e\x34\x1f\x32\x73\xc3\xc9\x7a\x30\x43\xef\x9e\
+\xd9\xac\xad\x6a\x2e\xb4\x24\x03\xe7\xd7\xd6\x39\xed\xef\x26\xf4\
+\x30\x40\x79\xd5\x60\xc2\xad\xb8\xe8\x20\xa0\xe3\x91\x00\xf0\x59\
+\x7f\xc0\x93\xbd\x2c\x8f\xde\xd9\xe3\xb2\x97\x05\xb2\xaa\x57\x85\
+\x6c\x7f\x95\xbe\xb5\x08\x20\x6a\xd1\xac\xde\x05\xe0\x4f\x7a\x0f\
+\x09\x7e\xf6\x11\x3f\xf5\x9f\xdf\xe6\x85\x7f\xef\xd3\x98\x61\x83\
+\xfa\x66\x93\x7f\xf5\x5f\xff\x34\x3f\x1b\x6b\x64\x80\xff\xe9\xb7\
+\xde\xc3\x37\xd7\xf8\x77\xfe\xe9\x4b\x0c\xfc\x88\xc1\xb0\x4d\x29\
+\xae\x00\x3f\xbd\x14\x35\x7d\x8d\xbc\x20\x9e\x05\x8e\x19\xb4\x81\
+\xfc\xac\x2e\xee\x76\x66\xb5\xb4\x3f\x30\x29\x85\x39\xd1\xa0\xa0\
+\x10\x77\x29\xd6\x01\xac\x1b\x76\xe9\x9b\x7c\x4d\xdf\x5f\x82\x74\
+\x26\x6b\x29\x4e\x2a\xd2\xff\x46\xdf\x0f\xb1\x2a\x06\xa3\xa1\xc9\
+\xe9\xa3\xbd\xb9\x9d\x7d\x00\x96\x0b\xcb\xac\x2c\x79\xdc\xc8\xdc\
+\xe2\x96\x91\x65\x61\xa5\xce\xa7\x1a\x6b\x2c\xac\xd4\xd9\xba\x73\
+\x87\xd5\xfa\x06\xab\xf5\x0d\xbe\xf0\xf1\xfb\xdc\x7a\xe5\x8b\x82\
+\x59\x35\x00\xcb\x04\x99\xce\x9c\x03\x40\xcf\x10\xd1\x2f\xad\x54\
+\x48\x2f\xef\x71\x9d\x89\xf0\x05\xb7\xfa\xb4\x3a\x72\x86\xb0\xad\
+\x52\x2e\xf5\x84\x9c\x74\xee\x43\x2b\x34\xd4\xf3\xf2\xbb\xc8\xfd\
+\xf5\x72\x7e\x3d\xc2\x17\x50\x53\x00\xce\xd0\xa5\x99\x81\x17\xee\
+\xdc\xe1\xf6\x9d\x8d\xb9\x00\x06\x88\xb2\x67\x73\x25\x84\x88\xbe\
+\x8a\x34\xc1\x9d\xa3\x0b\x26\xdc\x22\xcb\x01\xce\x69\xc4\xd3\xc3\
+\x55\xde\x7b\x27\xe0\xd1\xdb\xae\x62\x5f\x09\xda\x16\x02\xc0\xb2\
+\x52\x5a\xaf\x98\x96\xe3\x80\xf7\xfb\xcf\x44\xbb\xaf\xea\x5d\x7e\
+\xe3\x38\xe2\x7f\xff\xef\xfe\x4b\xce\xfe\xf4\x37\x09\xcd\x76\x0c\
+\x44\x83\xff\xf4\xef\x7f\x9e\xca\xfa\x16\x93\xf3\x47\xb4\xda\x06\
+\x6f\x7e\xfb\x77\x79\xfb\xe1\x1f\x51\x2b\x89\xf3\x70\x15\x64\x54\
+\x3a\xa6\x32\xde\x46\x56\x3c\xa6\x41\xef\x00\x15\x5f\x55\x75\x5c\
+\xf5\xa7\x19\x72\x55\x22\xd1\x01\x48\x02\x4b\x67\x61\x19\xa1\x93\
+\xcf\xe9\x85\xa2\x05\x6b\x88\x17\xb3\x70\xdb\xec\x61\x8f\x97\x13\
+\xde\x0b\xc1\xc8\x86\xa8\x08\xa9\xcc\xd6\x87\xc9\x7d\xf2\x85\x22\
+\xfb\xdb\x87\xfc\x9f\xbf\xff\xfb\xac\x6f\xad\xd1\x58\xdb\x4b\xec\
+\xf7\x29\xe7\xa7\xb9\x71\xc3\x8f\xe3\xe7\x00\xeb\xe8\x50\x2f\xe1\
+\xc3\x2a\x1c\x0f\x05\x6b\x7f\x76\xb3\xc4\xc3\xf7\xf2\x74\x3a\xfd\
+\x44\x0e\x83\x1e\x45\x2b\x85\x39\x5c\x67\x9c\xa8\x6f\xc3\x8c\xbd\
+\x16\x3d\x43\x31\xb1\x6b\x8e\xd5\x73\x92\xad\xa5\x6b\x4c\xa6\x3d\
+\x76\xe3\x9c\x5e\x09\x4c\x09\x48\xc9\xb6\x2e\x93\x44\xf2\xbb\x04\
+\x7a\xd0\xab\x53\xad\x76\x14\x53\xcb\x1e\xc5\x72\x41\x64\xe8\x52\
+\xb1\x36\x58\x59\xcf\x70\xff\x81\xc9\x72\x21\x43\xa5\xb9\x3c\x73\
+\x1c\x25\xfb\xea\x2c\xdc\x8f\x83\x1b\x62\x2b\x98\xb8\xb9\x30\xa6\
+\x7d\x1a\x71\x3a\xf4\x79\xb2\x77\xc4\xa3\x77\x44\xfe\xee\x65\x3f\
+\xc9\xbe\x9d\x32\xd4\x1d\x68\x95\x83\x69\x87\x1f\x8d\x99\x25\xa0\
+\xc5\xa4\x54\x9b\x56\xd4\xe2\xde\x9d\x02\xaf\x75\x3d\xf8\xd9\x5f\
+\xe0\xbf\xfd\xd5\x2f\x62\xdd\x01\xb3\x7e\x87\x57\xbf\xf4\x2a\xff\
+\xa2\xd5\xe1\x5f\x03\xfd\xa3\x1d\xbe\xfa\xee\x23\xee\x7f\xf5\x92\
+\xad\xa6\xc1\xda\x9d\x09\xed\xab\x01\xbe\x96\x6f\xde\x1e\x59\x2c\
+\x70\xcc\xa9\x07\x61\x7d\x19\x73\x74\xae\xb2\xd8\x64\xa5\x48\xf6\
+\x20\x62\xd2\x98\x56\x8d\xc8\x6c\x39\x71\x25\x4e\xb1\x6a\xd4\x15\
+\x00\xd6\x99\x58\xa6\x69\x56\x2c\x53\x81\x74\x1c\x2d\x60\x8f\x97\
+\x15\x30\xa3\xee\x68\x86\x99\x93\x12\x62\xea\xae\x6b\x56\x0c\xf6\
+\xb7\x9f\xf1\xdb\xff\xe3\xaf\x13\xed\x8b\x94\x9f\xef\x73\xbe\x28\
+\xfc\xc4\x4b\x3f\xc4\x57\x8c\xaf\xb0\x56\x79\xc6\x8d\x92\x68\x9a\
+\x71\xa3\xb4\x44\x94\x3d\x53\x8f\xcb\xab\x86\xda\xae\xd4\xd7\xb9\
+\x51\xf0\x29\xd6\x33\xd3\xaa\xde\xde\xd4\x2b\x21\x80\x3b\x51\xc0\
+\x95\xcc\x3b\xf7\x75\x9d\x91\xe3\x9e\x06\xfa\xf3\x93\x8a\x85\x11\
+\xf4\x71\x9d\x89\x02\xf0\xa4\x62\xcd\x24\xff\xe8\xee\xbc\xaa\x9f\
+\xf4\xa7\xe9\x9f\x59\x33\xab\x6a\x92\x92\x5c\x34\xb5\x7a\x8d\xb5\
+\xf5\x0c\x37\x9a\x4b\x2c\x17\x96\xe7\x5e\xa1\x56\x2a\x45\xce\xfa\
+\x83\x84\x06\x6e\x2e\x8c\x13\x8c\xdc\xbf\x12\xe9\x8b\xad\xab\x1c\
+\xee\x59\xc0\x77\xde\x5f\xe0\xd1\x3b\xdb\x71\x9b\x80\x42\x42\x32\
+\xc8\xfb\x66\x39\x43\x5d\xfb\xba\x66\x39\x33\x33\x68\x32\x74\x92\
+\x97\xfa\x66\xf5\x2e\xbf\x75\x74\xc5\x6f\xff\x57\xff\x0d\x61\x4b\
+\xb0\x71\xd7\xb0\xf8\x3b\x9f\x79\x99\x97\xee\x8b\x31\xc6\xf5\x66\
+\x85\x3f\x7c\xf8\x1e\x7f\xf1\xb5\xd7\x71\xba\x17\x94\x1a\x79\xfc\
+\x14\x13\x5f\xd5\x0a\x2c\xc7\x00\xbe\xe2\x06\xd1\xf8\x52\xe5\x13\
+\x03\xf8\xd5\x56\x82\x8d\x75\xb7\xa9\x39\x88\x8d\xda\x28\x8e\x53\
+\x4b\x1d\x3c\x70\xd1\x7c\xc1\x02\x8c\x6e\x64\x53\xb0\x44\x8e\xb0\
+\xf4\xf9\xca\xa4\x1f\xa3\x26\x80\xef\xe5\xce\x95\xac\x90\x6c\xac\
+\x12\x88\x62\x1d\x7c\x75\x34\xe4\x6b\xbf\xfe\x4d\x9e\xb4\x9f\xd2\
+\x69\xf5\x59\xbe\xda\xa0\xdf\x12\x40\x2e\xec\x3e\xa0\xb2\xb0\xca\
+\xcd\xdc\x27\xe8\x55\x2e\x15\x70\xe5\xa5\xf2\x46\x69\x89\x6a\x7f\
+\x91\xcd\xcd\x90\x6a\x7f\x91\x8d\x8c\x4b\x79\xd5\x60\xd0\xd1\xb4\
+\x9c\x04\xa2\xce\xaa\x12\x60\xf1\x6b\x0a\xcc\xf1\xeb\x6a\xab\x57\
+\x1d\x6b\x60\xd4\x2b\x98\x75\xb0\xa6\x73\x79\x75\x4d\x2b\x2b\x35\
+\xa6\xd5\xce\xb3\x61\xd6\x7a\xd7\x4c\x04\x31\x5e\x5d\x6f\x72\xff\
+\x81\xc9\xe6\xed\x0c\x95\x26\xb3\x5e\x08\xe0\xa4\x7f\x73\x46\x07\
+\xb7\xae\x72\x54\x16\x56\xc9\x72\xa0\x18\xd9\x39\x8d\x78\xb2\x3f\
+\xe0\x57\xbf\xf5\x4d\xde\xfd\xe6\xeb\xb4\xba\xde\x73\xe5\x42\x2b\
+\x6e\x14\x6e\x96\xc5\xfd\xd0\x09\xa8\x94\x6d\xd5\xbf\xc2\x65\x9c\
+\x78\x7f\x2b\x2c\x80\x71\x4c\x60\x36\x79\xeb\xfd\x6d\xfe\xf2\xb7\
+\xbe\x4a\x14\xec\x51\x8b\x7c\x8c\xad\x65\xfe\xd9\x7f\xf8\x25\x2a\
+\xeb\x5b\xb8\xd6\x3a\x4f\xf6\x86\xfc\xd5\x1f\xfc\x11\x1f\xbe\xf1\
+\x94\xc6\x64\x4c\x33\x35\x0b\x7a\xa1\x3b\xe4\xbc\x73\x4e\x98\x9f\
+\x2e\x5c\x79\x95\x15\x12\xae\x89\x5b\x1c\x27\x6a\xf8\xe4\x79\x30\
+\x8b\x5a\x41\x81\x97\x3b\x57\x60\x96\xcf\xeb\x00\x34\x8b\xc9\xac\
+\xb4\xa1\x9f\x4c\xdb\xf4\xac\x7c\x82\x9d\x6d\x7f\x84\xdf\x8f\x30\
+\x33\xe2\xc3\x2a\x95\x22\x97\xdd\x5d\x7e\xed\xd7\xbe\xce\xc3\xf7\
+\xcf\xa9\x5b\x55\x32\xd5\x0e\xc5\x46\x41\x9d\x24\xa5\x83\x62\xa3\
+\x04\xa0\x57\xb9\xa4\xda\x5f\x54\x4e\xfb\xfc\x7a\x5d\x39\xed\xcf\
+\xe3\x01\x8e\x85\xb5\x9b\xac\xad\x2d\x25\x81\xa2\x81\x59\x3d\xdf\
+\x33\x66\x8c\x3f\xfd\x39\xf9\xfc\xa4\x62\x25\xc0\x6b\x0d\x6c\xb2\
+\x7d\x9f\x6e\xd8\x4b\xfc\x0d\xf9\x19\x72\x2b\xf7\x97\x8f\x9b\x66\
+\xa4\x72\x28\xa4\xa1\x29\x35\xb3\x6e\xc0\xdd\xbb\x53\x60\x65\xa3\
+\xa1\xf4\xef\x3c\xe9\x20\xc1\xbb\x56\x79\x36\xa3\x8d\x9b\x0b\x63\
+\x9c\xd3\x48\x19\x74\x4f\xf6\x76\xf8\xea\x5f\x3c\xe1\xb5\xd7\xc6\
+\x9c\x1d\xb6\x55\xa2\x50\xdf\xf1\x12\xcc\x2b\xb5\x70\xe8\x04\x4a\
+\xf7\xca\xfb\x2e\x63\xda\x61\x87\x12\x39\xd1\x71\x33\x1a\x2a\x40\
+\xeb\x40\xae\x37\x2b\xfc\xc6\x71\xc4\xff\xf1\xab\xbf\x40\xe7\xbd\
+\xdf\xc4\x98\x74\x31\x87\x23\x3e\xfd\xc2\xdd\x04\x1b\xbf\xe6\x85\
+\xfc\xe1\xd7\xdf\xe4\x6c\xf8\x94\x61\xd6\xa3\xf7\xec\x50\x8d\x1b\
+\x96\x7a\xd8\x1c\x9d\xb3\xc0\x31\x46\x6e\x91\x1b\x05\x5f\x94\x27\
+\xf5\x23\x8c\xa0\xa5\x6a\xfb\x66\xfc\xec\xad\x62\x97\xa8\x3b\xc2\
+\x5e\x88\xb0\xc7\xcb\x53\x46\xd5\xf2\x89\x65\xef\x89\x84\x11\x61\
+\x99\x4a\x72\xd8\xfe\x28\x21\x19\x6c\x7f\x84\x77\x65\x24\xbc\x19\
+\x56\xa5\x42\xbf\x3f\xe0\x77\x7f\xe3\x21\x6f\xfc\xd9\x1f\xa9\x95\
+\x5d\xab\x0b\x4b\xd5\x30\xb7\x38\xe9\x8b\x6c\x2b\xe7\x34\xa2\x57\
+\xb9\x64\x74\xbe\xa2\x00\x7c\xec\x5e\xe0\x9c\x46\x1c\xbb\x17\xec\
+\x7e\xb8\x4d\xaf\x72\xc9\xee\xae\xc9\x72\x5b\x9c\xa0\xcf\x7d\xfc\
+\x0e\x9b\xf7\xee\xd2\xac\x37\xa6\xa0\x95\xe0\x8c\x8d\xb5\x19\x03\
+\x4e\xb2\x63\x7c\x5f\x02\x50\xa6\x48\xa6\x8b\x3b\xa5\x51\x27\xb3\
+\xd4\xe6\x97\xdf\xd8\x09\xe3\xad\x15\x1a\x34\x7b\x41\x82\xdd\xa5\
+\x61\x28\xd9\x77\xb3\x29\x3c\x10\x42\x03\x2f\xcf\x30\xf0\x59\x7f\
+\x90\x00\xaf\x8c\xc8\x25\x0c\xa3\xd3\x0d\xa2\xec\x19\xce\x69\xc4\
+\x1b\xdf\x9d\xf0\xee\x5b\x67\xfc\xc9\xdb\x8f\x79\xb2\xbf\x23\x7a\
+\xbb\x55\x44\xd7\x22\xa1\x69\x05\x98\x25\x20\xa5\x84\x90\x4c\x2c\
+\x25\x84\x18\x8c\x5e\x51\xdd\x8f\x64\x27\x23\xd9\x3a\x4b\x02\xd9\
+\x2c\x67\xa8\x37\x2b\xfc\xc9\x3b\x7d\x3e\xf8\x9d\xa7\x30\x38\xa5\
+\x6a\x3a\x98\x75\x93\xff\xe0\x27\xff\x96\x62\xe3\x56\xdb\xa0\xbe\
+\xd7\xe1\xc3\x37\x9e\xd2\xe9\x74\xa8\xce\x57\x4b\x4a\x4e\x1c\x0f\
+\x2d\x3a\x43\xf1\xe5\xda\xe6\xfc\x9e\x76\xa5\x30\x87\xd9\x1c\xd4\
+\x12\xac\x0a\xd0\x2a\x26\xa7\xf8\xb8\x91\xad\x80\xac\x8a\x49\x87\
+\x1e\x52\x8a\x78\x56\x1e\x23\x6e\x3d\x65\xfb\x23\xa2\x41\x97\x62\
+\x49\x48\x12\x2f\x77\x2e\x02\x24\x83\x90\xc7\x5f\xdf\xe3\xaf\xbe\
+\xf6\x8c\x52\x39\x4b\xa5\x70\x42\xa5\x2c\x9a\xf7\xad\x54\x27\xdc\
+\x5b\x8d\x30\xb5\x6a\x62\x09\x58\xb9\x55\x49\x2b\x71\x2f\x33\xe7\
+\x34\x22\xca\x9e\xa9\x7d\x72\xfe\x19\x9b\xb7\x37\x58\x5b\x5b\xc2\
+\x35\xc7\xb8\xce\x44\x48\x84\x58\xf3\xea\xf7\x13\x97\x7e\x4d\x3f\
+\x5b\x03\x5b\x31\xb0\xd2\xb4\x31\x20\x25\x98\xf5\x8c\xb3\x52\x59\
+\x44\xda\xe4\x7f\xdd\xeb\x20\xdf\x57\x33\xab\xb4\xaa\x99\xc4\xdf\
+\x95\x8d\x4f\x64\x16\x5a\xb6\x5a\xa0\xbc\xa1\x95\x86\xb5\x66\x59\
+\x58\x6a\xe0\xb3\xfe\x60\xc6\x2b\x21\x2f\xbd\x4f\xf6\x07\x7c\xf5\
+\x2f\x9e\xf0\xe8\x9d\x6d\xfe\xf4\xaf\x5a\xd4\xad\x2a\xcd\x5b\xf5\
+\x18\xb4\x05\x35\xfd\xb4\xef\x78\x54\xca\xb6\x92\x0a\x92\x91\x75\
+\x3d\x1c\x3a\x81\x6a\xdf\x25\x81\xad\xb7\xd2\x2a\x91\xa3\xa3\x8d\
+\xa8\x5b\xac\x2c\x11\x98\x4d\xfe\xed\x6f\xbe\x46\x6b\xe7\xf7\x94\
+\xb7\xe2\x53\x5b\x9b\x8a\x8d\xb3\xcb\x0f\x78\xcd\x0b\xd9\x3e\xde\
+\x65\x10\x57\xac\x67\xed\x1b\xca\xc5\x96\xbe\xe9\x57\xe5\x46\xd8\
+\x15\x72\xa2\x1f\x89\x0c\x39\xcd\xc6\x30\x13\xec\x19\xb3\xaf\x3d\
+\x5e\x4e\x30\x6b\x18\xb8\xaa\x82\x59\x37\xde\x24\x50\x75\x46\xf6\
+\xac\x3c\x5e\x54\x13\x9a\x7a\xa9\x4b\x25\x7f\x17\xdf\xb6\x79\xeb\
+\xdd\x0f\xf9\xed\xaf\xfe\x2a\xf8\x3b\x82\x2d\xe5\x17\x6d\x2e\x61\
+\x98\x5b\x1c\x0f\x2d\x56\x0b\x9b\x73\xf5\x90\xfa\xc2\x67\x01\xdf\
+\xce\x95\x67\x72\x04\xa2\xec\x19\x3b\x3b\xaf\xf3\xe2\xca\x33\x3e\
+\xf3\xc9\x2f\x2a\x00\xea\x5a\x77\x86\x7d\xe3\x4b\x7e\xa7\x16\x26\
+\x58\x52\xa5\x48\xc6\xc0\xd6\xfd\xb8\xe9\x5c\x07\x99\x4b\x9c\x76\
+\xb1\xe9\xef\x93\x0b\x60\x5e\x32\x7b\xf3\x56\xc4\xad\x1b\x36\x9f\
+\x5b\xa8\xb3\x5c\x58\x9e\x61\xe1\x46\x3b\xab\xc0\xbb\x5a\xd8\xe4\
+\xac\x3f\x48\x1c\x23\x63\xb2\xc2\x49\xff\x26\x67\xfd\x01\x3b\x7b\
+\x7b\xec\x6c\x9f\xf1\xed\xf7\x4e\xb9\xec\x65\xb5\x63\xdc\x8e\xbd\
+\x0a\xb6\xca\xfd\x10\x3d\xe5\x82\x84\x34\x90\x60\x95\xc0\x34\xcb\
+\x19\xfc\xe2\x28\xf6\x04\xe5\x14\x78\xf5\x4e\xa1\x4d\x6d\xd0\x47\
+\x2b\x6a\x29\xc9\xf0\x07\xff\xf7\x5b\x0c\xdd\x0f\x31\x26\x5d\x72\
+\x8d\xbc\xd2\xc6\x20\xfa\x2e\x77\xbf\x66\x72\xfe\x6c\xba\x10\xcf\
+\x3b\x42\x42\xcc\xbb\x45\x91\xd0\xc2\x41\xc7\x10\x72\xa2\x62\x50\
+\xca\x4c\x12\xc6\x9d\x39\x70\x85\x31\x37\x70\x3f\xba\x34\x4e\xd6\
+\xd2\xcd\xfc\xa1\x41\x97\x81\x2b\x00\x5d\xe8\x9d\x2b\x03\x51\xea\
+\xe3\xc9\xd1\x90\xdf\xfd\xc5\xd7\x68\x1d\x74\xd4\xc1\x14\xa5\x34\
+\xb0\x79\x3b\x43\xb9\xbe\xc3\x8d\x82\xaf\x80\x7b\x3c\xb4\x58\x68\
+\xef\xf1\xe4\xd4\xe0\x78\x68\xe1\x9e\x05\x9c\x0e\x77\xe9\xd6\xf2\
+\x98\x6c\xe3\x9e\x05\xea\x79\x79\x32\x8d\xc9\x0a\xce\x69\xc4\xc7\
+\x36\x2c\x9a\xf5\x06\x43\xdf\xa5\x63\x44\x09\x46\xcd\xd0\x55\x79\
+\x14\x12\xa4\xd9\xbe\xaf\x3c\x04\x7e\xd1\x23\xdb\xf7\x67\x8c\x3c\
+\xdd\xa7\x2b\x1f\xcb\x82\xd0\x34\x0b\x57\xcb\x83\x19\xd7\x9e\x5c\
+\x00\x19\xba\x6a\x18\x8d\xac\x44\x2e\x6f\x18\xb4\x96\x7b\x09\x16\
+\x96\xff\xdb\x8d\xe9\xc2\x3a\x1d\x8a\xa0\x46\x94\x3d\x53\xc0\x3e\
+\x1e\x5a\x98\x6c\xc7\x81\x8b\x6d\xde\xfe\xc0\x4f\x30\xa9\x04\x6d\
+\xa7\x2c\x1e\xf7\x1d\x8f\x86\x59\xc7\x65\xac\x58\x57\x9e\x0f\x09\
+\x54\xf9\x7c\xdf\xf1\x54\x42\x95\x64\x61\xd9\x9d\x53\x7d\xd7\x94\
+\x3e\x5e\xac\x2c\xd1\x6a\x1b\xbc\xfe\xce\xdb\x0c\x9f\xbe\x4f\x68\
+\xb6\xa9\x45\x7e\x42\x1b\x77\x5a\x7d\xde\x31\x77\x78\xed\x8f\xff\
+\x94\xe1\xc9\xb3\xb9\x78\x6a\xe4\x7d\x4e\x9c\x78\x40\xa4\x21\xb4\
+\x70\xaf\x59\xc5\x08\x5a\x49\x16\x0e\x46\xc2\x3b\x21\x19\xb4\x58\
+\x42\x79\x17\xd2\x99\x6b\xba\xac\xb0\x2a\x15\xac\x8a\x81\x67\x09\
+\xe0\x17\x4b\x60\x23\x7a\x32\xd8\x46\x57\xf4\x31\x5e\xea\xaa\x40\
+\x47\x7f\xf4\x94\x5f\xfb\xb5\xaf\x33\x39\x7f\x44\x76\xf9\xc1\x74\
+\x15\x9b\x43\xc5\xc2\x21\xa2\xd3\xbb\x04\xa8\xdb\xda\xe6\x20\x9a\
+\x10\x85\x3b\xd4\xba\x23\xba\xb5\x7c\x82\x81\xba\xb5\xbc\x7a\x5e\
+\xf7\x27\xde\x28\x2d\x51\x7e\x39\xc3\xad\xad\x57\xf0\x82\x20\x61\
+\x60\x89\xcc\xb5\x38\x49\x29\xe8\xab\xdc\x5f\xf9\x58\x82\x52\x37\
+\xd8\x66\x18\x3a\x7e\x6c\x0d\x6c\x8c\xa0\x9f\xe8\xe2\x23\x75\xae\
+\xac\xbc\xd0\x17\x81\xde\xea\x35\x43\x97\x5a\x46\x00\xf8\xfe\x03\
+\x53\x05\x75\x94\xad\xd1\x64\x46\x13\x57\xba\xb7\x66\xdc\x6a\x67\
+\xfd\x01\x6e\x6b\x9b\xf7\xde\x09\x78\xe3\xdb\xef\xf1\x64\x6f\xa8\
+\x64\x41\xb7\xd8\x57\x8c\x1a\x99\x15\xb2\xce\x58\xe9\x5a\x09\x38\
+\xc9\xbc\xb2\x62\x5b\xea\x5c\xf9\xbc\xde\xff\x58\xb2\xb0\x5e\x4d\
+\xa2\x7f\x9e\x32\x10\xa3\xa7\x64\xaa\x1d\xbe\x75\x60\xf1\xc1\xef\
+\x3c\xc5\x74\x46\xc2\xc8\xd3\xb4\x71\x76\xf9\x01\x97\x3d\xb1\xe8\
+\x5e\xff\xf6\x37\x94\x61\x97\x0e\x7c\xac\x95\x0d\xdc\xb3\x80\xa8\
+\xd2\xc4\x08\x5a\xd0\x8d\x65\x5e\x26\x36\xa4\x8b\x39\x4a\x99\xbc\
+\xf0\x4e\xd8\x46\x97\x68\xd0\x55\x6e\xb5\xc2\x45\x2d\x61\xbc\xc9\
+\x66\x28\x6e\x24\xaa\x9a\xc3\x41\xa8\x5e\x93\x72\xa2\x15\xf9\x71\
+\xe2\xce\x94\x81\xbd\xdc\x39\xfd\xd1\x19\x5f\xff\x8d\x90\x87\xef\
+\x9f\x93\x5d\x7e\x40\xa5\x70\xa2\x19\x3c\xe2\xa0\xe4\xce\x2f\x71\
+\x5b\xdb\x6c\x1f\xef\xd2\x6f\x4d\x07\xf0\x19\xe6\xd6\xf4\x72\x11\
+\x6b\xe5\x5a\x77\x44\xc8\xfd\x84\x76\x06\xd1\x9f\xe0\x46\x69\x89\
+\x5e\xe5\x92\xd5\xae\xc9\x46\xa3\x45\x79\xb1\xa9\xdc\x57\xd2\xa3\
+\x20\x7d\xbb\x72\x4b\xaa\xf8\x72\x52\xb1\xa6\x9a\x38\x96\x14\x92\
+\x45\xab\xbe\x93\x78\x8f\x94\x11\x12\xf8\xf5\xc8\x98\x61\xef\xf4\
+\x63\x05\xe0\x8d\x86\x1a\xdf\x25\x01\x2c\x41\x2b\x59\xb8\xd1\x9e\
+\x32\x4e\x71\xfd\x32\xa1\x89\x85\xf7\x21\xab\xe4\x03\x7d\x61\xfd\
+\xcb\xa0\x85\x6c\xb6\xdd\x29\x43\xd6\x19\x33\x29\xe7\x14\xf0\x74\
+\x90\x96\xc8\x29\xb6\x95\x3a\x57\xbe\x26\x41\x9a\xbe\xf5\x8d\x02\
+\x7e\x71\xa4\x5e\x4b\xba\xec\xaa\x6c\x36\x57\xe9\x5e\xb5\x79\x6b\
+\xcf\x65\xec\xff\x99\xd2\xc6\x77\x63\x6d\x3c\x39\x7f\x84\x6b\xad\
+\x27\x5b\x2a\xd8\x70\x9a\xba\xc8\x1b\xb9\x45\x4a\x2b\x19\x8c\x7e\
+\x8b\x28\xd3\x24\xac\x76\x84\x9b\x2d\x66\xe2\xd2\x60\x3c\xf5\x13\
+\x7b\x51\x2d\xa1\x71\x8b\x25\x91\x18\x5f\xb1\x4c\xdc\xc8\x06\xca\
+\x98\x99\x92\xea\x02\x34\xf5\xaf\x65\x12\x39\x16\xc5\x12\x4a\x3e\
+\xb4\x27\x36\x95\xfc\x0a\xdd\x77\x07\x22\x86\xee\xef\x30\x29\x1c\
+\x29\x57\x4e\x8b\x80\xa6\x39\xe4\xd4\x83\x0f\xdc\x36\x67\xbd\x2c\
+\x67\x3d\xf1\xe5\xa2\x70\x87\xb3\x5e\x56\x0c\xe3\xcb\xdc\x4a\xb0\
+\x70\xb7\x96\xe7\x46\xc1\x27\xe4\x7e\xc2\x11\x0e\x28\xe3\xef\xd0\
+\x35\x58\xad\x6f\x24\x7c\xc0\xf3\xd8\x75\x5e\x70\xc2\x08\xfa\x09\
+\xc3\xad\xea\x3b\x8a\x59\x7b\x56\x99\x52\x39\xab\xc0\xac\x03\x35\
+\xad\x87\x75\x2f\x87\xee\xda\xab\x65\x6a\x34\x6b\x36\x6b\x65\x43\
+\xb9\xd2\xce\x87\xe7\x09\x63\x4e\xb2\xf0\x41\x34\x49\xb0\xae\x2e\
+\x37\x9e\xec\x65\x79\xf2\xf4\x30\x21\x1f\x24\x40\xa5\x1c\x70\x19\
+\x2b\x00\xeb\x06\x9b\x04\xb4\xce\xc6\xe9\xed\xdc\x3a\x40\x5f\x74\
+\xd6\x9c\xf8\x43\xd5\x99\x3e\xbd\x7f\xa7\x4c\x9c\x8b\x01\x27\xef\
+\xfc\x25\x7f\xf5\x97\x21\x70\x85\x31\xe9\x72\xb7\x9e\xe1\xcb\x3f\
+\xf4\x22\xcd\x4f\xff\xdd\xf8\x12\x71\x83\xb3\xb8\x6d\x47\x1a\xc0\
+\x13\xef\x38\xf1\x9c\x11\xb4\x30\x0d\x69\x0b\x39\xb8\x41\x16\xb7\
+\x38\x0d\x6c\x99\x00\x5e\x54\x53\x8d\xb5\x3d\x2b\x8f\x9b\xcf\x29\
+\xc0\xda\x9e\x8b\x59\x14\x4d\x54\xb2\x14\x09\x03\x57\x05\x33\xa4\
+\x9c\x90\x1e\x0a\x29\x45\x1a\x59\x8f\xd3\xc3\x36\x7f\xfe\x8d\xc7\
+\xe0\xef\x80\x15\x5b\xa7\xce\x98\x6e\xb1\x2f\x1c\xeb\x61\x81\x95\
+\xcc\x34\x59\x7b\x83\x67\x9c\xf5\xb2\xe4\x2f\xab\xac\xc4\x3d\x74\
+\x4b\x2b\x99\x84\x85\x7a\xa3\x20\x1a\xde\x01\x8c\x4e\x8e\x66\x13\
+\xaa\x4f\x23\x96\xdb\xed\xc4\x68\xd5\xeb\x8a\x2f\x55\xb2\x79\xec\
+\x41\x90\x2d\xa3\x74\xab\x37\x30\x9b\x33\xb9\x0f\x41\xbd\x81\x5f\
+\xf4\x12\x0b\x62\x52\xb1\x12\xbe\x66\xe9\x86\xd3\x17\x49\xa6\xda\
+\x49\x64\xa3\xe9\xf9\x21\x69\x26\xd6\x1f\xa7\x75\xf2\xee\x7e\xc0\
+\xa3\x77\xb6\x39\x39\x0a\x12\xec\x28\x99\x31\xcd\xb4\x52\x4a\x28\
+\xd7\xa1\x33\x9e\xd9\x6f\xc6\x80\x8e\x35\x70\x1a\xa4\x12\xc8\x66\
+\xd4\x4b\x68\x6f\xa9\xb9\xf5\xc5\xf2\x9a\x17\xf2\xc1\x6b\x5f\xe3\
+\xea\xd1\xd5\x54\xeb\xbe\xf2\xb2\x62\xe3\xcb\xfe\x85\xaa\x9b\xd4\
+\x6f\xa7\x9e\xf0\x58\xe8\xd8\x88\x32\xcd\x79\xe9\xf3\x74\x7a\x3e\
+\x54\x23\x21\x27\x8a\xa5\x64\x32\x4f\x18\xb8\x62\xc8\x4c\x51\x54\
+\x2d\xdb\x9e\x41\xce\xb8\x4a\xf8\x81\x7d\x1c\x8c\x5a\x1e\x8b\xa9\
+\xb7\x40\x32\xf1\x65\xa7\xc3\x77\x7e\xe7\x1b\x3c\x7c\xef\x4d\x4a\
+\xe4\x98\x14\x8e\x14\x2b\x58\x83\x7c\xac\xc3\xda\x53\xf1\x9e\x7b\
+\xc6\x21\xc2\x47\x3c\x5a\x14\xc3\x03\x6f\x64\x6e\xcd\xb8\x90\xdc\
+\xb3\x80\x4a\xf7\x16\x83\x4e\x40\xbb\x31\xa1\xd6\x1d\x71\x3a\xdc\
+\x4d\x78\x32\x0e\x83\x52\xa2\x9b\x4c\x3a\xa0\x21\xc1\xaa\x4b\x0a\
+\xf9\x5a\xda\x7d\xe6\x9a\x63\xaa\xe5\x41\xc2\x78\xd3\xc1\x2e\x19\
+\xb7\x1e\x89\xd2\xf1\x6e\xd8\x4b\x84\x91\x75\xc6\xae\xd5\x6b\x6c\
+\xd5\xfa\x8a\x81\xd3\x01\x0d\xdd\xad\x26\xef\x4b\xe0\x02\x9c\xf5\
+\xb2\xec\xee\x07\xca\xfb\xa0\x03\x71\xe2\xcf\x02\x2e\x0d\x52\xe9\
+\x69\x90\x7e\x62\x5d\x36\xcc\xc4\x00\xa2\xa4\x01\xa7\x37\xf4\x96\
+\xc6\x9d\x94\x1b\x69\xf6\x07\xa8\x2c\xde\xa6\x7b\xd5\xe6\xf5\x77\
+\xde\xc6\x3f\x79\x08\x03\x11\x02\xff\xfc\xed\x1a\xaf\xbe\xb8\x44\
+\x76\xf9\x01\xae\xb5\x4e\x7f\xb8\xc6\xa4\x37\x64\x74\x3a\x5d\x90\
+\x2b\x99\x4b\xa5\x93\xd3\x1e\x2a\x11\xb1\x2b\x53\x1a\x8c\x99\xb8\
+\x19\xea\x55\x2b\xd6\xc4\x2c\x10\x0d\xba\x2a\x60\x21\xdd\x65\x22\
+\xe1\xa7\xac\x65\x45\x15\x15\x3b\x5b\x94\x45\x07\x79\x3f\x1b\x97\
+\x33\x25\xb3\xd6\x76\x8f\x1c\x5e\x7f\xa7\x05\xd6\x56\x22\x46\xdf\
+\x8c\x5b\xde\x34\xcc\x88\x96\xd6\x01\xaa\x79\x3e\x8d\xc7\x4b\x29\
+\x71\x1c\x1c\x70\x3c\xb4\x14\x48\x4d\xb6\x39\x89\x2c\x8e\x83\x03\
+\xa2\x70\x87\x7e\x0b\x8e\x83\x03\x2a\xdd\x5b\xca\x7a\xd7\xeb\xb4\
+\xb2\x7d\x3f\xd9\xc0\x4f\x73\xaf\xc9\xfc\x07\xbd\xe2\xb8\x14\xe6\
+\xe6\x06\x30\xf4\x26\x28\x52\x2f\x4b\xc3\x50\x06\x36\xf4\x90\xb4\
+\x0c\x43\xeb\x4c\xdd\xac\xc3\x67\x1a\x3e\x85\x17\x85\x4b\x50\x4a\
+\x88\xe7\xdd\x74\x50\x9f\xf5\x84\x7c\xf8\xf6\x7b\xa7\x74\xfc\xa4\
+\x01\xe6\x32\x4e\x34\x51\xd1\x8d\x2e\xb9\x9f\xae\x7d\xe7\x01\x3d\
+\xdd\x02\x40\xba\xd2\x74\x96\x96\x7f\x23\x6b\x89\xd7\x24\x53\xeb\
+\xfe\x62\xfd\x6f\x06\x66\x93\x6f\x1d\x58\xec\xbe\xf9\x94\x8b\xc3\
+\x7d\x8c\x89\xb0\xbb\xbe\xf0\x7d\x2f\x2b\x77\x5b\xc9\x3f\x52\xa1\
+\xeb\xd0\xbb\x20\xf4\x2e\x30\x72\x8b\xb3\xdf\x33\x0e\x37\x8b\x88\
+\x9d\x43\x27\x0a\xc8\x96\xa6\xc0\x37\x3b\x97\x27\x4a\x1a\x78\x57\
+\x46\x22\xf9\xc7\xf2\x2e\x54\x98\x59\x6f\x6f\x35\x4d\x49\x9b\xad\
+\xd6\xbd\x68\x89\x1f\x5b\xbe\xd9\x67\x52\x38\xa2\xef\x78\xea\x12\
+\xd6\x8e\xbd\x03\x7d\x47\x4c\xa3\x97\xfd\xcd\x74\x17\x93\x3c\x69\
+\xf9\xcb\x2a\x6e\x6b\x9b\x7e\x4b\x18\x74\xfd\x96\xd0\xcb\x72\xa2\
+\xbc\xdc\x9e\x44\x02\xe0\x12\xcc\x1b\x19\x97\xa8\x78\x53\x01\x4e\
+\xca\x87\xeb\x72\x22\x54\x10\xc4\x1c\xcf\x78\x27\xd2\x59\x68\x3a\
+\x78\x3b\x46\xa4\xb2\xd7\xa6\x33\x9c\x67\x33\xe7\x36\x6a\x59\x56\
+\xea\x0d\xfc\xd2\xb2\x92\x0f\xd7\x25\xf6\x28\xbf\x69\x0c\xf2\xf3\
+\xe1\xb9\x02\xf0\xd9\x61\x5b\x8c\x5b\xb0\x92\xb3\x42\xd2\x63\x0f\
+\xd2\x0c\xab\xdf\xaf\x94\x87\x6a\xd6\xc8\x3c\xcd\xab\xfa\x18\xc7\
+\x21\x6a\x1d\xe4\xb2\x45\x01\x88\x76\x01\x62\xc2\xd3\x73\x16\x45\
+\x4c\x1a\x27\x1f\x3e\xc3\xcd\xf7\x08\xcd\x36\x95\x7c\x86\xc6\x0b\
+\x5b\xca\xdd\xe6\xb4\xe4\x57\x92\x00\x00\x20\x00\x49\x44\x41\x54\
+\x5a\xeb\xca\x28\x3c\xeb\x88\xf6\x62\x69\x7d\x3c\xe2\x4c\x85\x9b\
+\xaf\x8a\x13\x26\x6e\x66\x0a\xe0\x58\xd6\x9a\xe1\xc2\x92\x72\x8f\
+\xd9\x86\x08\x41\xcb\x00\x86\xcc\xfd\x95\x00\x96\x92\x43\xb2\x6f\
+\x1a\xd8\x51\x77\x44\xe0\x4e\x3d\x10\xd9\xe1\xba\xba\x94\x4d\xfc\
+\x61\x82\x0d\x4c\x6b\x05\xfa\x10\x8d\x2f\x71\xcf\x16\x18\xb4\x87\
+\x0c\xda\xe2\x00\x0e\xda\x43\x3e\x70\xdb\xf8\x07\x43\xce\x7a\x59\
+\x8e\x83\x69\x0b\xcd\x83\x9c\xc7\x59\x2f\xcb\x68\xb1\xa7\x0c\xc1\
+\x4a\xf7\x16\xfd\x9a\x60\xee\x5e\xe5\x92\xcd\xdb\x1b\x2c\x65\x92\
+\xbd\x80\x75\x60\xea\x9a\x55\x07\x72\x9a\x89\xd3\x41\x8c\x74\xe2\
+\x8f\x8c\xcc\xb9\xce\x44\x19\x80\xd5\xf2\x80\x6c\xdf\x27\x43\x97\
+\x6a\x79\x30\x63\xc8\xcd\xbb\x55\x9a\x49\xe0\x4a\x83\xcf\x3d\x5b\
+\x50\x00\x16\x33\x38\x0a\x33\xc0\x9b\x07\x64\x1d\x4c\xba\x97\xa1\
+\xef\x14\x94\xbf\xf7\x3a\xa3\x4d\xee\xa3\x0f\xd6\x91\x7f\xb7\x1e\
+\x19\xea\xb1\x7e\x25\xa8\x3b\xd3\xbf\x23\x3f\xbb\x6e\x55\xe9\x06\
+\x5d\x1e\x05\x63\xf2\x7b\x87\xca\xc0\x03\x78\xf5\xc5\xa5\x44\xa4\
+\x4f\xca\xa3\xe3\xb1\xa7\xb4\xf0\x89\x13\x71\xa3\xe0\x33\xf1\xb7\
+\xb8\x8a\x9b\xa9\x64\x5c\x93\x6c\x29\xa0\x34\xc8\x31\x71\x33\x8a\
+\xa1\x55\xc4\xce\x8b\x6a\x78\x51\x0d\xdb\xe8\xce\x00\x73\xc6\x8f\
+\x37\xb1\x67\xb6\x97\x9d\x0e\x57\x91\xc7\xee\x91\xc3\xde\x5b\xef\
+\x63\x5c\x39\x4c\x0a\x47\x31\x18\xf2\xea\x80\xe8\x07\xb0\x1b\x74\
+\x39\x71\xa2\x38\xed\xee\x4a\x01\x58\xe9\xdb\x28\x8b\x91\x7b\xa6\
+\xd8\xf9\xac\x97\xe5\xd6\xd8\xe6\xd6\xd8\x56\xde\x0c\xc3\xdc\xe2\
+\x38\x38\xc0\xe9\x6c\xb1\xd0\xde\xe3\x9d\xb7\x77\x18\x9e\x3c\x53\
+\x56\xb8\x0e\x44\x09\x60\xd1\x10\xdb\x4b\xe4\x44\x74\x6a\xa1\x8a\
+\xac\xcd\xcb\x87\x48\x34\x3d\x29\x67\xc9\x74\xda\xca\x07\xac\xbf\
+\xa7\x15\x1a\xca\x2d\x27\x73\x22\x9e\x07\xe0\xf3\xe1\x79\x42\x3a\
+\xc8\xe7\x9c\xc3\x88\xe3\xd6\x05\x8f\xf7\xf6\x12\x43\x67\xf4\x63\
+\x98\xb5\x0a\x33\xcc\x3c\x4f\xc7\xea\xa0\xee\x1b\x05\x05\x58\xf9\
+\x3f\x6b\x15\x08\xfd\xb3\x29\x90\x8d\xe7\xb3\xfd\x75\x8b\xa6\xe3\
+\xf7\x94\x7d\x61\x46\x3d\xe8\x84\x1c\xb7\xb6\xd9\xdb\x1f\x13\xb6\
+\x62\x9f\xb8\x0d\xab\x8b\x0b\x4a\x52\xe8\x89\x48\x0b\xed\x4b\xce\
+\x02\x21\x27\xa4\x0b\x72\xc8\x10\xc3\x89\x08\x4a\x71\x43\x1f\x37\
+\xa3\xe4\xc4\xc4\xcd\x4c\x2b\x3b\x8e\xc2\x9c\x02\xaf\x04\xb2\x8c\
+\xbe\x19\xb5\xfc\x0c\x90\x0b\xa5\x7d\xe5\x85\xf0\x72\xe7\x34\xb2\
+\x02\x08\x12\xc0\x0f\xdf\x7b\x93\x16\xc2\x5a\xd5\x5d\x3a\xfa\x41\
+\x50\x07\xa8\x37\xe4\xc4\x89\x70\x0e\x93\x55\x21\xd1\x58\xac\xc8\
+\xf5\xb1\x00\xb0\xf4\x58\xe8\x65\x49\x80\x1a\x15\x15\x85\x3b\x7c\
+\xcb\x13\x1e\x8e\xa7\x1f\xfe\x85\x00\x9f\xd6\x32\x55\xca\x00\x1d\
+\xc0\x7a\x80\x43\x1a\x75\xe9\xe0\xc6\x3c\x9d\x2c\xbd\x14\x7a\x25\
+\xb5\x9e\x23\x0c\x62\x08\xa3\x34\xe4\x74\xc6\xfd\x28\xf9\x20\x82\
+\x37\x0b\x7c\xe7\xa8\xc5\xd9\x61\x5b\x31\xbc\xce\xc2\xcf\x03\xae\
+\x0e\xcc\x79\x52\x43\x67\x57\xfd\x33\x03\x6a\xaa\x29\xb7\xfe\x19\
+\xe9\x5b\xa2\x03\xe7\x75\xee\xb8\xd6\x48\xc9\x8d\xc3\x68\x89\x63\
+\xf7\x82\xf6\xd9\xd4\x0b\x51\xbf\xbb\xce\xad\xaa\xa3\xc2\xd5\x7a\
+\xec\x40\xf7\x56\x1c\x0f\x2d\x2a\xd6\x31\xa6\x51\x26\xe3\x9a\x04\
+\xa5\x90\xba\x91\x21\x28\x85\xd3\x8c\xb6\x6a\x24\x40\xbc\x60\xd8\
+\xd0\xac\xce\x0f\x29\xc7\x3d\x29\xa4\xfb\xac\x3d\xb1\x95\x17\x22\
+\xea\x8e\x18\xba\xb7\xb9\xec\x08\x2b\xcd\x3f\xda\x65\xbf\xfb\x14\
+\xac\x2d\x31\x32\xab\x3c\xbb\x72\x3b\x86\x68\x3b\x25\x0f\x5c\xab\
+\x3b\x1d\x50\x28\x81\xab\xdf\x0e\xb9\xc9\x4a\x75\x32\x03\xe4\x85\
+\x4e\x9f\xdd\x7d\x41\x51\xbb\xfb\x01\xbb\xfb\x01\xcd\xf3\x2a\xee\
+\xd9\x11\x7f\xfe\xc1\x00\x3a\xbd\x19\x8d\xab\x1b\x67\x12\xd0\xcf\
+\x73\xc3\xc9\xe8\x9c\x0e\x64\x09\x6c\xf9\x79\x3a\x80\xd3\xfe\xe0\
+\xc2\x8b\x2b\x09\x0d\xac\x33\xee\xf9\xf0\x3c\x61\xe0\x45\xe3\x38\
+\x83\xef\x30\x62\x7f\xef\x50\x69\xcf\xeb\xd8\xef\xa3\x9e\xbf\x8e\
+\x34\xd2\x8b\x20\x0d\xe4\x34\x18\xaf\xfb\x7b\x92\xad\x13\x2e\x3a\
+\x2d\x53\x50\x1a\x77\x67\x87\x6d\xe5\x0e\x0d\xcd\x27\x54\xf2\x19\
+\x6e\xd7\x16\xa8\xac\x88\x41\x06\xd1\x82\x00\x49\x7f\xb8\xa6\x48\
+\x4d\x77\xa9\x4e\xfc\x2d\xea\x46\x3c\xd0\x87\x88\x4e\x14\x90\x71\
+\x4d\xc5\xc6\xae\x33\xc1\x1c\x2e\x75\xb9\x8a\x3c\x91\x37\xbc\x94\
+\x64\x63\x19\x42\x8e\xba\x23\x15\xc9\x2b\x94\xf6\x13\x09\xf4\x6b\
+\x76\x5b\xb1\xf0\xd1\x33\x0f\xe7\x59\x05\xfc\x1d\x2a\x65\x9b\xc6\
+\x42\x8d\x97\xd6\x56\x55\x7a\xa4\xd4\x55\xed\x7e\x98\x90\x14\xad\
+\xae\xa7\xdc\x6d\x3a\x90\xa3\xf1\x25\x46\xee\x19\xfe\xc1\x50\x49\
+\x0a\x29\x39\x0e\xa3\xd8\x30\x3b\x9b\xfa\x8b\x0f\x46\xe2\xfb\x77\
+\x3a\x7d\xae\x3a\x9d\xb9\x27\x54\x7a\x0f\xd2\x0c\xab\x3f\xd6\x19\
+\x3a\x1d\x8e\xd6\x47\x7a\xc9\x5c\x0b\x23\xe8\x8b\xdf\x17\x37\x38\
+\x59\xd9\x68\x70\xfb\xce\xc6\x47\x1a\x6e\xd3\xc4\xa6\x05\x8c\xdc\
+\x33\x9e\xee\x2d\x70\xe2\x44\xec\xb6\x4e\x13\xde\x9b\xff\x3f\xc0\
+\x9d\x07\xc4\xb4\x1c\x79\xee\xe7\xc5\xf3\xf0\x5c\x67\x22\x16\xaa\
+\xe6\x07\xd7\x59\x5e\x77\xf3\x51\x8d\x12\x95\x31\xcd\x46\x44\xf7\
+\xaa\xcd\x69\xf7\x19\xfe\xc9\x43\x25\x29\xac\x85\x29\x61\x3a\xcf\
+\x84\xbb\x52\x46\x73\x2f\x7b\x59\x46\xa7\x41\xc2\x4b\xd1\x89\x02\
+\x25\x25\x80\x84\xb4\x28\x95\xb3\x98\x7a\x98\x59\x32\xac\x04\xb0\
+\xfe\x9c\x64\x63\xf9\x58\x26\xd0\xb7\x4d\x21\xba\xf7\xf7\xb6\x71\
+\x76\x0f\x15\x80\xa3\x85\x32\xb7\x6f\x35\xd8\xbc\x77\x97\x5b\x5b\
+\xaf\xd0\xa9\x85\x73\xfd\xb1\x41\xaf\x1e\x5b\xa7\xc2\x6f\x7c\xe2\
+\x44\x09\x0b\xd5\x39\x8c\x38\x8c\xb2\x0c\xda\x43\xdc\xb3\x23\xdc\
+\xb3\x23\xa2\xf1\xa5\xfa\x2f\xc1\x2e\xef\x97\x56\xd6\xe7\xea\x5a\
+\xbf\xe8\x31\xa9\x58\x89\x82\xcf\x79\x60\xd6\xbf\x9f\x5f\xf4\x04\
+\x40\xb5\x1c\x60\x1d\xc0\x51\xa6\x92\xa8\x93\xcb\x54\x3b\xa2\xbc\
+\xa8\x6c\x50\x5a\xb9\x9a\x09\x64\xe8\x00\x96\xf2\x49\xdf\x9e\x9c\
+\x3c\xe6\xd1\x9e\x90\x10\x59\xab\x90\x60\xf9\xef\xe5\xfe\x5f\x07\
+\xe8\xcf\xf3\x6e\x48\x63\x57\x5e\x6d\x16\xa2\x5e\x02\x9c\xcf\xfb\
+\x6c\x5d\x8e\xf5\x8d\x02\xd4\x4d\x06\x9d\x2a\xef\xb5\x8e\xe3\x64\
+\xad\x2e\xb5\xb0\x97\x30\xee\xd2\x49\x4b\x18\xc7\x1c\xb7\xa6\xb2\
+\x22\x8c\x92\x25\x5e\x19\xad\x35\x82\xeb\x4c\x84\x9c\x58\x37\xc7\
+\x44\xdd\x91\x48\x8e\x37\xba\x1c\xc5\xa5\x3b\x92\x99\xa5\x2e\x96\
+\x00\x1e\x2e\x75\x29\x5c\xd4\x54\x9e\x84\x7f\xd2\x21\x3a\x9b\xb0\
+\xdf\x7f\x06\xd6\x16\x2b\x75\xb8\x91\x13\x27\xdb\x58\x0d\xb9\xf3\
+\xb9\x8f\xb3\x94\x7f\x89\xa3\xc9\xe5\xcc\x6a\xcf\x54\x3b\x62\xfe\
+\x71\x1f\xe5\x72\x5b\xc9\x08\x81\x2f\x45\xbe\x0e\x52\x79\x93\xcc\
+\x9d\xde\xee\x1c\x0f\xa1\x5e\x55\x1d\xd9\x75\x90\xea\x7a\x38\x3d\
+\x1c\x66\x1e\x2b\xeb\xaf\xe9\xc0\x4e\xcb\x11\xd7\x99\x90\x09\x5b\
+\x6c\x36\x57\x79\x75\xbd\xa9\x74\xb0\x1e\x85\x3b\xeb\x65\x95\xc1\
+\x26\x81\xbb\xeb\x0f\xd4\xef\xfb\xce\x51\x04\xfd\x24\xc8\xe4\x40\
+\x46\x79\x05\xd1\xef\xcf\x2b\x8f\x9a\x07\xe8\x4e\x2d\x7c\x2e\xd8\
+\xaf\x03\xa2\xaa\x02\x8f\x8d\xd5\xef\x65\x41\xe8\x59\x83\x7a\x6e\
+\xf5\x71\x4b\xe4\xba\x48\x5d\x1c\x99\xd5\x19\xe3\x4e\x37\xf0\x2e\
+\x7b\x59\x65\xd8\x95\xad\x64\x7a\xa5\x04\xb4\xdc\x2a\xc3\x4e\xca\
+\x07\xc9\xc0\x0b\x86\x9d\xd0\xc4\x51\x77\x34\x95\x1a\xb9\x73\x05\
+\x60\xc9\xc6\xbb\xfb\x87\x7c\x67\x47\xf4\x98\xbd\x6d\x8f\x30\xed\
+\x25\xb2\xab\x05\xd6\xcb\x37\xb9\x73\xcb\xe2\xde\xc7\xee\xf3\x89\
+\x1f\xbd\x49\x79\xb1\xa9\x26\xd1\xab\xd0\x6e\xac\xc3\xe4\x20\x6f\
+\xc9\xc8\xd2\xf9\x2d\xd9\x19\xe0\x2c\x58\x54\xf7\xd3\x80\x9e\xf4\
+\x86\x1c\x1c\x7b\x9c\x9c\x3c\xc6\x08\x45\x86\x59\x7a\x98\x8b\xee\
+\x61\x90\x1e\x04\xbf\xe8\xcd\x14\x73\x4a\xd6\x95\xfb\xcb\x13\xa3\
+\xfb\x8d\xf5\xc7\x55\xdf\xa1\xb6\xd0\x48\x78\x22\x96\x0b\xcb\xf4\
+\x5b\x53\xe6\x35\x72\xcf\x70\x0e\x23\x1e\xfb\xcf\xd4\x6f\xf0\xb7\
+\x0b\x9c\x38\x11\xdf\x39\x6a\xd1\x0e\x3b\x4a\x03\x77\x8c\x68\x2e\
+\xe8\x74\x20\xab\x63\x28\x2f\xf7\xa9\xd7\x75\xf9\xa6\x6f\xbf\x57\
+\x30\xa7\xf3\x4e\xbe\x17\xb6\xd7\x17\x94\x7c\x6d\xe8\xbb\xec\x74\
+\x2b\x38\xa7\x11\x9d\xa1\x43\x68\xb6\x29\xd8\x49\xe3\x4e\xea\x61\
+\x3d\xc3\x4e\x1e\xa3\xab\x8e\x99\x00\xad\x69\x94\x09\x23\x47\xe5\
+\x52\xa8\xa4\x78\xf3\xea\x82\xa3\x30\xc7\xe8\x72\xac\xbc\x14\x57\
+\x91\xa7\x74\xb0\x64\x5c\xc9\xc6\x92\x99\x0b\x17\x35\xae\x22\x8f\
+\xa3\x67\x22\xa0\x51\x29\xdb\x64\x6b\x49\x7f\xd1\xde\x81\x4f\xe0\
+\x9e\xb0\xbe\x6e\x26\x58\x2d\x1d\x7c\xe8\x39\x45\xba\x9d\xee\x8c\
+\xb8\xd7\x81\x2a\x2d\x57\xf9\x03\x0f\x8e\x85\x51\x38\xe9\x0d\x69\
+\x85\x9e\xf8\xdf\x81\x4e\xa7\xab\x66\x64\x5c\xc7\xb4\x3d\xa7\x48\
+\xd5\x77\xc4\x90\x18\x6d\x30\xcc\xdc\xf0\x73\xaa\xbf\x84\xee\x72\
+\xab\x96\x07\x50\x37\x55\x7d\x5c\x22\x68\xb3\x28\x02\x30\x6f\x39\
+\x7b\x42\x2e\x38\x11\x85\x73\x41\xcf\x8f\xfd\x67\x6a\xd1\x02\x6a\
+\xf6\x47\x1a\xb0\x3a\x30\x5d\x67\xa2\x80\x22\xbf\xe3\x44\x1b\xa1\
+\x9b\xb8\x55\x93\x8f\xd3\x2c\x9e\xce\xed\xb8\x8e\x91\xd3\x36\x41\
+\x22\xd3\xac\x6a\x24\x5d\x79\x73\x3e\x6b\x99\x88\x56\xd7\x53\xc6\
+\x9d\xe9\x8c\xa8\xe4\x33\x34\xfd\x48\x19\x77\xa5\xb8\xff\xb4\x64\
+\xe2\x79\x9e\x0f\x09\x5a\x09\x60\x5d\x62\x98\x57\x91\xc7\x45\xb3\
+\xcc\xba\x29\xa6\x8a\x1e\x85\x39\xae\x22\x8f\x75\x73\xcc\x55\xe4\
+\xa9\x5c\x08\xdb\x17\x6c\xdc\x9e\xd8\xca\xb0\x1b\x2e\x75\xf1\x2f\
+\x2b\xec\x77\x9f\x72\x11\x78\x44\x0b\x65\xf2\x9b\x1b\x64\x57\x85\
+\xe5\x6a\x0c\x9e\xc1\xce\x09\x4f\xf6\xde\xe5\xe8\x28\xa4\x5e\xab\
+\xcd\xd5\x4f\x32\xdf\xb6\x15\x1a\x74\x3b\x5d\x76\x5b\xa7\x2a\xc3\
+\x49\x02\xba\x5f\x38\x56\xf7\xd3\xc0\xdd\xef\x45\xf4\x9d\x42\xa2\
+\xc9\x89\x1c\xee\x22\x07\x1e\x02\x34\x7b\x41\x82\x8d\x75\xf0\xce\
+\xd3\xc9\x7a\x7e\xc5\xf3\xea\xea\x36\x9b\xab\x33\xa9\x95\xe7\xc3\
+\x73\x31\xfc\x1c\x31\x10\xf2\xc4\x89\x38\xeb\xb4\x69\x85\x62\xe1\
+\x15\xce\x9b\x9c\x75\xda\xb4\x43\x23\x61\xc4\xe9\x40\xd5\xb7\x7a\
+\xf1\xaa\x7e\x5f\x26\xf5\x1b\x41\x3f\x31\x0b\x5a\xff\xde\xf2\x33\
+\x25\x6b\xcf\x63\x58\xd7\x99\x90\xa1\x9b\xcc\xc0\x0b\x73\x2a\x45\
+\x75\x1e\x80\x75\x03\x7d\x26\x33\xb0\x27\x00\x1e\xd4\x1b\xca\xb8\
+\xeb\x5f\x5e\xe0\x8f\xe3\x29\x5c\x0b\x9a\xe1\xd6\xea\x27\x24\x45\
+\xdf\x28\xa8\x73\xed\xc5\x73\xf5\xc2\xc8\x49\x00\x58\x07\xb2\x59\
+\x5a\x1e\xb3\x58\xaf\x2b\x1d\xbc\x6e\x8e\x59\x30\x6c\x8e\xc2\x9c\
+\x02\xf2\x82\x61\x73\xe8\x08\x66\x96\x3e\x62\x10\xb9\xc7\xd6\x62\
+\x1f\xc3\x78\x85\x7a\x64\x28\x1d\xac\xdc\x63\xa1\xd0\xa8\x3b\xaf\
+\xef\x32\xde\x13\xef\x93\x39\xbe\xe9\x03\x23\x67\xba\x49\x40\x77\
+\x3b\x7b\x89\x93\x2e\x26\x16\x4d\x99\xab\x15\x7a\xf1\x7e\x5d\x11\
+\x12\xed\xf4\x13\x4c\x20\x87\xbb\xe8\x33\x33\xa8\x9b\x33\x2e\xb3\
+\xe7\x69\x61\xfd\xf3\xf4\xf2\x24\x7d\x9f\x5a\xa6\xa6\x1a\x5d\x8b\
+\x61\xe7\xd3\xdb\xae\x3f\xc0\x39\x8c\xe8\x46\xef\x72\xd6\x69\xd3\
+\x34\x6d\xf5\xdd\xe5\x55\xc3\xec\x25\xdd\x10\x93\x8a\x95\x60\x5e\
+\x1d\x20\x69\x2d\xac\x57\x5e\xeb\xad\x04\xe6\x85\xd8\xd3\x9f\x21\
+\x35\xaf\x9e\x52\xaa\xe7\x89\x7c\x94\xa4\x88\x7a\x11\x8d\x8a\x99\
+\x04\x70\x2c\x61\x4a\x61\x4e\x15\xe7\x36\xe3\xd4\x99\x41\xa7\xca\
+\xe8\xa8\xc3\x38\x3f\xf5\xcc\x2c\xdc\x11\x57\x93\xec\xf2\x03\x42\
+\x27\x50\xff\x2b\x91\x20\xa8\xed\xe3\x5d\x6a\xb1\xc7\xc9\x34\xca\
+\x0c\x26\xb9\x19\x4d\x0c\x60\x95\x82\x4d\x42\x5c\x16\xeb\xf5\x38\
+\x42\xb2\x0c\xdd\x11\x8b\xf5\x3a\x5e\x77\xc4\x82\x21\x18\x37\xe3\
+\xde\xc6\xc8\x7a\xb8\xe7\x39\xec\x7a\x9e\xcb\x4e\x87\x05\xc3\x66\
+\xf7\xc8\x81\xcb\x37\x68\xd6\x1b\x64\x57\x0b\x6c\x98\x02\xbc\x93\
+\xd3\x21\xc7\x63\x0f\xe3\x2a\x76\x6a\x13\x40\xa7\x07\x18\xb1\x6b\
+\xca\x9e\xd1\xaa\x3d\x0b\xd5\xa3\xb7\xe6\xd4\x68\x11\x89\xd6\xfe\
+\x15\x0f\xfa\xd0\x8a\xfb\xf1\xb7\xf0\xe8\x06\x5d\x4c\x6b\x85\xe0\
+\x9a\xcb\x98\x35\xb0\xd5\x9c\x0c\xc5\xbc\xf1\x02\xb9\xee\xf2\x38\
+\x0f\xd4\x7a\xe7\x1e\x2b\x6e\x7c\x22\x07\x2a\x6e\xd4\xb2\x09\x19\
+\x71\x73\xf2\x03\x89\x80\xc5\xd2\x38\xe2\xe0\xd8\x63\x10\xda\x89\
+\x85\xd7\x77\xa6\x2e\x2a\x11\xf1\x43\xb1\xa8\x94\x06\x7a\xc7\xa2\
+\x49\xc5\x82\x48\xb8\xf7\x6a\xe5\xaa\x72\xf5\xa9\x2b\x45\x0c\x7c\
+\xc9\x9a\x92\x9d\xb3\xf1\xa2\x70\xfb\xc9\xb4\xd1\x7a\x39\x0b\x44\
+\x33\x75\x85\x35\x6a\x22\x73\x2f\xfe\x7d\x32\x37\xba\x6e\x56\x67\
+\x02\x1e\x13\x7f\x48\xbb\x1f\xb2\x64\xd9\x94\xca\x4c\x7b\x7c\xf4\
+\x72\x64\xc2\x16\x41\x3c\x6d\x55\x04\x3d\xda\x1c\xb7\xb6\x39\x76\
+\x1f\x70\xef\xc0\xa0\xb8\x71\x48\x73\xe1\x06\x1b\x85\x35\x2a\xeb\
+\x5b\xf4\x8f\x76\xa6\x0b\xc7\x5a\x07\x7f\x87\x70\x6f\x9a\xbe\x30\
+\x98\x8c\x80\x1c\xe5\x5c\x0e\x34\xbf\xb4\x33\x8e\x87\x31\xca\x22\
+\xd0\xc4\xa5\x22\x2e\xfb\x31\x6a\x79\x8c\x5a\x9e\x52\xb0\xa9\xa2\
+\x72\xeb\x8b\x05\xa2\x18\xe4\x99\xa6\xd0\x77\x6b\x6b\x4b\xdc\xda\
+\x7a\x85\xf5\xf2\x4d\x8e\x72\x2b\xd0\x15\xcf\x1b\x57\x0e\x2d\x02\
+\x5a\x9d\x36\x74\x7a\xaa\x79\xc9\x3c\x36\x94\x9e\x04\x31\x35\xc8\
+\x26\x13\xb6\xa0\x67\x08\x3f\x72\x47\x38\xfe\xf5\xff\x00\xe1\xe5\
+\xc9\xb5\x9a\x4e\x4a\x88\x19\x63\x44\xbb\x02\xa4\x59\xa6\x66\x56\
+\x67\xa2\x79\x7e\xd1\x13\xf9\x11\x5a\xe7\x9e\x9e\x55\xa6\xea\x3b\
+\x34\x6b\xb6\x2a\x31\x4a\xdf\x8e\x5b\x17\x1c\x1c\x7b\x0a\xb8\xf2\
+\xaa\xd1\xea\x24\x93\x69\xea\xf5\x4a\xe2\x72\x4f\xcf\x50\x60\xec\
+\xd4\x42\xda\xa3\x5e\x3c\x61\xa9\xa0\xd8\x56\xce\x7b\x56\xa0\xbc\
+\xc6\xf7\x7d\x9d\x9f\x3c\x1d\x95\xd4\x0d\x6d\xf9\xfb\x24\x53\xeb\
+\x5d\x8a\xd2\x40\x96\xb9\x14\xfa\x42\x70\xcd\x31\x41\xbd\x41\xa6\
+\xd3\xa6\xd9\x10\x41\x8f\x8b\x74\x2b\xbc\xe1\xec\x31\x53\x7a\xb8\
+\x70\x42\x25\x1a\x52\x5b\x68\x88\x1c\x99\x23\x71\xa5\x2a\x66\xc7\
+\x38\xe3\xb1\x60\xe0\xb8\x54\xa9\x98\x15\x6e\x40\xeb\xf4\xd1\x1e\
+\xd6\x5a\xfd\xda\x1f\xbd\x51\xb6\x19\x65\x4a\x1a\x38\x0a\x88\x41\
+\x19\x60\x37\x61\x73\xbd\x8c\x7f\xef\xae\x72\xa7\xdd\x3c\xb5\xd8\
+\xf5\xf6\x39\x39\xb9\x50\xec\xab\x0e\x76\xcc\x2c\xe9\xc1\xdd\x69\
+\xf0\x15\xac\x52\xac\x57\xc7\xe0\x14\x81\x79\x40\x2d\xe2\x57\x3d\
+\xfc\x9e\xcb\x72\xdd\xe0\xbc\x13\x25\xe6\x24\xa7\x3f\x4f\x2d\xd0\
+\xa0\x0f\xd8\x73\x0d\x11\x31\x89\x47\x78\x23\xdc\xfe\x34\x8b\xed\
+\xaa\x62\x91\xc5\x9f\xeb\x8d\x90\x3a\x58\x67\xe0\xe3\xd6\x85\xd2\
+\xec\xf4\xa7\x9e\x17\x7d\xe6\x5d\x5d\x16\x9c\xfa\x43\xc5\x92\xa3\
+\xb6\xc3\xc6\x9d\x06\x5f\x7a\xe5\x25\x8a\xdf\x27\xaa\x59\x8e\x8e\
+\x42\xf6\xb7\xf3\x1c\x7e\xe7\x37\xa7\xa9\x9d\x65\x31\x2a\xb7\x16\
+\x7f\xcf\x6e\xd1\x83\x38\x47\xba\x1b\xf4\x00\x9b\x7a\xd7\xc4\x35\
+\xe7\x87\xd3\x67\xec\x92\x8a\x35\x3b\x82\xa1\x1a\x7d\xcf\x5e\x09\
+\xd7\x99\x88\x6c\x39\xf9\x19\x3d\x43\x68\xe1\xa0\x4b\x00\x2c\x55\
+\x60\xa7\x5b\xe1\x4b\xf2\x9c\x30\x20\xdb\xee\xb2\xba\xb8\xc0\xad\
+\xaa\xc3\x43\x92\xdd\x88\xfa\x86\xc8\xe5\x70\xcf\x8e\x38\x76\xd7\
+\x69\x70\x87\xc1\x24\x37\x35\xf0\x6a\x3e\x61\xe4\x30\x98\xe4\xc4\
+\x1c\x3b\x00\xff\xa4\x43\xef\x9c\xb9\xcd\x2c\x76\xe9\x70\x18\x5c\
+\xb0\x21\x9b\x6e\x67\x37\xb0\x16\x3d\xe8\x78\x5c\x76\x3a\xec\x1e\
+\x39\x18\xab\x21\xcd\xee\x6d\x5a\xec\xab\x6c\xa4\x76\x0c\x60\x79\
+\x59\xcb\xf6\x7d\xa8\x66\xc1\x99\x3f\x81\x3e\x7d\x19\x97\xc3\x0a\
+\xa5\x81\xa6\xef\x2b\x81\xe9\xf7\x42\xac\xaa\xc9\x79\x27\x54\xc3\
+\x0c\xf5\xf7\xa5\x01\x3c\x2f\x99\x67\x9e\x7c\x90\xd3\xea\x6b\x66\
+\x95\x6e\xb1\x47\xb6\x9f\x7c\x4f\x6d\xa1\x41\xf1\xbe\x37\x53\x62\
+\x24\x3c\x10\x17\x42\xb7\xc7\xe0\xad\xc5\x6d\x4c\x45\xc6\x5b\x72\
+\x68\xa3\x94\x00\x2a\x21\x7c\x73\x8d\x4f\xbd\x7c\x8b\xaf\xfc\xa3\
+\xaf\x50\xfa\xc4\x0b\x5c\x99\xd0\xde\x1e\xf1\x27\xfc\x1e\x3b\x4f\
+\x2d\xba\x81\x90\x13\xad\xd0\x88\x67\x47\xcb\xdc\x0d\x21\x21\xba\
+\x7a\xc6\x5e\x0c\x28\x29\x2f\x66\x7e\x73\xdc\xc2\xb6\x1b\x4e\x7f\
+\x9f\x3c\x76\x69\x43\x4d\x77\x9d\x49\x29\xa1\x8c\xc8\x9e\x41\xb5\
+\x3a\xa0\xe7\xa4\xdc\x73\x64\x45\x20\x4b\xef\x6d\x17\x8f\xb9\x5d\
+\x2a\x14\xe8\x67\x8d\x19\x26\x56\xa5\x6b\xe5\x21\xdd\x8e\xf0\x42\
+\x1d\x0f\x2d\x36\x8d\x0e\x9d\x48\xe4\x87\x86\x91\x83\xd9\xab\x63\
+\xd6\x62\x92\xab\x46\x58\x7f\xfe\xf0\x4d\x8c\xc2\x0a\x37\x2d\x8b\
+\xab\x7d\xc1\xa6\xd1\xa9\x89\xb5\xbe\x49\xe0\x3f\xa5\xd9\xbd\xcd\
+\xed\xca\x11\xa1\x1d\xb7\x0d\x9d\x1c\xb2\x7b\x64\xb1\x91\xf1\x39\
+\x0c\x2c\x02\x5f\x18\x33\xad\xda\x3e\xd1\xa9\xc9\x33\x3f\x3e\x29\
+\x12\xc0\x9a\x2b\xa8\x1b\xf4\xa0\x48\xa2\xc0\x52\x19\x53\xd2\x10\
+\xd3\xb6\x0c\x50\xc3\x0b\x67\x46\xca\x0e\x52\xef\x21\xf6\xe1\x22\
+\x64\x49\x61\x30\x7f\xe0\xb7\xc8\x62\x9b\x0f\xe0\x9a\x53\x4b\x9c\
+\x7c\xb7\x2f\x98\x59\xf7\x0f\x37\x7b\x01\xcd\xda\x0d\x3e\xbe\xb9\
+\x30\x13\x42\x96\xfe\x6a\x9d\x7d\xbb\x41\x37\x1e\x30\x8e\xda\xaa\
+\x4b\x7b\xd7\x84\x6a\x96\x97\x1e\xbc\xc0\xe6\xbd\xbb\xdc\x5d\xce\
+\x72\xeb\xde\x16\xc5\x9b\x2b\x74\xdb\x01\xa7\xef\x74\x78\xfd\x83\
+\x3f\x63\xef\xf1\x07\x64\xfb\x3e\xf5\xfa\x72\x9c\xd2\x6a\x43\x6c\
+\x68\x4a\x26\x15\xfa\xf5\xfa\xe8\xa3\xf4\x77\x2b\xad\x1d\x77\xfb\
+\x94\xbf\x6f\x26\x27\x79\x4e\xee\x35\xc0\x45\xe0\xb1\x64\xd9\xd4\
+\x25\x1b\x57\xa3\x69\x3b\x83\xf8\x73\xab\xe5\x81\xf0\xff\xc7\x00\
+\x0e\xea\x0d\x76\x5b\xa7\x1c\x07\x07\x94\xdb\xfb\x30\xfc\x24\x64\
+\xcb\x2c\xad\x5b\xc2\xcd\xf6\xfe\x1f\xd3\x1f\xae\x51\xe2\x48\x54\
+\x89\x94\x1b\x10\xe7\x9b\xd7\x52\xc9\x67\x83\x49\x8e\x62\xb5\xc3\
+\x60\x3c\x6d\x0c\x69\xad\x97\x6f\x2a\xe0\x3d\xf3\x7d\x38\x82\x68\
+\x78\x02\x1f\x3c\x8b\x13\x70\x4e\xe0\x02\x8c\x82\xf8\xa1\x37\x63\
+\x6b\x69\x37\x96\x0f\x00\xd1\xa9\xd0\x38\x47\xcf\x3c\x26\xde\x31\
+\xce\xb3\x8a\xd0\x4c\xfe\x90\x4e\xcc\x04\xf5\xc8\x48\x8c\xbc\xd5\
+\xe7\xb4\xc9\xc7\x12\xb0\x0a\x9c\x96\x60\xdd\x4c\xa6\x06\x74\xa7\
+\xcc\x1a\x3b\x0a\x74\xd0\x4b\x26\x2e\x0c\x4a\x0c\x7b\x2e\x3e\x42\
+\x52\xe8\x4c\x2c\x80\xd8\x67\xe8\x4f\xf7\x6f\xf6\x02\xa5\xc3\x25\
+\x80\xf5\x74\x4d\x6b\x20\x18\xd9\x65\x42\xd3\x8c\xa8\xdd\x91\x79\
+\x11\x57\x8a\x85\xa5\x0f\x58\x67\xe0\x80\x9a\xca\xb3\xf0\x7d\xf1\
+\x7d\xe4\x1c\x3b\xc8\xaa\xb6\xb2\x9f\xb9\xb3\xcc\xdf\xfc\xa7\xf7\
+\xb9\x63\xdd\xc7\x66\x81\xca\x4d\x8b\x63\xe0\xe8\x9b\xdf\xe5\xe7\
+\xff\xb7\xd7\x79\xba\x2d\x86\xf3\x98\xc5\x08\x3a\x02\x28\xa5\x6a\
+\x36\x31\x9c\xd1\xed\x4f\x70\x99\x02\x52\x1a\x7c\x89\x81\x90\x45\
+\x0f\xd7\x91\xe0\x1c\xcf\x18\xae\x3a\x0b\xeb\x4c\x3d\x4f\x53\x5f\
+\x04\x1e\x75\x8c\x44\x74\xcf\x35\xc7\x6a\xa8\x8e\x34\x56\xe9\x19\
+\x64\x9b\x79\x2a\xd1\x90\xee\x55\x88\x7f\x30\xe4\x24\x28\xb2\x64\
+\x3a\xc0\x22\x8d\xc1\xd4\xc5\x39\x29\x1c\x81\x13\xbb\xd8\x1c\x8f\
+\x5a\xa6\x46\xb7\xd3\xe5\x38\x38\xe0\x13\xbc\x48\x31\x9b\x67\x30\
+\x11\x3a\x58\x4a\x0b\x95\x9d\xa8\x03\x53\x6e\x29\xdf\x9c\x7b\x99\
+\x7f\xe6\xfb\x18\x83\x67\xc2\x78\x03\x38\x12\xef\x79\xe6\xfb\xd4\
+\x3b\x1e\xfb\xdd\xfd\xb8\x55\xeb\x98\x8b\xc0\x03\x63\x3a\x87\x58\
+\x9d\xd0\x39\xab\x3e\x5d\x41\xa1\xef\x53\xb0\x4a\xd0\xf7\x09\xe2\
+\xfb\xf3\xe4\x85\x3c\xf8\xe9\xc9\x9d\x72\x7f\xc9\xf4\x69\x5f\xb0\
+\xf4\x88\xe8\x60\x96\xba\xd9\x2f\x6a\x03\x15\x7b\x39\xaa\xa1\x43\
+\x2d\xd3\x88\x27\x77\x4e\x01\x7c\x30\xbc\xc9\xc8\x39\x54\x00\x6e\
+\xb5\x0d\x5c\x53\xe8\x78\x0b\x9b\xf1\xf8\x04\x62\x83\x4c\xaf\xd3\
+\x93\x03\xcc\xd7\xca\x06\x7b\x07\x3e\x66\xb8\xc3\xa0\xb3\xcd\xe9\
+\x1f\x1f\xf2\x03\xaf\xfe\x10\x00\x9f\xf8\xd1\x9b\xdc\xb6\x3f\x4b\
+\x6b\xe1\x81\xb2\xe0\xcf\xb6\xdf\xa0\x49\x53\x63\xc0\x89\x02\xae\
+\x3c\xc6\x6e\x6c\x43\xc8\xb6\x5c\xfa\xa0\x48\x1d\x74\x7a\xf0\x46\
+\x12\x86\x3c\x4e\x99\xb8\x87\xf2\xdc\x4e\x9e\xb1\x8c\x90\x19\xe9\
+\x72\xf1\xcf\xb8\xf4\xaa\x59\x91\x9f\x1c\x67\xca\x1d\x8c\xba\x30\
+\xfe\x10\xf8\x7e\x16\x32\x11\x7b\x95\x12\x5b\x95\x21\x0f\xd7\xb7\
+\xe8\xef\xed\x28\xcf\x83\xe8\xfb\x86\x60\xe3\x5e\x96\x43\xd7\xa0\
+\x52\x14\x03\x0b\x07\x13\x7d\x5e\x74\x9c\x69\x28\xe5\x43\x7a\x9b\
+\x06\xef\x4d\xcb\xe2\xa6\x65\x11\x59\x37\xb9\xa9\x3d\x0f\x10\x9d\
+\x4d\x78\x77\xe7\x21\x51\xdc\x0e\xe9\x22\xf0\x94\x1f\xd3\x2f\x82\
+\x3b\xe7\xb2\x95\x98\x7d\x9c\x9a\x44\x6f\x61\xce\x68\x59\x09\xc8\
+\xb4\xbc\x60\x30\xdf\xf8\x48\x03\x7e\xd8\x73\xa7\x2e\x37\x8d\xe9\
+\xe5\xdf\xed\x59\x82\xe5\xba\xe5\x6e\xa2\xb3\x8f\x72\xb1\x99\x4d\
+\x56\x36\xea\xca\x9d\x26\x2b\x2f\x46\xad\x29\x80\x0f\xbb\x13\x86\
+\xa1\x0b\xa1\xb6\x80\x62\x00\xcb\xef\x2a\xbd\x1d\x3d\x47\x8c\x0d\
+\x33\x72\x8b\xac\x5c\x1e\xf0\xd4\xbf\xc3\x07\xaf\x3f\x06\xe3\x98\
+\xa8\x78\x93\xfb\x9f\xff\x24\x3f\x76\xe3\x0b\x14\xbf\xfc\x05\x26\
+\x8d\x02\x17\xad\x2f\xf1\xd6\x1f\xee\xf2\x26\x30\x39\x7f\x04\x3d\
+\x03\xbf\xec\xc5\xda\xb8\x88\xcb\xac\xf4\x91\x25\x55\x69\x3b\x20\
+\x13\xb6\xf0\xcb\x99\xc4\x00\xf5\x82\x55\x12\x83\xd1\x7b\x0e\xe7\
+\xb8\xe0\x94\x66\xd2\x2b\xf5\xec\x36\xf5\x58\x6b\x40\x9e\x96\x23\
+\xea\xbd\x71\x0e\x89\xe5\x9e\xb3\xbb\x6b\xb2\xb1\x75\xc1\xc2\xc6\
+\x6d\x2a\x0b\x8b\x74\x17\xe4\x49\xd8\xc2\x2c\x9c\x28\x03\xaf\x44\
+\x8e\x7e\x27\x6e\xec\xee\x6f\x03\x9f\xc1\x1f\x58\x58\xc5\x3e\x50\
+\x49\x78\x44\x4c\x80\xae\x7f\x7f\xea\xc4\x8e\x01\x6c\xac\x86\x82\
+\x79\x57\x43\x6e\x5a\x96\x92\x0e\xfa\x56\x32\xf7\x7e\xf7\x29\xad\
+\x83\x4e\x02\xc0\x1d\x23\xa2\x66\x56\xe7\xb2\xaf\x1e\x54\x48\xaf\
+\x74\x69\xb0\xe9\x46\x9c\x6e\xa4\xe9\xa1\x64\xfd\x73\xd3\x9a\x59\
+\x37\xfe\x74\x50\xfb\xbd\x90\x28\x53\x51\x72\x42\x06\x32\xfc\xa2\
+\x97\x00\x70\xa2\x8a\x23\x14\x5d\xd1\xd7\xca\xd3\x0a\x8d\x83\xe1\
+\x4d\x8e\x5b\xc2\x88\x6b\x75\x62\x00\xfb\xee\xdc\x2b\x80\xba\x52\
+\xc4\x7f\xaf\x15\x0a\x5f\x79\xd0\xab\x73\xdc\xba\xc0\xfe\xf4\x16\
+\x3f\x7c\xcb\xe0\xc1\x8f\xdf\xe3\xc5\x1f\xfc\x22\x9b\xb7\x37\xf0\
+\x4f\x3a\x7c\xeb\xf0\x82\x77\xdf\x38\xe1\xfd\xdf\xd9\x65\xcd\xdb\
+\xe7\x1f\xfc\x0d\x93\x2f\xff\xc4\x06\xd9\xe5\x07\x1c\x4d\x2e\x89\
+\x32\x95\x44\xcf\x37\xfd\x7b\xcf\xdb\xca\xbf\x9f\x0e\xb3\xeb\x84\
+\x71\x8e\x91\x78\xec\x9a\x63\x5c\x73\x3c\x75\xb3\x69\x1d\x46\x13\
+\xb3\x4f\xb4\x9b\x1e\xf5\xd3\x0d\xbb\x9d\xae\x00\xdf\xd9\xf0\x29\
+\xe3\xe1\x15\x99\x6e\x9b\x8d\xc2\x9a\xc8\xa1\xf0\x77\x66\xab\x45\
+\xea\x26\x83\xf6\x90\x6a\x7f\x91\xfe\xa0\x8b\x55\xf4\xf1\x07\x96\
+\x62\x61\x95\x3b\x11\x9d\x9a\xd4\xd7\x3f\x4c\x80\x57\x82\xba\xcc\
+\x83\x19\x46\x4e\x3f\xb6\xd6\x37\xb9\x5d\xbb\x4b\xb6\x99\xe7\x22\
+\xf0\x44\xda\x5e\x2a\x14\x19\x65\x2a\x89\x18\xbc\x7e\x40\xf5\x01\
+\x31\xd7\x01\x53\x02\x21\x0d\x50\xc9\xdc\x12\x2c\x2a\xd4\xdc\x0b\
+\x67\x16\x8d\xee\xa9\xd0\xf5\xae\xcc\xa3\xb8\xce\x53\xe2\x3a\x13\
+\x6a\x77\xa6\xc9\x3d\x52\x03\x37\x2f\x8e\x14\x80\xaf\x3a\x9d\x04\
+\x9b\xe9\xdf\x5b\x7e\x17\x1d\x60\x7a\x7f\x8b\xb3\xc3\x36\x7b\xaf\
+\x1d\x52\x5e\x35\xf8\xe2\x67\x3e\xc7\x8f\xfe\xbd\xcf\xf2\xf2\x27\
+\x57\xb9\x73\xb3\xc8\x46\xc6\xe7\x5b\xdf\x7d\x8d\xdf\xfa\x8d\x5f\
+\xe1\xf7\x7e\xf5\xf7\x38\x0a\x73\xdc\xbb\xf3\x0a\xad\x07\x1b\x34\
+\xf2\xd5\x99\x06\xdf\xd7\x79\x5c\x12\x55\xdf\x73\x8e\xb1\x7e\x7f\
+\x99\x48\x91\x46\x22\x76\x10\xf4\xe7\xba\xe9\xd2\xcf\xa5\xcf\xab\
+\xee\x92\x6b\x75\x3d\xa2\xec\x19\x79\x56\x70\x49\x85\xb2\xad\x64\
+\xb9\x52\x89\x1c\x01\x35\xd1\xe2\xd5\xbd\x60\xa3\x34\xdf\xe5\x57\
+\x2a\x67\xb1\xee\x7f\xfe\x93\xf8\x97\x15\xac\xcf\xf7\x45\xf4\x0d\
+\x78\xf5\xee\x90\xc3\xe0\x2e\x0b\x77\x7c\x02\x1f\x16\xec\x0d\x5a\
+\xec\xc7\xa0\xfe\x50\x31\xf6\xfa\xba\xa8\xe6\x30\x56\xb2\xe2\x4b\
+\x04\x0f\x55\x56\x5a\x3d\x32\xe8\xc4\x91\x26\x79\x49\x13\xee\x9e\
+\xf9\x2e\xae\xb4\x3e\x53\x46\x9a\xef\x42\x0f\x7c\xdc\x84\x11\x37\
+\x57\x0f\xc7\xd2\x41\xee\x3b\xec\xb9\x09\xa3\x45\x07\xb2\x6e\xd0\
+\x28\x3d\x88\xa9\x5c\x4d\xcd\xfa\x40\x15\x82\x16\x57\x93\x25\x56\
+\x8f\xfd\x67\x14\xce\x9b\x74\x3b\x5d\xdc\x98\x09\x75\xf6\x95\x2c\
+\xaf\xff\x16\x7d\xe1\xd6\x23\x43\xc8\x8c\x6a\xc4\xf6\x55\x87\xee\
+\xaf\x7f\x9d\x47\xef\xdc\xa0\xfc\xca\x21\x0b\x5d\xd1\x19\xe9\x0b\
+\x1f\xbf\x4f\xb1\x9e\x61\xf3\xde\x5d\x8e\xc7\x1e\x61\x7e\x19\x3f\
+\x7c\x88\x65\xbe\xc4\x0f\x1b\x23\xde\x90\x2e\xba\x39\x2c\x7c\x5d\
+\xe4\x32\x7d\xac\xf5\xab\x97\xce\xc4\x46\x3f\x22\xdf\x28\xcf\x1c\
+\x2f\x5d\xeb\xea\xe4\x23\xc9\x44\x12\x4b\xda\xd5\x26\xd9\xbf\x06\
+\x8c\x0f\x26\xf0\xfd\x10\x19\x5d\x20\x98\x1b\xf4\x90\x92\xa2\xa9\
+\x35\x79\xba\x74\x45\xae\x85\x55\xf4\x29\x7a\x2e\x7d\x16\x89\x68\
+\x09\x4d\xbc\xba\xb1\x81\xb3\x50\xa6\x5c\x74\x58\xdd\x00\xbf\x2f\
+\xc2\x2b\x2b\xdd\x51\x9c\x00\xf4\x4a\x2c\x6b\xea\xf8\xf9\x0e\xd6\
+\xda\x2b\xec\x5a\x9a\x53\x70\x1d\xd6\xfd\xa7\xec\xaf\x6f\xb1\xfb\
+\xd6\x9f\x53\xcf\x2e\xaa\x4b\x88\x8c\x0e\xd5\xca\xc2\xdf\x0a\x95\
+\x19\x8b\x39\x7d\x5f\xd7\xc9\xc2\xa8\x22\x21\x23\xa4\x0b\x2d\xed\
+\x47\x96\x5e\x09\xaa\xe2\x3d\xfa\xeb\xe9\x13\xb6\x4c\xa4\x2e\x9b\
+\xcb\x44\xf4\x00\x33\xec\x01\x75\xc2\x4e\x87\xe5\x66\x4d\x65\xb9\
+\xd5\xea\x0d\x5e\xb0\xa6\x39\xc2\xdb\x8f\x42\x0a\xbd\x26\xbb\xad\
+\x53\x7a\x4e\x51\x7d\xae\x6e\xc0\x0d\xfd\xa9\x27\xc2\x1a\xd8\x6a\
+\xa1\xc8\xdf\xa4\x8f\xba\x2d\x58\x25\x7a\xc0\x5b\x3b\x27\x98\x4f\
+\x3e\x24\x72\x2b\x2c\x55\x44\x7f\xb2\xf5\x7b\x5f\x64\xf3\xde\x06\
+\x5f\x78\x61\x93\x93\x70\x0d\xcb\x14\x44\xf3\xf0\xfd\xf3\x99\x2b\
+\xca\x75\x41\xa3\x79\x72\x4b\x5e\xb9\xe8\xcd\x46\x36\x0b\x56\x89\
+\x11\xce\xcc\xfe\x05\xab\x94\x18\xb2\xa3\x37\x57\xd4\xf7\xd5\xff\
+\xa6\x0c\x9b\x97\xca\x62\xd0\x7a\x37\x80\x9d\xfd\x3e\x2f\x5e\x5e\
+\xd0\xb8\xb5\xc5\x62\x63\x13\xd8\x4b\xba\xd9\xfc\x23\x05\xe4\xbe\
+\x51\x50\x19\x8b\x1e\x57\x71\xe3\xca\x0a\xbd\xc8\xc3\x2a\x7a\xf8\
+\x72\x1c\xb2\x4d\x0e\x8a\x5a\x32\x45\x25\xbe\xd4\x55\x2a\xac\x02\
+\x36\x01\x1e\x19\xc2\x41\x48\x18\xe7\x57\xc8\x3c\x8b\x28\x06\xfa\
+\xf2\xc2\x57\xc8\x58\x1f\xb2\xf3\xb4\x09\x5d\xe1\x10\x97\xda\x78\
+\x52\xb1\xe8\x10\x51\x37\xab\x74\x88\x34\x46\xf6\x67\xee\xa7\xa5\
+\x86\xce\x64\xf2\x80\x4b\xb6\x4d\xb0\xb5\xe6\x52\x4b\xeb\x69\xdd\
+\x90\x93\x8f\x7b\x56\x19\x7c\x97\xaa\xef\x08\x30\x03\x8b\x66\x85\
+\x16\x90\xcb\xad\xd1\x73\x44\x7e\x44\xed\x4e\x43\x25\xb9\xef\xfa\
+\x03\xc2\xa3\x0d\xfa\x85\x77\x39\xd9\x1b\x27\xb4\xa8\x34\xe0\x74\
+\x06\x4e\xe8\xd3\xd8\xaf\x9d\xce\x8e\x2b\x55\xb3\x4c\x0c\x8b\x7a\
+\xd7\xa4\x64\xe6\xa0\x5e\xa7\xb9\x04\x9f\x7a\xe5\x05\x3e\xf1\xa9\
+\x17\x09\xef\x3c\xc3\xdc\x3b\xe5\x1b\xe7\x13\x16\x6c\x9f\xab\x27\
+\x87\xbc\xf1\xfe\x5f\x31\x39\x3f\x52\x75\xea\xfa\x15\x4e\xff\x3e\
+\xf2\x6f\xa6\x01\xac\xa2\x9a\xbd\x59\x90\x0e\x7d\x97\x51\xdb\x21\
+\xaa\x18\x62\xa1\xa7\x5e\x5b\x26\xa2\xe7\x94\x67\xe4\x42\x9a\xcd\
+\xe5\xdf\xc9\x84\x2d\x4a\xd5\xc6\x34\x5a\xd9\x11\x39\x14\xa3\xa3\
+\x0e\xd1\xfa\x39\xb9\x8d\x06\x37\x3e\x56\xe5\x3b\x1f\xc4\x55\x1c\
+\xbe\xf0\x50\xa8\x4e\x9b\x8e\xc8\x58\x3c\x1e\x5a\xdc\x02\xaa\x46\
+\xc8\x80\x3e\x90\x4c\x1d\xb0\x3c\xc6\xe4\x0b\x21\xa3\xa1\x39\xb3\
+\x55\x65\x4b\xe4\xe2\x39\x83\x7a\xf5\xab\x07\x95\x05\xb2\xb4\xa8\
+\x34\x96\xf9\xdb\x1b\x77\xf9\xb3\x3f\x3a\x10\xe1\x51\x3f\x62\xc9\
+\xb2\x55\x75\x82\x14\xfb\x75\xb3\x4a\x27\x8e\xf5\xcb\xe8\x92\x9e\
+\xb4\xa2\x07\x23\x54\x07\xf6\x5e\x88\x15\x9f\xb1\x82\x55\x52\x5e\
+\x06\xc9\x76\x09\x66\xd1\xa4\x83\x7c\x6f\xda\x9f\x2c\x13\x78\x86\
+\x18\x0a\xcc\xca\xa0\x89\x43\xca\x3d\xab\x4c\x50\x6f\xb0\x12\x37\
+\xaa\xde\xf5\x07\x2c\x9d\xd8\x7c\xe7\xe4\x31\x7d\xa7\x41\xcf\xe9\
+\xcf\x8d\x06\x8e\xc7\x27\xe4\x58\x9b\x0b\x64\xfd\x52\xde\x2d\x8a\
+\xc8\x9b\xeb\x4c\xc8\x02\xae\x29\x82\x2b\x5b\xa6\x41\xf1\xbe\x17\
+\x03\x58\x5c\x52\x9f\x9e\x4f\x78\xfd\xf7\xdf\x10\x9d\x7f\x34\xf7\
+\x98\xee\x49\xd1\x43\xe9\xba\x27\x64\x9e\x4e\x4f\x3f\x97\x5e\xf0\
+\x51\x3c\xd4\xe5\x42\x73\x02\x0c\xf5\x63\x74\x8d\x7c\x49\x2f\x08\
+\x19\xe4\xd0\x23\x7f\xd4\xc5\x39\xea\x55\x2e\x31\x96\x97\xb1\xa9\
+\xf0\xc9\xdb\x9f\xe1\x83\xca\x43\xe1\x75\xf1\x87\x98\x75\x5b\x25\
+\xc8\xcb\x71\x63\x2a\xd0\x61\x87\xf8\x03\x8b\xaa\x11\xd2\x1b\x78\
+\x58\x45\x5b\x34\x14\xb4\xc9\x61\x0e\x23\x6c\x02\xcc\x61\x3c\x93\
+\x21\xde\xe6\x0b\x61\xfc\x21\xde\x14\xb8\x6a\x2b\x9e\xb7\xb1\xf1\
+\xdb\x67\xd8\x35\x9f\x9f\xfa\x99\x2f\x51\x5f\x7c\x85\xa3\xab\x2b\
+\x2e\x02\x4f\x95\x85\x4b\x4f\x85\x9e\xef\x2a\x19\x44\x4f\xc8\x49\
+\x07\x19\x74\x9d\xab\x07\x44\xae\xab\x8f\xd3\x25\x84\xae\x9d\x75\
+\x00\x5b\x55\x53\x49\x89\x79\x9a\xb0\x67\x95\xa9\x96\x07\xdc\x6b\
+\x8a\xa6\x27\x17\x6b\x1e\x4b\x27\x36\x8f\xfd\x67\xa2\x61\x75\x47\
+\x00\xd8\x0c\x7b\x33\x97\xe1\x5c\x6e\x6d\xae\xaf\x3b\xed\x03\xd7\
+\x7f\x8f\xdc\x2f\xdb\xf7\x69\x05\x70\xf6\xa4\xc1\xd7\x77\xf6\xf8\
+\xf3\x3f\x3d\xe4\x4f\x7f\x79\x9b\x3f\xfc\xfd\xaf\xb1\xb3\xbb\xaf\
+\x0a\x5f\xe7\x75\x2c\x92\xbf\x4d\x97\x4e\xba\x36\x9f\xe7\xb9\x19\
+\xfa\xae\xea\xe1\x5c\xb0\x4a\x18\xfd\x88\x65\xa6\xc6\x53\x54\x31\
+\xbe\xa7\xec\x3e\xdd\x08\xd4\x8f\xa5\xde\x6d\xbf\x63\x88\x3e\x75\
+\x74\x42\x0e\x23\x31\xfd\xaa\x7d\xb0\xc3\x78\x78\x45\x34\x39\xa6\
+\x7a\x73\x43\x94\x2a\xf5\x0c\xfa\xc3\x35\xd5\xa4\xb0\xef\x14\x68\
+\x85\x1e\x6e\x5c\xde\x24\x3d\x13\x03\x3b\xc4\x88\xfd\x76\x71\x65\
+\x87\x97\x64\x57\x5d\x64\x0f\x0b\x78\xaa\xf1\xc6\x75\x40\x06\x8f\
+\x0c\xfe\xf1\x29\x9b\xf7\xef\xf3\x77\xff\xa3\x2f\xb2\x79\xf3\x87\
+\x45\x3a\x60\xa7\x4f\xa7\xd3\xa7\x51\x31\x67\xaa\x14\xd2\xae\x35\
+\xc9\xc6\x3a\xa8\x25\xf8\xfc\xa2\x37\xd7\xeb\x20\x73\x85\x75\xb6\
+\x9d\x77\x40\x75\x40\xeb\xde\x82\x74\xd8\xbb\xea\x3b\x54\xcb\x03\
+\x6a\xf5\x1a\xc3\xe5\x16\x17\x6b\x9e\x0a\x27\x9f\x3d\x69\x24\x72\
+\x7f\x43\xb3\x3a\xa3\x27\xa5\x6e\xd7\x7f\x83\xee\x19\xf0\x8b\xc2\
+\xaf\x2b\xaf\x4c\x52\xfb\x27\x4a\x8d\x3a\x7d\xfe\xe4\x37\xff\x8c\
+\xd7\x5e\x7b\x97\x6f\xfe\xe5\x43\x26\xad\x11\xcd\x5a\x93\x4c\xa3\
+\x96\x30\x98\x66\x02\x42\x73\xb4\x70\x9a\x69\xd3\xc7\xd0\xce\x64\
+\xd4\x6b\x51\xc5\x48\x64\x9b\x49\x80\x7b\x41\xa0\xfe\xeb\xbf\x51\
+\xff\xdb\xf3\x58\x58\x5d\x2d\xc2\x1e\xf5\xc8\x20\xca\x54\xb8\x0c\
+\xfb\x42\x1e\xc4\x6d\x78\x33\x83\x0c\x4e\x2f\x69\x34\xcb\x86\x3b\
+\x6a\x94\xc2\x9c\x61\xb0\xfe\xc0\x22\xa2\x05\xf4\xa7\x7e\x62\xfd\
+\x66\x93\xc3\x63\xac\x6d\x03\xf5\x8a\xbe\xd7\x8c\x21\xd1\xee\xe0\
+\x84\x7d\x7e\xe0\x2b\x3f\xcc\x7f\xf6\xdf\xff\x34\x5f\xfe\x47\xff\
+\x82\x8d\x57\xff\x21\xed\x51\x0f\x6b\x90\x57\x6d\xa5\x9e\x5b\xb3\
+\x15\x03\x59\x4f\x85\xd4\x99\x38\x11\x42\xd6\xc0\x9b\x8e\xc8\xa5\
+\xc1\xec\x05\xc1\x5c\xd9\x31\xb3\x30\xea\x26\xb5\x7a\x8d\xe2\xaa\
+\xc7\x0b\xd6\x4d\xda\x87\x2d\xfc\xed\x02\x1f\xb4\x3a\x84\xfe\x19\
+\xe7\x9d\x48\x81\xc4\x0c\x7b\xea\x04\xea\x27\x54\x46\xc8\xa2\x4c\
+\x25\xb9\xc8\xa4\x8f\x36\x9e\x24\xaa\x03\x41\x56\x54\xeb\x9f\xa3\
+\xb2\xcf\xcc\x31\x9d\x5a\x98\x58\xe0\xba\x54\x4a\xbf\x4f\x6f\x18\
+\x93\xf0\xfa\xa4\xae\x46\x33\xe9\xb7\xfd\x28\xc1\xbe\x12\xe0\xe9\
+\xed\xf3\x5c\x74\xf2\xb1\x5e\x64\xaa\x8f\x06\xce\xe5\xd6\xa6\x87\
+\xba\x50\x26\x73\xcb\xa4\xb1\x24\xbe\xcb\xad\xaa\x43\x76\xf9\x81\
+\xea\xdb\xa7\x7c\xce\x41\x57\xb5\x6a\x98\xbd\x55\x24\x13\xdb\x0a\
+\x98\x1e\x19\x60\xda\x0d\x5e\x00\xd8\x4e\x30\xee\x3c\x36\xb6\xc9\
+\xe1\xd9\x25\xec\xf6\x19\xe5\x41\xc8\xe6\xfd\xfb\x7c\xf9\x67\x5e\
+\xe4\x9f\xff\xcb\x1f\xe3\xe5\xcf\xfd\x24\x9d\x4e\x5f\xc9\x0b\x29\
+\x27\xae\x3a\x1d\xd5\xb3\x21\x68\x77\x71\x2e\x5b\x04\xed\x6e\xe2\
+\xc4\xea\x27\xbb\x69\x46\x89\xcb\xa5\x7e\x72\xd2\x60\xd4\x41\xdf\
+\x1e\xf5\x68\x68\x03\xaf\xf5\x13\x19\x76\x3a\x0a\x84\x4d\x33\x4a\
+\x00\xf8\xb1\xff\x8c\xca\xf0\x06\x67\x9d\x36\x51\x6f\x9a\xe4\x22\
+\x59\x47\x67\x62\x9d\x89\xa4\x91\xaa\x03\x53\xff\xbe\xf3\x6a\xd6\
+\x9e\x97\xa4\xaf\x2f\x6c\x3d\x99\x67\x1e\xdb\xa6\x0d\xdb\xb4\x4f\
+\x5d\x2e\x3a\xf9\xf7\x24\xbb\xea\xf2\xc1\x48\xcd\xe7\xf6\x82\x20\
+\x01\x60\x3d\xb2\x9a\x06\xb2\xdc\x66\xc2\x56\x02\xc8\xba\xcd\xd0\
+\x0a\x45\xbd\x5d\x67\xe8\x60\x3a\x19\x36\x1b\x9b\xd4\x3f\xb6\x7e\
+\xed\xef\xaf\x65\x6a\x2c\x74\xfa\x8c\x2e\xc7\xca\xc5\x66\x15\x7d\
+\x15\xf0\x50\x33\x3b\x04\x1c\x05\xeb\xba\x03\x83\x52\x31\x96\x11\
+\xde\x50\x03\xab\x27\x0c\x3c\x6f\xa8\xc0\xec\x69\xd3\x73\x04\x73\
+\x67\x70\x46\x2d\x9c\xab\xef\xb2\x10\xc2\xda\xcd\x02\x3f\xf5\x33\
+\x5f\x62\xe3\xd5\x7f\x48\xb6\xef\xb3\x7b\xf6\x8c\xa3\xab\x2b\x8e\
+\xae\xae\xf0\x82\x80\xd2\xfa\x02\x77\xee\xbf\xc4\xbd\xef\xfb\x24\
+\xeb\x77\x37\x71\xfb\x22\x09\xbc\xdf\x9e\xa8\xd2\x22\x79\x70\x64\
+\xbe\xb0\xae\x8b\xd3\x72\x61\x1e\x2b\xd8\x99\x4c\xe2\x79\x9d\x89\
+\xc3\x38\x09\x5e\x3e\x27\xcb\x87\x54\x75\x75\xa7\x1d\xfb\x82\x27\
+\x73\x3d\x1e\x73\xfd\xd5\x73\xca\xfd\xf5\xe8\xa0\x7e\xa5\xf9\x5e\
+\x92\xf8\xf5\x54\xcd\x79\x85\x04\x69\x37\xe2\x75\x36\x42\x3a\xfa\
+\x79\xdd\x4d\x67\x63\xa3\x1f\xcd\x00\xf8\xba\x9b\xfc\xfd\x32\x17\
+\x5c\x8f\xe2\x49\xe9\x98\xcb\xad\xd1\xed\x74\x39\x88\x26\x71\xbd\
+\xdd\x25\xad\xb0\xcb\x6a\x7d\xda\x11\x68\x5e\x4f\x8b\xc3\x28\xcb\
+\xbd\xdb\x59\x0d\xbc\xe2\xd8\x55\x8d\x30\xce\x01\xf7\xda\x60\x17\
+\x94\x7c\x28\x15\x03\xdc\xc1\x90\x52\xb1\x00\xb6\x94\x14\x36\xee\
+\x60\x88\x59\x1c\x63\xdb\x0d\x6c\xaf\x0d\x76\x43\xe4\x73\xe2\x29\
+\x30\xdb\x71\x02\x87\x07\x74\xdb\x5d\x6c\xc6\xbc\xd0\x28\xf1\xcf\
+\xff\xe5\x8f\xf1\xdd\x77\x6f\x71\xb5\x67\xe1\xf0\x88\x9b\x96\x85\
+\xb5\xbe\xc9\x67\x3f\xb1\x8e\x99\x29\x31\xa0\x8a\x37\xec\xf0\xe4\
+\xc3\x6d\xf6\xf7\xb6\xd9\x7b\xfc\x01\xbb\x3b\x07\xb4\x2f\x5b\x84\
+\x03\x71\x50\x6f\x7d\xf2\x8e\xb8\xbc\x1e\x5d\x25\x4f\x60\x2f\x19\
+\xd8\x90\xec\x5b\x69\x64\x67\x2e\xb9\x72\xff\x74\x35\x87\x9c\x66\
+\x34\x5c\x6e\x51\x19\xde\xa0\x5f\x38\x56\x35\x7d\x22\x78\x33\x99\
+\x3d\x61\xd7\xe4\x6c\xe8\x41\x81\x04\xd8\x52\xa9\xa1\xba\x57\x26\
+\xed\x39\x98\xe7\xf9\x98\x97\x0b\x3d\xcf\x38\xd5\x17\xb8\xf4\x5f\
+\x17\x72\x6b\x33\x57\x8d\x79\x0c\x9b\x96\x14\xcf\x33\xee\xae\x5b\
+\x78\xfa\x77\xd7\x93\xe4\xeb\x55\xa0\x9c\x85\x4e\xc8\xce\xf6\x19\
+\xfc\x28\x84\x3d\xb0\xcc\x88\xe5\xf6\xd4\xc5\x9b\x2d\x7c\x1c\xfc\
+\xa3\x69\x92\x7c\xec\x21\x79\xb2\x3f\x41\x14\x8f\x57\xa8\x1a\x2e\
+\x66\xad\xa1\x65\xb1\xd9\x0d\x3c\xc6\x84\x83\x21\xa5\x62\x14\x33\
+\x71\x14\x3f\x17\x0a\x30\x7b\x6d\x4a\xc5\x06\x78\x6d\x3c\x1b\xc2\
+\xc8\xa6\xa4\x71\xb0\x8d\x87\x3b\x30\xa0\x88\x02\xbd\x40\xf3\x90\
+\xb6\x9d\x61\xed\x66\x85\xd5\xfa\x97\xe1\x8b\x7d\x9a\x93\x2f\xd1\
+\x0f\xce\xc0\x8e\x2d\xea\xa1\x41\x35\x9f\x63\x62\x98\x6c\xae\x7e\
+\x19\x7e\xe4\xcb\x9c\x76\xae\x28\x5c\x79\x9c\x5e\x5e\x71\x38\x14\
+\xb5\x56\x9b\xeb\x65\x7e\xe9\x17\xdf\xe7\xe8\xe9\x2f\x51\x5e\x6c\
+\x52\xe8\x97\x12\x8c\xa3\x4b\x0a\x3b\x93\xc1\xef\x85\xea\x44\xa5\
+\xfd\xc4\x89\xbc\x64\x50\x32\xa2\x70\xde\xa4\xbf\x3c\x05\xf0\xe1\
+\xd1\x64\xd6\xf7\x0a\xd3\x54\xd0\x54\xb4\x4a\x82\x37\x51\xb0\x3a\
+\x27\x62\x26\xdf\x2b\x7d\xbb\xe9\xab\xc8\x3c\x00\x4f\xa5\x85\x3d\
+\x03\xd8\xeb\x8c\xbb\xa1\xef\xce\x05\xf0\xf3\x58\x38\x0d\x64\xf9\
+\xf8\xa3\xde\x3b\x6f\x11\x59\x55\x93\x9a\x53\x9b\xe6\x5b\x68\x79\
+\x14\x17\xdd\x27\x74\xbd\x4d\x8a\x1b\x4d\xce\xdb\x65\x95\xcd\x76\
+\xf8\x9d\xdf\x84\x7a\x45\x25\x01\xb5\x3a\x43\xa2\xf1\x25\x3b\x3b\
+\x5f\xe3\xac\x73\x9f\xd0\x5e\x65\x3d\x3a\x22\xb8\xb8\x43\x36\xb3\
+\x22\x98\x38\xe7\x0d\x71\x23\x62\xe0\x66\x00\xe1\x56\x93\xa0\x06\
+\x31\x39\xc9\x64\x0c\x76\x89\x9a\x17\x32\x2e\x16\x14\x5b\x0b\xd0\
+\xa2\xee\xd7\xbc\x90\x76\x24\x24\x89\x1b\x89\xa1\x20\xfd\xf6\x1e\
+\x50\xc6\x26\x47\xbf\xd0\x87\xe1\x90\xf6\x50\x04\x50\xcc\xa2\x09\
+\x23\xd1\x7f\x78\xc4\x3e\xe5\x7c\x93\xb5\x9b\x05\xa2\x46\x8e\xca\
+\x46\x86\xef\x2f\x2c\xd1\x8b\x2a\x74\xfc\x08\x78\x7f\x06\x54\x32\
+\x32\x96\x0e\x47\x5b\x55\x13\xbb\x97\xd4\x89\xfa\x89\x58\x26\x02\
+\x33\xa2\xa6\x55\x66\x65\xab\x05\x5a\xa7\x36\xa1\x53\xa5\xef\x1f\
+\xe2\x17\x0d\xf5\xb9\x7a\x16\x5a\x9a\x19\x25\xcb\xce\x1b\x1b\x76\
+\x2d\x60\x32\x15\xfc\x62\x7f\xc6\x68\xbd\x8e\x85\x75\x69\x31\x6f\
+\xdf\xeb\xd8\x3c\x0d\x60\xb9\xbd\x4e\x26\xa4\xd9\x57\x02\x7b\x58\
+\x71\x3f\x52\xfa\xa4\x33\xe2\x7c\x3c\x55\x3c\xaa\x1b\xcf\x27\x4e\
+\x84\x73\x1a\xc1\x4b\x50\x2a\xd6\xb9\x5d\x0b\xf9\xa3\x85\xe9\x24\
+\x57\xd5\x7d\xde\x11\x81\xb3\x13\x27\x62\x0b\x18\x74\x02\xe8\x3c\
+\xe3\xcf\xc7\x11\x6b\xb9\x7d\x8a\xf5\xb8\x5f\x45\x5b\x03\xb0\x60\
+\xde\x08\xbc\x36\x66\xd1\x14\xec\x8a\x18\xc2\x68\x93\xc3\xf6\x5c\
+\xc6\x76\x21\x96\x1d\x05\xc5\xd6\x60\x83\xd7\x26\x1c\x84\x8c\xed\
+\x82\x00\xf0\x60\x48\xc3\x40\x19\x89\xe0\xe0\xd1\xa2\xdf\x3e\xe6\
+\x6a\x60\x88\xbf\xa5\x0d\x77\xb4\x3c\x0f\xbf\xdf\xa7\x73\xb9\x4f\
+\xfb\x60\x97\x5e\xfb\x12\x77\x30\xe4\xe0\xa2\x45\xd6\xe8\xd3\xbe\
+\x10\x6e\x99\x46\xbe\x4a\xb6\xef\x27\x12\x80\xfc\x5e\x48\xa6\x51\
+\x4b\xe8\xbd\xb4\x81\x93\x28\x1f\xf3\x1d\xe1\x89\x88\x4b\x87\xa4\
+\x16\x96\xed\x00\x3a\x7e\x8f\x80\x5a\xc2\x80\x92\x4c\x28\x8b\x35\
+\x96\x90\x1f\x66\x00\x00\x19\x9b\x49\x44\x41\x54\xe7\xb9\x08\xe7\
+\x25\xc4\x3c\x4f\xeb\x5e\x67\x20\x3d\xef\x52\x7d\x1d\xeb\x5d\x07\
+\xfc\x8f\x62\xe0\xb4\x21\xa7\x3f\x27\xb7\x12\xd8\xba\xee\x7d\xde\
+\xad\xea\x3b\x33\xae\x38\x55\x84\xea\x14\x55\x4f\x89\xce\xd0\x81\
+\x81\x60\x1a\x99\xcd\xe6\x3a\x13\x5c\x6b\x3d\x31\x7b\x6f\xd2\x1b\
+\xb2\xbb\x1f\xcc\x0c\x14\x1a\x74\x82\x69\x8d\x1d\xde\x90\x30\xb2\
+\x63\xe0\xc6\xa0\x8c\x41\xe6\x61\x12\x46\x36\x0c\x86\x94\x8a\x0d\
+\xdc\x81\xec\x86\x28\xb6\x42\x82\x88\xd7\x4a\x5e\x1b\x77\x20\x58\
+\x19\x40\x2e\x10\x77\x50\xc4\x2c\x9a\x84\x83\x90\x6c\xd1\x66\x3c\
+\x20\x66\xf9\x82\x08\x67\x07\x11\x54\x6c\xcc\x81\x18\x76\x03\x65\
+\x6c\xcf\x8d\x47\x90\x4d\x6f\xfb\x95\x09\x81\x66\xad\xeb\xae\x23\
+\xe9\xd9\x98\x77\xc2\x66\x0c\xbf\x38\x72\xd4\xac\xd9\x0c\x97\x5b\
+\xb4\x4e\x81\xd3\xe9\xd8\x58\x59\xf9\xa0\x97\xb9\x8b\xf1\x60\x36\
+\xa8\xd6\xae\x3c\xb7\x4e\xf0\x3a\x69\x90\x0e\x76\xcc\x2b\xa3\x9a\
+\xc7\xa6\x32\xd7\xa1\xea\x3b\x60\x25\x93\x73\x9e\xc7\xb8\xd7\x45\
+\xe6\xa4\x67\xc2\xae\x64\x66\xa4\x83\x64\xdf\x8f\x5a\x44\xd7\xdd\
+\xf4\x48\x68\x42\x1b\xc7\x00\x6f\x75\xb3\x6c\x1f\xef\xb2\x79\x79\
+\x9f\x71\xe3\x52\xb5\x42\x00\xa8\x2f\xbe\x42\xc9\x3f\xc2\x25\x1e\
+\x96\x33\xc8\x89\xb9\x1e\xbb\x01\xd9\xd6\x9b\xec\xda\xa2\x11\xe1\
+\x51\x3c\x13\xda\x35\xc7\x98\x25\xc3\xc3\xb3\x93\x07\x52\x32\xa4\
+\x1b\xd9\x53\x76\x8e\x3d\x18\xf2\x35\x09\x54\x8f\x0c\x0d\x03\xdc\
+\xc1\x50\x0d\x6c\x74\x07\x43\x4a\x86\x17\x33\xb2\x91\x60\x64\xc9\
+\xee\xf2\x7e\xc3\x40\xcc\xc9\x1b\x08\x17\x56\x38\x28\xe2\xf7\xfb\
+\x49\x00\x7b\x31\xe8\x1e\x1d\x26\x00\x3c\x4f\x1b\xea\x27\x49\xfa\
+\x88\xf5\xe7\x97\xeb\xa2\x7f\xb0\x64\xe1\xc1\xa9\xad\x98\xb8\x1d\
+\x1a\x89\x80\x86\x3e\x3a\x37\xca\x54\x54\x85\x8a\x2c\xed\x7f\x5e\
+\x33\xc2\xeb\x4e\xb6\xfe\x9e\x66\x2f\x98\x49\x50\xba\xee\xf3\xf4\
+\xae\x45\x32\x8f\x61\xde\x71\x78\x1e\x80\x13\xf1\x80\x4c\x86\xe2\
+\xc0\x9c\x6b\xd4\x49\x00\xe7\x1b\xe5\x6b\x3d\x10\xcf\x5b\xb4\x55\
+\xdf\x99\xd9\x47\x36\x9f\x39\xc7\x80\x0a\xdc\xc8\xdc\xe2\xa2\xfb\
+\x84\xbd\xfd\x0e\xbd\x6e\x3c\x7f\x7a\xe5\x65\x2e\x46\x0f\xd5\xb0\
+\xc6\x86\x99\x5c\x48\xa6\x3d\xed\xa4\xe9\xec\x1e\x72\x7a\xf2\x50\
+\x04\x3b\xdc\xc8\xc6\xf6\xc4\x0f\x95\xdb\x34\x03\xba\x03\x43\x4d\
+\x13\x75\x23\x7b\xca\xbe\x31\xa0\xc7\x78\x94\x8a\x51\xac\x83\x05\
+\xa3\x7b\x76\x09\x3c\xf1\xe5\xc6\x76\x21\x01\x7c\x01\x74\x61\x40\
+\xb6\x23\x68\x18\xc9\xc5\x63\x66\x4a\x94\x46\xf1\xb0\x14\x3f\xcb\
+\x85\x35\x4d\xb6\xb9\x6a\xf7\xa7\x8d\xb2\xb5\x88\x5e\xfa\xe0\xea\
+\x4e\xfa\x99\x83\x5f\x11\xff\x5b\xa1\x47\x71\x75\xda\x1b\xc2\xec\
+\x75\x12\x1d\x20\x65\xc8\x54\xef\x9c\x23\x9d\xf7\x69\x00\xeb\x3e\
+\xdc\xeb\xf2\x79\xd3\xcf\x5d\x35\xea\xcf\xcd\x6b\xd0\xfd\xbb\xe9\
+\x08\x9d\x04\xf3\x3c\x59\x91\xce\xd8\xfb\x28\xe0\x49\x00\x4b\xf0\
+\x0e\x8a\x21\x51\xc5\x60\xd4\x76\xe6\x12\xc4\xbc\x85\xa1\x7f\x87\
+\x73\x66\xbd\x1a\x7a\xc2\x14\x7d\x31\xf9\xaa\xda\x5f\xa4\x13\x05\
+\xf8\x57\x1d\x98\x1c\xe2\xf0\x88\xa5\xfc\x4b\x94\xfc\xa3\x78\xe4\
+\x6e\x35\x96\x7b\x43\xd5\xe3\x2f\x6b\xdf\x10\xf2\xe3\xc5\x35\xf2\
+\xcd\x57\x66\x99\x58\x6e\x15\xdb\x1a\x1e\x66\xd1\x14\xa0\x8b\xc1\
+\x39\x05\x60\x41\x81\xdd\x8d\x6c\xc1\xb0\xb1\x96\x0e\x07\x21\x36\
+\x39\xf5\x1e\x25\x41\xe4\x56\xbe\x2f\x66\xe5\x31\xde\xdc\xc5\x03\
+\xe0\xe6\x73\x54\x02\x97\xd1\xbe\x33\x17\x30\xb2\x7a\xe3\x3a\x37\
+\x93\xbc\x2d\x13\xcd\xb4\xa2\x6a\x9a\xb6\xf2\x44\xb4\x3a\x71\xc5\
+\x45\x2f\xbc\x36\x39\x7e\x12\x57\x15\xfb\x45\xef\xb9\x1d\x23\x75\
+\xc0\xe9\x06\x67\xda\xaf\x7d\x9d\x7b\x6d\x1e\xe8\x54\x37\xcf\x54\
+\x07\xcf\xe7\xb1\xb8\xd1\x8f\x54\x15\x87\x7e\x2c\xe6\x49\x85\x74\
+\xb8\x59\x6a\xe1\x51\xdb\xf9\x6b\xc9\xa5\xe7\x2d\x98\x8e\x21\xf2\
+\x33\x64\x14\xee\xbc\xd1\x20\xec\xb6\xe9\x76\x32\xaa\xcc\x2d\x51\
+\xd9\x11\xdf\x5a\x61\x41\xb1\xf0\x02\xc7\x0a\xc8\xf2\x78\x98\xe2\
+\x12\x2e\xf4\x6f\x9a\x89\xa5\x9c\xf0\xec\x52\x82\x89\xcd\xa2\xa9\
+\x58\x56\x86\xa5\x25\xa8\xed\xd4\x84\x4a\x7b\xce\xc4\x4a\x7d\x91\
+\xc8\xbf\xa3\xd8\x38\x66\x60\x37\x9f\x53\xf7\x3d\xc6\xec\xd6\x44\
+\xe6\xff\x42\xa3\x32\xc3\x70\x69\x97\xd9\xbc\xa0\x87\x3c\x99\xb5\
+\x7a\x4d\x3b\x38\x9e\x92\x11\x19\xba\x09\x43\x4e\xea\xe1\x79\x7d\
+\x81\xf5\x46\x83\xf3\x2a\x52\x94\xd7\x42\x0b\x80\xa4\x81\x36\xa9\
+\x58\xcf\xf5\x0f\xa7\x75\x6c\xba\xb4\xe8\xa3\x64\x83\xcc\x87\x98\
+\xb7\x28\x74\x57\x5a\x7a\x2b\xaf\x5e\x12\xcc\xd7\xf9\x8a\xd3\xdf\
+\xf3\xa3\x8c\xd2\xb9\x8d\xcf\x8f\x1e\xd3\x8b\xe2\xcc\x36\xd9\xf9\
+\xc0\xdf\xa1\x53\x4e\x8e\x2e\x6b\x9a\xc3\x04\x0b\x37\xf2\x3e\xed\
+\x91\xc5\x02\xc7\x04\xf5\x86\x90\x13\x20\xc6\x79\xa5\xb5\x31\xa0\
+\x98\x55\xc8\x88\x82\x02\xae\x7c\x2c\xa5\x86\x64\x59\xe1\x53\x2e\
+\xcc\xb0\xaf\xee\x89\x50\xab\x2d\xd6\xd0\xd2\x08\xd4\x6f\xe9\xf6\
+\x5a\xd6\xd9\x1b\x62\xbf\x51\x4f\x85\x6e\xf5\x26\x29\xcf\x0b\xdf\
+\xce\x63\xe1\x04\x43\x74\xba\x2a\xa7\x61\xe8\xbb\xc9\x71\xb7\x1a\
+\xf3\xcb\x06\x7e\xb2\x86\xec\xa3\x52\x2e\xe7\x45\x14\x25\xb8\xf5\
+\xa6\xdd\xd7\xe5\xe3\xea\xb5\x85\xf3\xa2\x92\x69\x00\xeb\x3a\xf9\
+\xa3\x02\x13\x12\x9c\x69\x20\xeb\x00\x46\x15\x0b\x7c\xf4\xe7\xc9\
+\x4c\xb8\xf4\x3e\x7e\xd1\x53\x19\x6d\xd9\xbe\xaf\x16\xa1\x7b\x76\
+\xc4\xf1\xd0\xc2\xe3\x0a\xa7\x7d\x39\x53\xa6\x24\x01\x6c\x96\x7b\
+\x6a\x98\xfd\x02\xc7\x84\xf9\x65\xda\x23\x8b\x46\xde\x27\xcc\x2f\
+\x4f\x3b\xc5\x9b\x45\x13\x33\x33\xdf\xb8\xd3\x5d\x61\x52\x07\xeb\
+\xc0\x35\x8b\xa6\x02\xa3\xbc\xaf\x22\x7e\x29\xb6\xd5\xc1\x3b\x0f\
+\xc8\x92\x81\xa5\x2e\x96\xf7\xfd\x8c\x88\xce\x5c\x8c\x1e\x62\x67\
+\x32\x89\xde\x63\x7a\xd2\xcb\x75\x01\x83\x56\x35\x33\xc3\xc2\xea\
+\xb5\xce\x34\x2f\x43\x26\xec\xa4\xdb\x94\xca\x7e\x65\x52\x0f\xeb\
+\x35\x72\xe9\x44\xfe\x79\x57\x89\x79\x85\xab\xf3\xea\x04\xe7\xb1\
+\x9d\x9e\x4e\xfa\xbc\x80\x48\xc1\x2a\x71\x8e\xf1\x91\x9e\x83\x79\
+\x6e\xb4\xa8\x62\x60\x86\x3d\x06\xc5\x10\x33\xec\x29\x7b\xc2\x0b\
+\x02\x42\xb3\xfa\x91\x52\xc2\xe8\x47\x8a\xf9\xd3\x0b\x2c\x3d\xcd\
+\x55\xbf\xdd\x28\xf8\x6a\xac\x86\xaa\x7a\xf6\x77\xd4\xd4\x2d\x39\
+\x57\x0f\x44\xa5\x4b\x98\x5f\xa6\x5c\xec\x61\xac\x64\x69\x8f\x2c\
+\x95\xf2\x99\x70\xa0\x4a\x0f\x82\xd4\xc0\xf3\x40\xa7\xd8\x3a\x36\
+\xd6\xa4\x04\xf1\xec\xd2\xf4\xfd\xb1\xe1\x97\xd8\xff\x1a\x49\x91\
+\xfe\x7c\x9d\x81\xe5\x7d\xb3\x7f\xc5\xd5\x9e\xa5\x0e\x9c\xbc\xbc\
+\xcf\x6b\xa4\x9d\xbe\xcc\x59\x55\x53\xa5\x3f\xa6\x6f\x7d\xa7\x80\
+\xeb\x4c\x12\x46\x87\x04\x64\xba\x87\x82\x64\x4e\xe9\xad\x78\x9e\
+\xd7\x21\xed\x5f\x4e\x97\x52\xcd\x73\x8b\xa5\xa3\x6f\x33\x69\x94\
+\xa9\x36\x5e\x69\x40\xcb\x1c\xe7\xef\xc5\x90\x9b\xc7\xc8\xa1\x59\
+\xc5\xce\x64\x12\xa0\x95\x60\xfe\x28\x36\x5e\xaa\x3c\x5f\x13\xcf\
+\x1b\x95\x06\x60\xad\xbf\xc0\xa7\x6f\xaf\x50\xb9\x5b\xa7\x76\xe5\
+\x2b\x26\x96\x03\x1e\xd5\x64\xa7\xbe\x90\xae\xe5\x4f\x94\x60\x6b\
+\x8d\xdb\x77\xee\xf3\xd9\xcd\x12\xa5\xc5\xca\xb4\x53\xfc\x34\x20\
+\xc1\xb5\x06\x56\x1a\xe8\xd2\x28\x93\xfb\xea\x9f\xa1\xbb\xd1\xd2\
+\x9f\xad\x33\xf3\x3c\x89\x61\x66\x4a\x53\xf0\x66\x4a\x94\x8a\x05\
+\x5a\x65\xe3\xda\xa4\x98\x8f\xd2\x63\x12\xc0\xf3\x58\x78\xe2\x0f\
+\x67\xda\x01\xe8\x80\xd4\x2b\x7c\xd3\x63\x76\xe7\x31\x70\x5a\x23\
+\x26\x7a\x65\x68\xef\xb9\xce\x00\x4d\x4b\x88\x99\x56\x05\xda\x02\
+\x48\xef\x2f\x13\x6c\xce\x31\x54\xc5\xf2\xf3\x58\x78\x50\x0c\x31\
+\xfa\x11\x46\x3f\xc2\x0b\x82\x84\x14\xf8\xeb\x24\xfe\x48\x9d\x2e\
+\x17\xe2\x75\x6e\x3d\x69\x5f\xe8\xb2\xce\x3f\x7a\x8c\x1b\x8c\x58\
+\x08\x97\xa8\xde\x14\xd3\xa6\x26\xc3\xf7\x13\xb3\x0f\x27\xfe\x90\
+\xee\x55\x9b\x17\x4b\x0d\xbe\xb8\xf5\x80\x2f\x6e\x3d\x60\x73\xbd\
+\x4c\xf9\xd3\x2f\xf1\x23\x0f\x3e\x2f\x70\x62\x16\xcd\x84\xfe\xd5\
+\x19\x30\x6d\x80\x5d\xf7\xdc\x75\x9a\xf7\x3a\xf0\xce\x63\xfb\x34\
+\x90\x81\xff\xaf\xb3\xab\xeb\x71\x1c\x4b\xcb\x8f\x3f\x52\x89\xed\
+\x38\x76\x52\x55\xdd\xd5\xbd\xdd\x3d\x3d\xd5\x3b\x2b\xcd\xdc\xec\
+\x0a\x84\x84\xd0\x08\x81\x10\xdc\x00\x17\x08\xc1\x25\xab\x15\x3f\
+\x8a\x0b\x7e\x01\x3f\x61\xaf\xd1\x0a\xd0\x22\x56\xa3\xd5\xd0\x30\
+\x3d\xd3\xd3\x1f\xc5\x54\x77\x57\x25\x71\xe2\xd8\x49\x2a\x8e\xcd\
+\x85\xfd\x9e\xbc\xe7\xe4\x1c\x27\xbd\x96\x4a\x49\x1c\x97\x93\xd8\
+\x8f\x1f\x3f\xef\x37\xc6\xab\xa6\x4d\xd6\xed\x16\x0b\x3c\x97\xc0\
+\xcb\x0d\x23\xe9\xea\x66\xd1\x39\x77\x60\xd7\x43\x06\x07\xfb\x5d\
+\x3f\x67\x49\xdd\x15\x5d\xe7\x9e\x6a\x9b\xa8\xa4\xba\xd7\xa2\x96\
+\xdb\xad\x64\x74\x2a\xd5\x29\x3a\x26\xd5\xbd\x56\x93\xfb\xdb\x3e\
+\xe7\xee\xee\x1a\xf7\x50\xe1\x26\x05\x4e\xed\x61\xab\x3b\xcd\xcf\
+\x6d\xe1\x4a\xf3\x73\x5b\xf2\x11\xab\xc1\x0e\x93\xa4\x20\x1d\x4c\
+\x1e\x0c\xd3\x9d\x45\x92\x6f\xa5\x05\x34\x4d\x51\xfa\x17\x16\xa6\
+\xd3\x04\x63\xfb\x46\xe4\xc8\x74\x7a\x5f\x88\x9c\xe2\x00\x27\x82\
+\x8d\xdf\x9c\x2c\xf1\x38\xa8\x30\x18\x0d\xf0\x69\xff\x1c\xbf\xef\
+\x04\x88\x7e\x14\x34\x77\x0a\xca\x5f\x60\xac\x49\x20\xca\x2a\x0f\
+\xe5\x36\xd3\x4a\x0b\x0e\x46\x13\x7b\x9b\x24\x03\xdf\x77\xdb\x32\
+\xec\x2c\xd1\xeb\x55\xb0\xe3\x33\xbc\x7e\xd1\x95\xd8\xb0\x93\x16\
+\x72\xbe\xac\x26\x49\x9e\x32\xd4\x86\x1a\x39\xc1\x07\x0f\x9a\xdc\
+\x59\x6d\xc1\x0c\x5d\x7f\x85\xb6\x5c\x02\xae\x89\x75\x40\x36\x25\
+\xd3\xa8\x91\xb9\x36\x6f\x46\x69\x0f\x30\x77\xfb\xe8\x0e\xfb\x18\
+\x97\xd3\x83\x49\x3e\x7e\x6e\x4b\x46\x9c\xc9\xf5\x66\xb3\x8b\x9d\
+\x3f\xae\xa7\x0b\x8c\xa2\x91\xf0\x82\x1c\x23\x61\x22\x7b\x20\x6c\
+\x94\xc5\xbb\x0a\xb1\x95\xe0\xb4\x3c\xc7\xe3\x5e\x9d\x30\x9f\xdc\
+\x7e\xa5\x77\x71\xbe\xbf\xc2\xcd\xec\x5b\x54\x2b\x0b\x3d\x58\xc8\
+\xbd\xa0\x69\xba\x0d\xbd\x9c\x90\x4e\x68\x18\x1e\x05\x4e\x1d\x5b\
+\xb7\xc9\x12\x21\x17\x0c\x0c\x4e\xeb\x57\x2b\x0b\xdd\x55\x61\x4c\
+\x7b\x54\xcb\x8e\xf8\x42\x29\x96\x3a\x16\xe6\xe5\xe6\x87\xa2\x5b\
+\x5c\x4e\xb4\x01\xfc\x90\x05\xaf\xf6\x66\x30\xb5\xa0\x6d\x03\x83\
+\x29\xe0\xc0\xc1\x7c\x48\x4a\x70\x20\x7b\x8e\x23\x5e\xe7\x7e\xa9\
+\xdd\x9e\x17\x00\xf0\x7d\xd3\xc5\x62\xa5\x15\x4e\xed\xa1\xd6\x87\
+\x2d\xce\x67\x79\x02\xcc\x6b\x77\xe5\x68\xbe\xbb\x70\xd6\xf1\x05\
+\x56\x41\x0a\x6c\xde\x8a\xb0\xb3\xd4\xb8\x1b\x27\x98\x0c\x9c\x5d\
+\xd2\x10\x80\xfe\xd2\x97\x71\x74\xe8\x44\x50\x1f\x0a\x2e\x33\x38\
+\x38\xdb\xbc\x0f\x6d\x12\x43\x27\x2f\x74\xeb\x9d\x6e\xff\xa3\x4f\
+\x28\x19\x73\xe5\x20\xde\xab\xd1\x22\x6b\x57\xa7\xa5\xdb\xc0\xc3\
+\x5d\x62\xba\xd0\xb2\x09\x54\x26\x69\xa0\x93\x1c\x3a\x3d\x7d\x28\
+\xc0\x70\xcc\x05\xa8\x33\xe4\x48\x13\xab\x12\x43\xf5\x19\x5b\x41\
+\x6a\xbc\xc0\x28\xa2\x57\x85\x16\xc6\xe5\x54\x44\xea\xb4\x9a\xb8\
+\xe9\x9a\x19\x57\x16\x6e\xcb\x54\x14\x1e\x58\x8b\x0a\xae\x7d\x01\
+\x74\x1e\x0b\x26\x56\x67\x4a\x47\xf6\x00\xef\x93\x29\x7e\x58\xd5\
+\x44\xb2\xf0\x72\xf4\x4f\x4e\x76\xe3\x0e\x4c\x7e\x59\x93\xa1\xc5\
+\xb7\xe5\x52\xc3\xe4\x07\x36\x01\xd8\x24\x47\xf8\x7a\xfa\xbc\xe5\
+\x2a\x41\x55\x7d\x85\xc5\xed\x44\x5b\x11\xa1\xde\xea\x46\x76\x85\
+\x2d\x22\x0c\xed\x4a\xf4\x09\x16\xbf\xb3\x78\x2f\x9a\x9e\x1c\xcb\
+\xa0\x1c\xb8\xbc\x01\xe2\x31\xc1\x0a\x9d\x34\x30\x19\x83\xba\x10\
+\xef\xa1\x7c\x08\xca\x55\x38\xd6\xad\x46\x86\x1c\x01\x3a\x4b\x4b\
+\x01\xdc\x05\xaa\x3d\x4d\xac\x2b\xc3\x22\x29\x41\x5d\x82\xb8\x0c\
+\xe1\x79\x13\xf4\x3b\x85\x6b\x6d\x6e\x69\x35\x76\x95\xbe\x16\x9a\
+\x38\x3e\xfb\xe9\x3e\x81\xb8\x3d\xcc\x5e\x4d\x61\xe3\x05\xfc\xa5\
+\x5d\x8f\x3e\xb0\x73\xb1\x4f\x5b\x07\x56\x93\xa1\xa5\xbe\xe6\x72\
+\xc0\xe4\x6d\x38\xa4\x8f\x4d\x40\x27\xcd\xbc\x5d\xdf\xe0\x7f\x92\
+\x7b\x62\x06\xb0\xc9\x88\x53\xd7\x39\x4d\x37\x64\x92\x13\xb3\x64\
+\x86\x69\x69\xed\x0d\xe1\x3e\x74\xfb\xe7\xc0\x55\xf5\xb0\x4e\x27\
+\x9a\x7c\xb9\x52\x89\x94\xc6\x43\xa1\x0b\x39\x1f\xca\x0f\xa6\x85\
+\x3c\x12\x26\x39\xa2\xa6\x54\xf2\x10\x73\x1f\x96\xa4\x8b\x89\xa1\
+\x4d\x99\x6c\x5c\x4a\x10\x80\xb9\x51\xc8\x7d\xd5\x54\xc9\x2d\xec\
+\x86\x66\x56\x34\xff\xae\xf5\x50\x19\x08\x4d\x4c\x8d\x05\x33\xdc\
+\x21\x73\x1f\x89\x74\xcc\xe8\x74\x88\x45\x72\x89\x13\x7f\x52\xf7\
+\x27\x5e\xb9\x40\xaf\xd8\x97\x13\x2a\x58\x0f\x81\x51\x35\xd0\xd2\
+\xc2\xac\xad\x0f\x19\x7e\xba\x0b\x20\x74\x6d\x2c\xe1\x88\x68\xdd\
+\xa1\x88\x11\xdd\x7a\xa2\x38\x92\xc0\x4b\x60\xb6\xe7\x89\xdc\xb1\
+\x11\xfa\xea\x08\xde\x9c\xf0\x90\xc1\x67\xca\xf1\x35\x05\x2e\x78\
+\xd4\x4e\xa7\xc7\x8f\xc9\x44\xe3\xeb\x88\xf9\x78\xd2\x8d\x29\x3a\
+\xc7\x75\x30\xf9\x81\xe9\xf5\x02\x15\x82\xd0\x86\x9f\xdb\x22\x7b\
+\x4d\x05\x3d\x81\x76\x3d\x5d\xec\x35\x5b\xa1\xe7\x04\x50\x5e\x38\
+\x1b\xf4\x3b\x52\xab\xd7\xb9\xdb\x17\x9d\x7d\xd2\x7c\x86\xc5\xdd\
+\x9d\xd0\xc4\x70\x2f\x77\x43\xd5\x8b\x97\x08\x58\xda\x42\x55\xbe\
+\x44\x52\xc5\x20\x8d\xd8\x2f\xfd\xda\x4f\xcc\xa5\x81\xca\xc4\x3a\
+\x66\xe6\xa0\xa5\xff\x21\x16\xe7\x6c\xae\xfb\x5f\x75\x5d\x1b\x23\
+\x93\xe4\x28\x9c\x21\xc6\xaf\x5c\xdc\xac\xbf\x16\x09\xf1\x04\x34\
+\x35\xb9\x66\xd0\xcf\x05\x03\x73\xf0\x4e\x4b\x0b\xd3\xd2\x92\x58\
+\xd0\x94\xa3\xa0\x1a\x89\x26\xd9\xa1\x36\x25\x31\xe5\x2f\xe8\xa4\
+\x0f\xaf\x34\x69\xd3\xf9\xc7\x48\x14\x62\xbe\x7b\xa8\x8e\xce\x54\
+\xb3\xd2\x4a\xd4\x2e\x02\x40\xd6\x0c\x55\xcc\xd2\x12\xb9\x5f\x4a\
+\x12\x41\x65\xe3\x2a\xb4\xf6\x52\x34\xf9\x42\x17\x13\x97\x4d\x62\
+\x74\xef\xa0\x42\x1c\x87\x75\xdf\x3a\x40\x8c\x32\xd8\xe6\x1e\xe6\
+\x1f\x80\x37\xf3\x7a\xbf\x34\x8f\x5a\x32\xc6\xc7\x53\x56\xba\x5f\
+\xdf\x95\xcb\x6a\xb1\x1f\xb1\xe3\x4c\x5c\x6e\x33\xac\x9c\x07\xe2\
+\x39\x25\xe3\x98\x34\xb3\xee\x71\x2f\xf2\xe6\x1c\x17\x45\x22\x56\
+\x0f\xfc\x1e\xec\x74\xbc\xe7\x21\x20\xa0\xf1\x6e\x36\xc4\x00\x94\
+\x27\xcc\xbd\x12\xd5\xbc\x12\x65\xf7\xc7\x30\x27\x67\x60\xb5\x5a\
+\x58\xcd\xef\xd5\xb9\xcb\xa6\xeb\xb9\x36\x02\xa7\x7e\xd6\xa1\xd4\
+\x46\x1d\x90\x4d\xf2\xa3\x2d\xe4\xcc\x75\x2f\x31\x67\x1f\xb5\x1e\
+\x26\x90\xda\x7e\x65\xcc\xad\x38\x74\x17\x54\x2f\x16\x0a\xb6\xf0\
+\x1e\xcf\xd4\x5d\x7e\x53\xac\x44\xff\x89\x34\x7a\x03\x0f\xa7\x70\
+\x46\x29\x06\xf7\xea\xde\x13\x9b\x0f\xcf\x45\x90\x83\xe7\x50\x44\
+\xa7\x43\x3c\xb9\xf3\x90\xe6\x33\xf8\x4d\x94\x38\xdf\xd4\x43\x1f\
+\x6d\x1d\x5b\x12\x08\x7b\xdb\xeb\xbd\x9c\x86\x43\x40\x56\xf5\xb5\
+\x0a\xe8\x63\x16\xce\xd8\x39\x06\x58\xe0\xf9\x5e\xa4\x8e\x17\x86\
+\xf6\xdc\x40\x54\x6b\x88\x26\xe2\xe9\x8e\x8d\x3f\xc6\x0d\x26\xf9\
+\x9a\x59\x36\x9a\xc8\xd3\x50\xf4\x2c\x15\xa0\xf2\xfc\x8d\x61\x77\
+\xd0\x9a\xa8\xa3\x03\xe4\xb1\x9e\x97\x63\xa2\x94\x7b\xb2\x2d\xb4\
+\xb5\xd9\x6a\x41\x68\x0b\x19\xc1\x81\x6c\x62\x61\xdd\xf7\xe5\x7a\
+\x1a\x00\x46\xd1\x68\x3f\x9f\x98\x9a\x72\x37\x15\x1c\xd4\x7f\x22\
+\x9c\x3d\xc1\x12\xe3\x5a\xdf\x36\xde\x89\xce\xbd\xcf\xb5\x61\xfd\
+\xd9\x76\x86\xbb\x7b\x75\x7b\x57\xca\x7c\x13\x86\x9d\x0a\x3c\xdb\
+\x09\x5a\x59\x15\xa8\x13\xd5\xf9\x63\x9b\xf1\xf7\x31\x80\xe5\xa0\
+\xa7\x7d\x2f\x57\x09\x5e\xbf\xe8\x4a\x4c\xcc\x7b\xad\xf1\xdb\x96\
+\xea\x13\x8e\xe2\x08\xe9\xa2\xb7\x37\xb3\x58\x3d\x31\x6a\x6e\x00\
+\x35\x64\x59\x15\x19\x2a\x27\x6c\xad\x6d\xa3\xfe\x13\x62\xe2\x53\
+\xc3\xc4\xea\xc9\xd5\xb5\x5a\x35\x19\x74\x2a\x60\x8e\xc9\x37\x6e\
+\xf3\x31\x9b\xd2\x2e\xad\xb4\x12\x00\x0f\xac\x4c\xfc\x71\xe3\x8e\
+\xf6\x69\x0a\x65\xf3\xf0\xb4\x95\x56\x7b\x41\x96\x41\xb1\xa8\xbb\
+\xcd\xb3\xa0\x50\x69\x0f\x44\x62\x7c\xe8\x47\xf0\x86\xf5\x7b\xd6\
+\xfd\x8e\xf0\x29\xd3\xa8\x31\x00\xb0\xab\x39\x22\x27\xc2\x03\xab\
+\x80\x87\xd3\xba\x91\x20\x73\xdd\xd9\x6d\x40\xe2\x8f\x92\x5b\xad\
+\x61\xe5\x36\x76\x3e\x96\x85\x4d\xe0\x4f\xdd\xfa\x87\x79\xbd\x58\
+\x62\x61\x5d\x57\x47\xea\xde\x23\x5f\x69\x35\x1b\x17\xfe\x5a\x78\
+\x24\x4c\xc5\x97\xaa\xcb\x27\x9d\xee\x32\xd5\xac\x6d\x6a\x94\x01\
+\xc4\xda\xab\x22\x83\x33\x8c\x04\x83\xf7\xcf\x46\xe2\xe4\xea\x12\
+\x7e\xd4\x0b\xc1\xf4\x5c\x17\xbc\x38\x54\x1c\xba\xd7\xe1\xbd\x69\
+\x98\xcd\x41\x29\xb4\x71\x90\x0a\xb6\xcd\xaa\x00\x0b\x00\x55\x16\
+\x0a\x83\x8f\xef\x53\xf5\x80\x50\x24\xaf\xcd\xfb\xc1\xf3\xb8\xd5\
+\x0c\xb6\x51\x54\x03\x31\xb6\x12\x5c\xc4\x0f\x1b\x89\x53\x4f\x26\
+\xe8\x8c\xba\x3b\xe3\xae\xd1\xc3\x3f\xfb\x7c\x84\xde\x27\xcf\xe4\
+\xa8\x6b\xd3\xe3\xc3\x2e\xb7\x19\xa6\x9b\xa6\xc6\x6c\xe3\xed\x19\
+\x66\x5c\xcf\x92\x4e\x56\x0d\x3b\xf5\xaf\x8d\x6d\xdb\x0c\x3f\x75\
+\x7d\xea\x04\x48\xfe\xf7\x4a\xb0\x9b\xe9\x24\xaa\x00\x9e\x25\x33\
+\x31\x8a\xcb\x9e\x27\xda\x72\xa2\xb6\x25\x1c\x76\x44\xe1\x69\xe5\
+\x84\x98\xae\xe7\xa8\x9c\x50\xea\xe9\xa6\xea\x67\x5e\xa8\xba\xb8\
+\x9d\xec\x49\x13\xf5\xf6\x7f\x6c\x95\xb3\xca\xde\x26\xa3\xd4\xc4\
+\xcc\x54\x9d\x41\xc0\xa5\x3b\xc4\x02\x75\x24\x6e\x01\x26\x2f\xb2\
+\x50\x44\xed\x74\xee\x35\x1e\xcc\xa0\x48\x9e\x49\x37\xab\x44\x43\
+\x4c\xdc\x71\x7b\xe8\xb9\x01\xbe\x7f\xf9\xc3\xee\x77\x01\xf8\x9c\
+\x0d\x02\x4d\x92\x54\xcc\x09\x21\x36\x0e\xee\x3f\x42\xf7\xec\x44\
+\x74\x01\x02\x00\xa7\xc9\x36\xb4\x6d\x27\xc0\x13\xab\x40\xb9\xcd\
+\x30\xec\xd4\x01\x06\x02\x35\x67\x47\x4a\xc6\xf1\x31\x17\x60\xa7\
+\x6d\x49\x82\x70\x29\x62\x02\xb0\xca\xbc\x6d\xbe\xe9\x55\xba\xc1\
+\xdb\xd5\x35\xd2\xab\x97\xc2\x33\xc1\xbd\x02\x34\x89\x48\xa6\xd1\
+\x06\xd4\xe1\x2e\x47\x42\x57\xe7\xd6\x6a\x54\x4e\x37\x12\x38\x3d\
+\xc7\xc1\x76\x3a\x43\xff\x6c\x64\xd4\xcf\x1c\x58\xbc\xf7\x9b\x8e\
+\x41\x75\xfe\xed\x36\xcd\xae\x6e\xdf\x16\x1c\x31\x7d\x2e\x67\xe2\
+\xe5\x76\x0b\xdb\xaf\xa4\x47\x8a\xd6\x95\xb9\xa5\xf5\x13\x93\x57\
+\xc3\xc4\xba\x26\xf0\xaa\x9d\xe3\x37\x93\xb5\x08\xce\x90\xb7\xe1\
+\x7c\xd4\x81\xfb\xf0\x3e\x2e\x43\x16\x6e\xe6\x29\xaf\xb1\x8d\xcb\
+\xa7\x4f\x11\xfa\x35\x59\xd1\xd0\x19\xda\xa7\x5d\x6e\x33\xbc\xa9\
+\x5c\x09\x54\x34\x8c\xdc\xe4\x5d\xa0\xf7\xc7\xab\x12\xa7\x3d\x5b\
+\xcb\xae\xe3\x55\x89\xb0\xe8\x68\xe5\x84\x6e\x7b\x95\xf1\x29\x29\
+\xe9\xd5\x7f\xfc\x37\x92\xdb\xaf\x76\x1d\x21\x99\xf6\x34\xc9\x08\
+\x62\x62\x0a\x7a\xb4\xb1\x30\x6f\x61\x4a\x07\xdc\x73\x1c\x09\xc8\
+\xa2\x69\x34\x63\x5b\x1d\x38\x4d\xef\xa9\xcc\xad\x26\xc6\xb7\xe9\
+\x5a\x3e\x35\x95\xeb\xec\x63\x42\xcd\x94\xac\xce\x41\xe7\x39\x8e\
+\xa4\x63\xcb\x7c\xe7\x27\x26\xaf\x05\x07\x28\xff\xcc\xee\xb0\x2f\
+\x12\xe7\x4d\xe0\x35\x1d\x17\xd2\xaf\x99\x7d\x87\xb9\xdb\xc7\x74\
+\x36\x13\x49\x3d\x6f\x5f\xbe\x07\x92\x7a\x9f\xe1\xa3\xcb\xfa\x5c\
+\xcf\x2d\xc9\x1b\x95\x4d\x5e\x20\xcd\xeb\xe3\xef\xfa\x1e\xb6\x6c\
+\xfc\xaf\x7c\x89\x27\xbb\x94\x45\xce\xc6\xd3\x8d\x27\x01\x97\xc0\
+\x36\xec\x2c\xf7\xf4\xf3\x78\x55\x8a\xf7\x52\x77\x63\xf4\x1f\x9b\
+\xc0\x4d\xfb\x2f\x9c\x21\x7e\xfb\xd5\xaf\xa5\xf9\x14\x1c\xc8\xa6\
+\x89\xf2\xb3\xa4\x4e\xfa\x99\x34\xc7\x7e\x52\xb6\x57\x3b\x70\xc7\
+\x3f\xf5\x28\xa3\x5e\xc0\xe9\x74\x23\xf5\x2e\xd3\x55\x90\xe8\xc0\
+\xcb\x53\x13\xb9\xe1\xa8\x1a\x80\x87\x5c\x6f\x9c\xe9\x8b\x79\xa9\
+\xcd\xf1\x6d\xbb\x68\x54\x23\x8e\x83\x92\xfc\xc4\xc4\xc4\x7d\xec\
+\xb6\x25\xd7\x1b\xe5\x53\xa8\xbf\xab\xca\x42\x2d\x78\x75\xe7\xc4\
+\x24\x73\x86\x51\x84\x37\x3f\x2c\xf1\xcd\x2b\x07\xd3\x69\x82\x22\
+\x5f\x8a\xea\x8e\x7a\x0e\x78\x25\x6a\x1a\x89\xb5\xd7\xb7\x77\x28\
+\x72\x17\x45\xbe\x84\x43\x21\x6d\xf2\x13\x13\x40\xa7\xc1\x4e\x4c\
+\x8b\x75\x0a\x80\x9f\x58\xc5\x4e\x3b\x37\xa0\x27\xe0\x11\x8b\x1b\
+\x83\x26\x49\xbc\x97\x2b\xac\x3e\x17\x92\xe6\xe6\x46\x04\x39\xc8\
+\x33\xc1\xdb\x38\x71\x16\x1e\xd9\x9e\x08\x66\x94\x83\x18\xb3\x64\
+\x06\x07\xcd\x4c\xe5\x23\xb4\x30\xf7\x04\x78\x8e\x83\xc5\xed\x04\
+\x9e\xe3\x48\xae\x32\xea\xef\xa6\x7a\x1b\x54\xef\x01\xe5\x14\xd0\
+\xfe\xee\xee\xae\x85\x5f\xd4\x54\x2f\xf7\x31\x52\x47\xc7\xc2\x6a\
+\x6f\x0d\x2e\x21\xd4\xe8\x1b\x4f\xbf\x24\x16\xa6\x8b\x83\x00\x4c\
+\x2e\xb7\xe5\x76\x2b\x19\x81\x3c\xeb\x4d\x07\x50\xb5\x7b\x3c\xfd\
+\x51\x47\x20\x7e\xec\x6e\xcb\x14\x9d\x41\x0f\x0f\x7b\x05\xfc\x4e\
+\x17\xae\xef\x89\xea\x8e\x4d\xe8\x8a\x2a\x90\x4d\xe8\x8a\xfc\xe3\
+\x9a\x85\x8b\x66\x9e\xdd\x52\x61\xe2\x44\x49\x1a\x67\xaf\x87\x9d\
+\xa5\xc4\xca\xa9\xbb\xc1\x30\xeb\x4a\xa0\xa7\x6d\xc2\xa2\x23\x19\
+\x89\x7c\x5f\xd3\x8d\x07\xc4\x89\x00\x2c\xdf\xaf\x90\x2f\xcd\xb6\
+\x54\x9f\xf7\xf5\x8b\x97\xcd\x60\xee\x70\x2f\x5a\xc6\x17\x5e\xb5\
+\x6c\xcf\x13\x91\x04\xcf\x7b\x1a\xb7\x2d\x9c\x39\x97\xdb\x2d\x86\
+\xdd\x81\x30\xe2\x74\x8d\xab\xd5\xb4\x47\xee\xfe\xe2\x21\x5e\xd5\
+\xc3\xa0\xba\xca\x78\x9e\x6e\x9b\xdc\xd1\x31\x35\xff\x0e\x04\x42\
+\xd5\xe8\x35\x95\xdc\x7b\x8e\x03\xdb\xaf\xa4\x80\x07\xb9\xd5\x82\
+\xd0\x16\xc1\x11\x62\xe1\x2a\xb4\xe0\xa4\xb2\x8c\x30\x75\x16\xd2\
+\x1d\x6f\x6e\x10\xf2\xf7\x29\xf4\x3c\x9f\x6d\xb1\xcd\x3d\x89\x89\
+\xa9\x8e\x52\xf5\x19\xd7\x4c\xec\xa2\xf0\x7b\x58\xa1\xaa\x99\x98\
+\xc0\x35\xdd\x78\x78\x68\x25\xe0\xaf\x09\x58\xc3\xce\x52\x7a\x44\
+\x5c\x77\xc9\x89\xf3\x44\xda\x86\xdc\x62\x61\xd1\xc1\xb0\xb3\xac\
+\x7d\xbd\xcd\xb6\xc4\xb0\x62\x7d\x12\xe3\xb4\x67\xcb\xc0\x0f\xd6\
+\xe2\xf9\xfa\xf5\x02\xe9\xd5\x4b\x6c\x42\xb7\x9e\x13\xcd\x0e\x1e\
+\x6f\x88\x0d\xd4\x15\x0c\x43\xbb\xc2\x30\x6b\xa2\x4f\x4d\x17\x9f\
+\x0f\x49\x75\xf0\xd6\x46\x27\x9b\x9f\x60\x95\xd1\x78\x78\x5b\x6d\
+\x72\xa2\x73\xfc\x4f\xd7\x73\xb1\x4f\x62\x61\x9d\xaf\xf7\xa4\xe9\
+\x58\xa9\xfa\x94\x55\xc0\x91\x67\x86\x03\xfa\x90\x71\xa7\xcb\x6d\
+\xa0\xd7\x64\xc8\x91\x06\xe6\x79\x14\xdc\x77\x4c\xdb\x02\xc0\x26\
+\x8a\x85\x37\x42\x0d\x7a\x98\xc2\xee\xf7\xb0\x33\x04\x79\x5e\x8a\
+\x64\xc0\xe3\x05\x96\x18\xa3\xc2\x04\xd1\xb8\xc0\x93\xc1\x02\x71\
+\x1c\xd6\x4c\x3c\xdf\x7d\xf7\x7c\xba\x82\xb3\x7a\x25\xd8\xb8\xd3\
+\x74\x8c\x92\x34\xf1\xb0\xb3\xc4\x0f\x55\x2c\x58\x31\xce\x77\x80\
+\xae\x57\xb0\xc7\x86\x31\x13\x3f\x16\xeb\x38\xab\xbe\xa9\x5c\x20\
+\x89\x05\xa8\xa7\x1b\x0f\x48\x62\x90\x3b\x2f\xeb\x9e\x88\xfd\xa5\
+\x8b\x40\x7c\xe6\xb0\xb3\xac\x2f\x06\x27\xd8\x95\xab\xa4\x85\xf9\
+\xb6\xfa\x61\x04\x60\x2a\x45\x75\x48\x62\xf0\x4e\x3e\xba\xe2\x51\
+\xf5\x64\xab\xc6\x0a\x9f\x67\xa1\x03\xa0\x3a\x70\x85\x77\xa4\xe7\
+\xda\xd5\x94\x3e\xc9\x3f\xbb\xad\x9e\x8d\xbe\xab\x3b\xb0\xb5\x17\
+\x98\x2e\x24\xdd\xa6\x45\xa9\x7e\x8e\x7a\xae\x99\x32\xdd\x4c\x59\
+\x6c\xc7\x32\x30\x65\xb4\xd1\xfe\x74\xc3\x1a\x01\x20\x9d\x00\xeb\
+\xdb\x3b\x3c\xff\xb0\x5b\x77\xb3\x5d\xd6\xe3\x31\x06\x95\xe8\x38\
+\x5f\xdd\xdd\x4a\x6c\x4c\xe7\x37\x28\x4f\x60\x13\x58\xab\xd9\x5a\
+\x32\xe4\xac\xea\x3e\x86\x9d\x65\xbd\x3e\x89\xa5\x6d\xb8\x8c\xa8\
+\x66\x6b\xa1\x9b\xf9\x73\xa1\xaf\x1b\x96\xe6\xff\x43\x7a\xba\xdc\
+\x66\x98\x06\xeb\x5a\x27\x33\xd9\xb1\x4a\x37\x42\x0f\xab\xbd\x1f\
+\x82\x7e\x47\x00\x75\x75\x6f\xe7\x8f\xa5\x64\x77\x0a\x35\xeb\xe6\
+\x7c\xa8\xc6\x12\x3f\xe0\x6a\xc0\xc3\x04\x5c\x93\x1b\x8c\x33\xa6\
+\xee\x7d\xce\xda\xc7\x74\xb1\xe4\xdf\x55\xd5\xe3\x6d\x81\x91\x43\
+\x2e\xb7\xdc\x2f\xf7\x0a\x43\xb9\xeb\x4d\x8d\xf2\x05\x96\x5c\x37\
+\xa7\x76\xea\xa7\x7e\x77\x6a\xdf\x09\x7e\x81\xa8\x13\xaf\x7a\x6e\
+\x80\xb3\x51\x84\xce\xa0\x07\xcb\xbe\xc4\xf5\xba\x10\x59\x6c\x6f\
+\xe6\x7d\x9c\x3b\x1e\x36\x93\xb5\x48\x8e\x9f\xbb\x7d\x5c\x2f\x2a\
+\x91\x14\x0f\x00\x61\x3f\x93\x99\x78\xd8\x59\x0a\x56\x15\x60\x66\
+\x8c\x8b\x38\x91\xb6\x91\xc0\x1e\x75\x85\xac\x48\xfc\x58\x68\x5d\
+\xa1\x79\xe3\x64\xef\x7f\x54\x23\xb2\xdc\x66\x62\xbb\xd3\x9e\x8d\
+\xe5\x2a\x11\x7a\x58\x5d\x28\x4b\x0d\x80\x68\x41\x35\x2d\x2d\x94\
+\xc5\x7b\x6d\x29\xd2\xa1\x72\x1d\xdd\x49\xe4\x27\xf3\x10\xe0\x38\
+\x33\xf2\x7e\x0d\xa6\x6d\x0f\x75\x83\xd7\x7d\x66\xdb\x76\x1f\xb3\
+\x88\x64\xf8\x06\x98\xdc\x73\x91\xfb\x25\xfc\xdc\xde\x63\xe4\xa1\
+\xfb\xc9\x9e\xf1\xa6\x16\x26\x70\x03\xd8\x14\x45\xa4\xa1\x3c\x6e\
+\xee\xe1\xee\xee\x1a\x5b\x44\x78\x38\xaa\x5b\x53\x3d\xe8\xd6\xb9\
+\x13\xe3\xe5\x5b\x3c\xe8\x7c\x03\xb8\x97\x75\xd4\xae\x09\x74\x6c\
+\xc7\xff\xb7\xb7\x4f\x92\x13\x41\x79\x02\xdb\x8a\xba\x98\x6e\x3c\
+\xc4\x79\xb2\x0f\xe6\x38\x01\xbd\x2f\x69\x60\x0e\x76\x26\x2b\x88\
+\xd5\x25\x0d\xdd\x6c\xab\xfa\x9e\xd5\x85\x1b\x8f\xdb\xec\x7a\xcf\
+\x23\x41\x57\x31\x01\x95\x06\x25\x72\x0d\x4c\x2c\xbc\x45\xf4\xd1\
+\x27\x98\x37\x0d\x51\x83\x15\x6d\xfd\x21\xda\xc0\xac\xbb\x05\x9b\
+\x52\x37\x75\xb9\x16\x6d\x6e\xbc\x63\xbd\x18\x5a\x49\x51\x05\x70\
+\xcb\x99\x30\xe6\x72\x7f\xe7\xbe\xb3\x82\x54\x7c\x9f\x2c\x2d\x31\
+\x99\x4d\x8c\x95\xd3\x04\x4c\x7a\xce\xbd\x32\xfc\x58\xf1\xc1\xf0\
+\x94\x3b\x31\x72\x00\x7f\xd8\x83\x1f\x37\xc7\xaa\x61\xe2\xeb\xcd\
+\x4f\x10\x14\x57\x52\xd8\x79\xd3\x74\x42\x27\xfd\x4c\x72\xd1\xcd\
+\x57\x75\x16\x1b\x81\x31\xf1\x63\x09\x98\x56\xd4\x05\x92\x58\x0b\
+\x56\xf1\x3e\x03\x28\x67\x65\x6e\x1c\x56\xb3\xb5\xb4\x6f\xba\x10\
+\x54\xc6\xa6\xf5\x81\xdf\xc3\x8b\xcd\x4f\x91\x5e\xbd\x14\x09\xd5\
+\xf4\xe3\x79\x13\x14\x6a\x88\x4d\xae\x35\xce\xc2\x6a\x05\xf2\x31\
+\x27\x5f\x95\x13\x3a\xad\xa9\xb2\x3a\x4f\xb9\x34\x4d\x33\x32\x25\
+\xfb\xa8\x6c\x7b\xc8\x07\x7c\x28\xa0\xa2\x3e\xaa\x1d\x83\xd4\x8b\
+\x64\x13\xc5\x52\xa9\x3e\x00\xb8\xe5\x0c\xcf\xce\x9f\xe0\xcf\xfe\
+\xe6\x8f\xf1\x57\x7f\xfe\xb7\x78\xf6\xd9\x97\x58\xa0\xc2\x64\x36\
+\x91\x59\xb0\x39\x2f\x9b\x66\x3a\xec\x26\x74\xb5\xd3\x92\xd4\x7e\
+\x74\x52\x0e\x45\x08\x5c\x3e\x7d\x8a\xfb\x71\x1d\x4e\x06\x80\x59\
+\xf1\x19\x46\xe3\xe7\xc8\x70\x87\xce\xa8\xdb\x64\x10\xb1\xd6\x01\
+\xf8\x0c\x1e\x4e\x51\xf8\x3d\x0c\xed\xb1\x38\xd7\x76\xe2\xc7\x12\
+\xc3\x72\x46\xad\xac\xf7\x42\x22\x70\x30\x73\xff\xb1\xca\xc2\x56\
+\xd4\x15\x4c\xfc\xc4\x2a\x60\x45\x5d\xf1\xa8\x03\x3f\xbf\x28\xaa\
+\xd9\x1a\xa9\x13\xe0\xd3\xd9\x4b\xc1\xc4\xbc\x13\x4f\x14\x47\xa2\
+\x97\x30\x67\x61\xf2\x0d\xeb\x0e\xde\xa1\x5b\xab\x89\x05\x8f\xd1\
+\xc2\xdc\xd0\x3a\xc4\xfc\x87\x7a\x4d\xa8\xdf\xe1\x50\x51\xa9\xe9\
+\xbb\xea\xa6\x37\xa9\xfb\x26\xd9\xc0\x8d\x37\x4a\x8c\xbf\xff\x78\
+\x88\xbf\xff\xbd\x2f\xf1\x77\xff\xf8\x17\xf8\xcb\x5f\xfc\x09\x7e\
+\xf6\xa7\xff\x00\xfb\x49\x2c\x7d\x26\x75\xf3\x21\x37\x58\x5c\xd5\
+\xf3\x38\xa8\x6b\xa8\xea\x37\xe6\xcf\xe9\x7c\xde\x8f\x87\xb0\x51\
+\x4f\x0a\x0d\x47\x17\xf5\x36\xc9\x7f\xe1\xf5\xb2\xbb\xbb\x58\x9a\
+\x69\xb4\x3c\xf1\x68\x89\x31\xdc\x7c\x85\x69\xb9\xcb\x66\xb3\xe3\
+\x3c\x41\xe2\xc7\xd8\x66\xd7\x20\x40\xab\x8f\xfc\x56\xcf\x19\x95\
+\x18\x94\xc0\x4b\x86\xdc\x6d\x92\xe0\xdd\xed\x18\xf3\x6c\x81\xb0\
+\xe8\xe0\xa4\x77\x82\x6a\xb6\xc6\xbb\xe7\xaf\x50\xcd\xd6\x38\xef\
+\x9f\xc1\x19\x8d\xa4\x30\x36\xff\x0c\xee\x99\xa0\x36\xaa\xd6\xc0\
+\x92\x7c\xc2\x94\x27\x51\x0e\x62\xa9\x31\xb6\xea\x4b\xd6\x25\xed\
+\x10\x00\x45\xb7\x74\xc7\x39\xe8\xb3\x35\xe9\x5c\x75\x3d\x1f\x35\
+\xdb\xa6\x5f\x0f\x31\xf1\x31\x3d\x29\xd4\x46\x31\x3c\x22\x48\x39\
+\x17\x6d\xee\x3b\x49\x62\x04\xb5\x3f\xf9\xe1\xe8\x1c\xdd\x2f\xde\
+\x62\xf4\x49\x81\x3f\xf8\xf2\x8f\xf0\xf3\x5f\x7c\x81\xcb\x67\x7f\
+\x2d\xa2\x98\xab\x22\xdb\xeb\x16\x9a\x58\x95\x54\xa1\x4c\x2c\xad\
+\x66\xaf\xd1\x7a\xf2\x04\x95\xf8\xac\x66\xe0\xef\xd6\x78\xbb\x75\
+\x45\x7f\x35\xee\x52\xe5\x7e\x66\x11\x17\xa8\x0a\x8c\xec\x4a\xcc\
+\xb1\x73\x09\xa8\x63\xc3\x8f\x13\xc6\x9a\x06\xe0\xdb\xec\x1a\x56\
+\x1c\x23\x9e\x25\xb8\xad\x96\x38\x8b\x81\x69\x00\xfc\xe7\x2f\x57\
+\xf8\xfa\xdf\xfe\x19\x0f\x1e\xd4\xc2\xbd\x73\xd1\xc3\xe6\xdd\xae\
+\x3d\xe7\xa3\x1f\x79\xf8\xf4\x93\x3a\x09\xda\x7d\x10\xe3\xd3\xfe\
+\x39\x42\xab\x40\x1a\x75\x11\xbb\x8a\x5f\xd3\x09\x81\x0a\xda\x06\
+\x28\xa9\xd5\x83\x3d\x7f\x2f\xaa\x39\x26\xdb\x9d\xe1\xc7\xa7\x27\
+\x1d\x0a\x39\x93\x9c\xd0\x59\xfc\xe4\x3e\x53\xf7\x43\xfb\x56\xd7\
+\x07\x56\x86\x12\x83\xdf\xc9\xe8\x52\x0d\xa4\x43\xcf\x79\xe4\x8f\
+\x86\xb5\x8b\x01\x39\xa0\xca\x8a\x8d\xf4\x7b\xd5\x32\x25\x71\x9c\
+\xb3\x3e\x86\x91\x05\x7f\xd8\x03\x3e\x3c\x83\x5b\x14\xf0\x56\x2f\
+\xf0\xfd\xd5\x02\xb8\xfd\x55\x3d\x30\xb3\xf9\xcd\xab\x22\x03\x16\
+\x01\x3a\x00\xd0\x54\x6d\x6c\x8a\x15\x62\x58\x02\xcc\x71\xb1\xaa\
+\x47\x7e\x35\xc6\x17\xc9\x82\x78\x66\xc3\x19\x45\x78\xd0\xb4\x26\
+\xeb\x3d\x39\x87\x0b\x1f\xd1\xaf\x6a\xc9\x78\xb3\xfe\x5a\x9a\x3e\
+\x1b\x57\x96\x16\x9b\x1b\x3f\x87\x9b\x03\x98\x5b\x70\xd7\xaf\x17\
+\x18\x9f\x2d\x85\x41\x35\x06\x80\x6c\x29\x1e\x01\xe0\xdd\x6d\x08\
+\xf7\xcc\xf0\xde\xb7\x5b\xb8\xcd\xff\xdf\x26\x09\xbe\xbf\xba\xc2\
+\xbf\xfe\xcb\x3f\xc9\x9f\x78\x0d\x54\xa7\x7d\x5c\x6c\x17\x58\x2f\
+\x6f\xf0\xdd\x04\xf8\xee\xb7\xff\x2e\xde\xfe\xf1\xb3\xc7\x78\xfa\
+\xf9\x1f\xe2\xfe\xc3\x07\x58\x84\x13\x49\x73\xf6\xc3\x11\x46\x0d\
+\x4e\x46\xb6\x27\x98\x38\x5d\xf4\x10\x56\x2b\xc0\x89\x30\x99\x5a\
+\x70\x06\x89\x18\x0d\xe9\xe6\x1e\x0a\xec\x2a\x2c\x3e\x66\x0c\x80\
+\xae\x2f\x9a\xee\x42\xe0\x51\x32\xbe\xaf\xf2\x40\x5b\x2b\xb3\xc6\
+\xcd\x8c\xc6\x5c\x5b\x11\x29\x00\x9c\xc6\x31\x12\xab\xc2\x69\x15\
+\x8b\xdb\xfc\xc6\x8a\x80\xb4\x10\xc0\xad\x13\x78\x02\xac\xb1\xd8\
+\xab\x50\xf6\x1c\xa7\xc9\xfa\xab\xf0\xfc\x37\x2f\x90\x4f\x57\x78\
+\xb7\x04\xae\xaf\x6f\x90\x2e\x96\x78\xff\xfd\x35\x2c\x00\xc3\xa1\
+\xdc\x44\xe5\x34\x8e\xa5\xe4\xf5\xd8\x1d\xd4\x53\x8f\x00\xc4\x8b\
+\x7a\x02\x52\xbc\x00\xb2\xd1\x9d\x28\xf8\xcc\x46\x77\x08\xfb\x11\
+\x82\xfb\x8f\x50\x7a\x17\xb8\xd7\xe9\x22\x0f\xa2\xba\x17\xdb\xb7\
+\xdf\xd4\xd2\xc4\xbd\xc4\xa6\x77\x85\x78\x01\xc0\x3d\x81\x13\xcf\
+\xf0\x70\x74\x8e\xd2\xbb\x80\x87\x53\x78\x16\x50\x34\x8c\x8c\x41\
+\x85\xff\x07\x5b\x53\xe4\xea\xf5\xd8\xe3\x94\x00\x00\x00\x00\x49\
+\x45\x4e\x44\xae\x42\x60\x82\
+"""
+
+qt_resource_name = b"""\
+\x00\x09\
+\x06\xa8\xaa\x74\
+\x00\x71\
+\x00\x75\x00\x6f\x00\x74\x00\x65\x00\x2e\x00\x74\x00\x78\x00\x74\
+\x00\x0a\
+\x07\x2b\x67\xc7\
+\x00\x73\
+\x00\x61\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\
+"""
+
+qt_resource_struct = b"""\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x00\x18\x00\x00\x00\x00\x00\x01\x00\x00\x00\x39\
+"""
+
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+
+qInitResources()
diff --git a/sources/pyside6/tests/QtCore/sample.png b/sources/pyside6/tests/QtCore/sample.png
new file mode 100644
index 000000000..60450f0dc
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/sample.png
Binary files differ
diff --git a/sources/pyside6/tests/QtCore/setprop_on_ctor_test.py b/sources/pyside6/tests/QtCore/setprop_on_ctor_test.py
new file mode 100644
index 000000000..de8f67bb3
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/setprop_on_ctor_test.py
@@ -0,0 +1,24 @@
+#!/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.QtCore import QTimer
+
+
+class SetPropOnCtorTest(unittest.TestCase):
+ def testIt(self):
+ timer = QTimer(interval=42)
+ self.assertEqual(timer.interval(), 42)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/signal_sender.py b/sources/pyside6/tests/QtCore/signal_sender.py
new file mode 100644
index 000000000..2552591e5
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/signal_sender.py
@@ -0,0 +1,91 @@
+# 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 (QCoreApplication, QObject, QStringListModel,
+ QTimer, Signal, Slot, Qt)
+
+
+class Sender(QObject):
+ testSignal = Signal()
+
+ def emitSignal(self):
+ self.testSignal.emit()
+
+
+class Receiver(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__()
+ self._sender = None
+ self._slot_count = 0
+
+ @Slot()
+ def testSlot(self):
+ self._sender = self.sender()
+ self._slot_count += 1
+
+
+class DerivedReceiver(Receiver):
+ pass
+
+
+class TestSignalSender(UsesQApplication):
+ """Test PYSIDE-2144/1295, check that QObject::sender() works also if it is
+ routed via GlobalReceiverV2 in case of a non-C++ slot (Python callback,
+ as for derived classes)."""
+ def testSignalSender(self):
+ sender = Sender()
+ receiver = Receiver()
+ sender.testSignal.connect(receiver.testSlot)
+ derived_receiver = DerivedReceiver()
+ sender.testSignal.connect(derived_receiver.testSlot)
+ sender.emitSignal()
+
+ QTimer.singleShot(100, self.app.quit)
+ while derived_receiver._slot_count == 0:
+ QCoreApplication.processEvents()
+
+ self.assertEqual(receiver._sender, sender)
+ self.assertEqual(derived_receiver._sender, sender)
+
+
+class TestConstructorConnection(UsesQApplication):
+ """PYSIDE-2329: Check constructor connections for signals from the
+ base as well as signals with arguments."""
+ def testConstructorConnection(self):
+
+ was_destroyed = False
+ was_changed = False
+
+ def destroyed_handler():
+ nonlocal was_destroyed
+ was_destroyed = True
+
+ def changed_handler():
+ nonlocal was_changed
+ was_changed = True
+
+ data_list = ["blub"]
+ model = QStringListModel(data_list,
+ destroyed=destroyed_handler,
+ dataChanged=changed_handler)
+ model.setData(model.index(0, 0), "bla", Qt.EditRole)
+ del model
+
+ self.assertTrue(was_changed)
+ self.assertTrue(was_destroyed)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/snake_prop_feature_test.py b/sources/pyside6/tests/QtCore/snake_prop_feature_test.py
new file mode 100644
index 000000000..82087ab9a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/snake_prop_feature_test.py
@@ -0,0 +1,143 @@
+# 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 PySide6.QtCore import Property, QSize
+from PySide6.QtWidgets import QApplication, QMainWindow, QWidget
+
+is_pypy = hasattr(sys, "pypy_version_info")
+if not is_pypy:
+ from PySide6.support import feature
+
+"""
+snake_prop_feature_test.py
+--------------------------
+
+Test the snake_case and true_property feature.
+
+This works now, including class properties.
+"""
+
+
+class Window(QWidget):
+ def __init__(self):
+ super().__init__()
+
+
+@unittest.skipIf(is_pypy, "__feature__ cannot yet be used with PyPy")
+class FeatureTest(unittest.TestCase):
+ def setUp(self):
+ qApp or QApplication()
+ feature.reset()
+
+ def tearDown(self):
+ feature.reset()
+ qApp.shutdown()
+
+ def testRenamedFunctions(self):
+ window = Window()
+ window.setWindowTitle('camelCase')
+
+ # and now the same with snake_case enabled
+ from __feature__ import snake_case
+
+ # Works with the same window! window = Window()
+ window.set_window_title('snake_case')
+
+ def testPropertyAppearVanish(self):
+ window = Window()
+
+ self.assertTrue(callable(window.isModal))
+ with self.assertRaises(AttributeError):
+ window.modal
+
+ from __feature__ import snake_case, true_property
+ # PYSIDE-1548: Make sure that another import does not clear the features.
+ import sys
+
+ self.assertTrue(isinstance(QWidget.modal, property))
+ self.assertTrue(isinstance(window.modal, bool))
+ with self.assertRaises(AttributeError):
+ window.isModal
+
+ # switching back
+ feature.reset()
+
+ self.assertTrue(callable(window.isModal))
+ with self.assertRaises(AttributeError):
+ window.modal
+
+ def testClassProperty(self):
+ from __feature__ import snake_case, true_property
+ # We check the class...
+ self.assertEqual(type(QApplication.quit_on_last_window_closed), bool)
+ x = QApplication.quit_on_last_window_closed
+ QApplication.quit_on_last_window_closed = not x
+ self.assertEqual(QApplication.quit_on_last_window_closed, not x)
+ # ... and now the instance.
+ self.assertEqual(type(qApp.quit_on_last_window_closed), bool)
+ x = qApp.quit_on_last_window_closed
+ qApp.quit_on_last_window_closed = not x
+ self.assertEqual(qApp.quit_on_last_window_closed, not x)
+ # make sure values are equal
+ self.assertEqual(qApp.quit_on_last_window_closed,
+ QApplication.quit_on_last_window_closed)
+
+ def testUserClassNotAffected(self):
+ FunctionType = type(lambda: 42)
+ # Note: the types module does not have MethodDescriptorType in low versions.
+ MethodDescriptorType = type(str.split)
+
+ class UserClass(QWidget):
+
+ def someFunc1(self):
+ pass
+
+ @staticmethod
+ def someFunc2(a, b):
+ pass
+
+ inspect = UserClass.__dict__
+ self.assertTrue(isinstance(inspect["someFunc1"], FunctionType))
+ self.assertTrue(isinstance(inspect["someFunc2"], staticmethod))
+ self.assertTrue(isinstance(UserClass.someFunc2, FunctionType))
+ self.assertTrue(isinstance(UserClass.addAction, MethodDescriptorType))
+
+ from __feature__ import snake_case
+
+ inspect = UserClass.__dict__
+ self.assertTrue(isinstance(inspect["someFunc1"], FunctionType))
+ self.assertTrue(isinstance(inspect["someFunc2"], staticmethod))
+ self.assertTrue(isinstance(UserClass.someFunc2, FunctionType))
+ self.assertTrue(isinstance(UserClass.add_action, MethodDescriptorType))
+
+ def testTrueProperyCanOverride(self):
+ from __feature__ import true_property
+
+ class CustomWidget(QWidget):
+ global prop_result
+ prop_result = None
+
+ @Property(QSize)
+ def minimumSizeHint(self):
+ global prop_result
+ print("called")
+ prop_result = super().minimumSizeHint
+ return prop_result
+
+ window = QMainWindow()
+ window.setCentralWidget(CustomWidget(window))
+ window.show()
+ self.assertTrue(isinstance(prop_result, QSize))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/staticMetaObject_test.py b/sources/pyside6/tests/QtCore/staticMetaObject_test.py
new file mode 100644
index 000000000..223c334d3
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/staticMetaObject_test.py
@@ -0,0 +1,36 @@
+# 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, Slot, QMetaObject
+
+
+class MyObject(QObject):
+ @Slot(int, str)
+ def slot1(self, a, b):
+ pass
+
+
+class testAttribute(unittest.TestCase):
+ def testBug896(self):
+ mo = MyObject.staticMetaObject
+ self.assertTrue(isinstance(mo, QMetaObject))
+ self.assertEqual(mo.className(), 'MyObject')
+ self.assertTrue(mo.indexOfSlot('slot1(int,QString)') > -1)
+
+ def testDuplicateSlot(self):
+ mo = MyObject.staticMetaObject
+ self.assertEqual(mo.indexOfSignal('destroyed(void)'), -1)
+ self.assertTrue(mo.indexOfSignal('destroyed()') > -1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/static_method_test.py b/sources/pyside6/tests/QtCore/static_method_test.py
new file mode 100644
index 000000000..bbf96e44a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/static_method_test.py
@@ -0,0 +1,65 @@
+#!/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
+
+'''Test cases for overloads involving static and non-static versions of a method.'''
+
+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 QFile
+
+
+class StaticNonStaticMethodsTest(unittest.TestCase):
+ '''Test cases for overloads involving static and non-static versions of a method.'''
+
+ def setUp(self):
+ filename = 'somefile%d.txt' % os.getpid()
+ self.existing_filename = os.path.join(os.path.curdir, filename)
+ self.delete_file = False
+ if not os.path.exists(self.existing_filename):
+ f = open(self.existing_filename, 'w')
+ for line in range(10):
+ f.write('sbrubbles\n')
+ f.close()
+ self.delete_file = True
+
+ self.non_existing_filename = os.path.join(os.path.curdir, 'inexistingfile.txt')
+ i = 0
+ while os.path.exists(self.non_existing_filename):
+ i += 1
+ filename = 'inexistingfile-%d.txt' % i
+ self.non_existing_filename = os.path.join(os.path.curdir, filename)
+
+ def tearDown(self):
+ if self.delete_file:
+ os.remove(self.existing_filename)
+
+ def testCallingStaticMethodWithClass(self):
+ '''Call static method using class.'''
+ self.assertTrue(QFile.exists(self.existing_filename))
+ self.assertFalse(QFile.exists(self.non_existing_filename))
+
+ def testCallingStaticMethodWithInstance(self):
+ '''Call static method using instance of class.'''
+ f = QFile(self.non_existing_filename)
+ self.assertTrue(f.exists(self.existing_filename))
+ self.assertFalse(f.exists(self.non_existing_filename))
+
+ def testCallingInstanceMethod(self):
+ '''Call instance method.'''
+ f1 = QFile(self.non_existing_filename)
+ self.assertFalse(f1.exists())
+ f2 = QFile(self.existing_filename)
+ self.assertTrue(f2.exists())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/thread_signals_test.py b/sources/pyside6/tests/QtCore/thread_signals_test.py
new file mode 100644
index 000000000..a453d1ac1
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/thread_signals_test.py
@@ -0,0 +1,47 @@
+# 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 case for QObject.signalsBlocked() and blockSignal()'''
+
+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 Signal, QThread
+from helper.usesqapplication import UsesQApplication
+
+
+class MyThread(QThread):
+
+ test = Signal(str)
+
+ def run(self):
+ self.test.emit("INdT - PySide")
+
+
+class TestThreadSignal(UsesQApplication):
+
+ __called__ = True
+
+ def _callback(self, msg):
+ self.assertEqual(msg, "INdT - PySide")
+ self.__called__ = True
+ self.app.quit()
+
+ def testThread(self):
+ t = MyThread()
+ t.test.connect(self._callback)
+ t.start()
+
+ self.app.exec()
+ t.wait()
+ self.assertTrue(self.__called__)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtCore/tr_noop_test.py b/sources/pyside6/tests/QtCore/tr_noop_test.py
new file mode 100644
index 000000000..a3b2e257f
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/tr_noop_test.py
@@ -0,0 +1,66 @@
+# 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 QT_TR_NOOP, QT_TR_NOOP_UTF8
+from PySide6.QtCore import QT_TRANSLATE_NOOP, QT_TRANSLATE_NOOP3, QT_TRANSLATE_NOOP_UTF8
+
+
+class QtTrNoopTest(unittest.TestCase):
+
+ def setUp(self):
+ self.txt = 'Cthulhu fhtag!'
+
+ def tearDown(self):
+ del self.txt
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testQtTrNoop(self):
+ refcnt = sys.getrefcount(self.txt)
+ result = QT_TR_NOOP(self.txt)
+ self.assertEqual(result, self.txt)
+ self.assertEqual(sys.getrefcount(result), refcnt + 1)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testQtTrNoopUtf8(self):
+ refcnt = sys.getrefcount(self.txt)
+ result = QT_TR_NOOP_UTF8(self.txt)
+ self.assertEqual(result, self.txt)
+ self.assertEqual(sys.getrefcount(result), refcnt + 1)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testQtTranslateNoop(self):
+ refcnt = sys.getrefcount(self.txt)
+ result = QT_TRANSLATE_NOOP(None, self.txt)
+ self.assertEqual(result, self.txt)
+ self.assertEqual(sys.getrefcount(result), refcnt + 1)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testQtTranslateNoopUtf8(self):
+ refcnt = sys.getrefcount(self.txt)
+ result = QT_TRANSLATE_NOOP_UTF8(self.txt)
+ self.assertEqual(result, self.txt)
+ self.assertEqual(sys.getrefcount(result), refcnt + 1)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testQtTranslateNoop3(self):
+ refcnt = sys.getrefcount(self.txt)
+ result = QT_TRANSLATE_NOOP3(None, self.txt, None)
+ self.assertEqual(result, self.txt)
+ self.assertEqual(sys.getrefcount(result), refcnt + 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/translation_test.py b/sources/pyside6/tests/QtCore/translation_test.py
new file mode 100644
index 000000000..da09e47b6
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/translation_test.py
@@ -0,0 +1,102 @@
+#!/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
+
+'''Unit tests to test QTranslator and translation in general.'''
+
+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, QTranslator, QCoreApplication
+
+from helper.usesqapplication import UsesQApplication
+
+
+class TranslationTest(UsesQApplication):
+ '''Test case for Qt translation facilities.'''
+
+ def setUp(self):
+ super(TranslationTest, self).setUp()
+ self.trdir = os.path.join(os.path.dirname(__file__), 'translations')
+
+ def testLatin(self):
+ # Set string value to Latin
+ translator = QTranslator()
+ translator.load(os.path.join(self.trdir, 'trans_latin.qm'))
+ self.app.installTranslator(translator)
+
+ obj = QObject()
+ obj.setObjectName(obj.tr('Hello World!'))
+ self.assertEqual(obj.objectName(), 'Orbis, te saluto!')
+
+ def testLatinClass(self):
+ # Set string value to Latin, no instance
+ translator = QTranslator()
+ translator.load(os.path.join(self.trdir, 'trans_latin.qm'))
+ self.app.installTranslator(translator)
+
+ obj = QObject()
+ obj.setObjectName(QObject.tr('Hello World!'))
+ self.assertEqual(obj.objectName(), 'Orbis, te saluto!')
+
+ def testLatinDerived(self):
+ # PYSIDE-131: Test that derived classes work, too.
+ translator = QTranslator()
+ translator.load(os.path.join(self.trdir, 'trans_latin.qm'))
+ self.app.installTranslator(translator)
+
+ class Derived(QObject):
+ pass
+
+ obj = Derived()
+ obj.setObjectName(obj.tr('Hello World!'))
+ self.assertEqual(obj.objectName(), 'Orbis, te saluto!')
+
+ def testLatinDerivedClass(self):
+ # PYSIDE-131: Test that derived classes work, too, no instance.
+ translator = QTranslator()
+ translator.load(os.path.join(self.trdir, 'trans_latin.qm'))
+ self.app.installTranslator(translator)
+
+ class Derived(QObject):
+ pass
+
+ obj = Derived()
+ obj.setObjectName(Derived.tr('Hello World!'))
+ self.assertEqual(obj.objectName(), 'Orbis, te saluto!')
+
+ def testRussian(self):
+ # Set string value to Russian
+ translator = QTranslator()
+ translator.load(os.path.join(self.trdir, 'trans_russian.qm'))
+ self.app.installTranslator(translator)
+
+ obj = QObject()
+ obj.setObjectName(obj.tr('Hello World!'))
+ self.assertEqual(obj.objectName(), 'привет мир!')
+
+ def testUtf8(self):
+ translator = QTranslator()
+ translator.load(os.path.join(self.trdir, 'trans_russian.qm'))
+ self.app.installTranslator(translator)
+
+ obj = QObject()
+ obj.setObjectName(obj.tr('Hello World!'))
+ self.assertEqual(obj.objectName(), 'привет мир!')
+
+ def testTranslateWithNoneDisambiguation(self):
+ value = 'String here'
+ obj = QCoreApplication.translate('context', value, None)
+ self.assertTrue(isinstance(obj, str))
+ self.assertEqual(obj, value)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/translations/trans_latin.qm b/sources/pyside6/tests/QtCore/translations/trans_latin.qm
new file mode 100644
index 000000000..efdbee8c7
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/translations/trans_latin.qm
Binary files differ
diff --git a/sources/pyside6/tests/QtCore/translations/trans_latin.ts b/sources/pyside6/tests/QtCore/translations/trans_latin.ts
new file mode 100644
index 000000000..b9fcf41be
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/translations/trans_latin.ts
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS><TS version="1.1" language="lt">
+<defaultcodec></defaultcodec>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Hello World!</source>
+ <translation>Orbis, te saluto!</translation>
+ </message>
+</context>
+</TS>
diff --git a/sources/pyside6/tests/QtCore/translations/trans_russian.qm b/sources/pyside6/tests/QtCore/translations/trans_russian.qm
new file mode 100644
index 000000000..5f16552a7
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/translations/trans_russian.qm
Binary files differ
diff --git a/sources/pyside6/tests/QtCore/translations/trans_russian.ts b/sources/pyside6/tests/QtCore/translations/trans_russian.ts
new file mode 100644
index 000000000..d1ba49bd2
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/translations/trans_russian.ts
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS><TS version="1.1" language="ru">
+<defaultcodec></defaultcodec>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Hello World!</source>
+ <translation>привет мир!</translation>
+ </message>
+</context>
+</TS>
diff --git a/sources/pyside6/tests/QtCore/unaryoperator_test.py b/sources/pyside6/tests/QtCore/unaryoperator_test.py
new file mode 100644
index 000000000..7b38685c8
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/unaryoperator_test.py
@@ -0,0 +1,53 @@
+#!/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
+
+'''Tests the presence of unary operator __neg__ on the QPoint class'''
+
+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 QPoint
+
+
+class NegUnaryOperatorTest(unittest.TestCase):
+ '''Tests the presence of unary operator __neg__ on the QPoint class'''
+
+ def setUp(self):
+ # Acquire resources
+ self.x, self.y = 10, 20
+ self.neg_x, self.neg_y = -self.x, -self.y
+ self.qpoint = QPoint(self.x, self.y)
+
+ def tearDown(self):
+ # Release resources
+ del self.qpoint
+ del self.x
+ del self.y
+ del self.neg_x
+ del self.neg_y
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testNegUnaryOperator(self):
+ # Test __neg__ unary operator on QPoint class
+ __neg__method_exists = True
+ try:
+ neg_qpoint = -self.qpoint
+ except:
+ __neg__method_exists = False
+
+ self.assertTrue(__neg__method_exists)
+ self.assertEqual(self.qpoint, -neg_qpoint)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/unicode_test.py b/sources/pyside6/tests/QtCore/unicode_test.py
new file mode 100644
index 000000000..73ce96c77
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/unicode_test.py
@@ -0,0 +1,44 @@
+#!/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
+
+'''Unit tests for QString conversion to/from Python Unicode'''
+
+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
+from PySide6.QtCore import QByteArray
+
+
+class UnicodeConversion(unittest.TestCase):
+ '''Test case for QString to/from Python Unicode conversion'''
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def testSetRegularStringRetrieveUnicode(self):
+ # Set regular Python string retrieve unicode
+ obj = QObject()
+ obj.setObjectName('test')
+ self.assertEqual(obj.objectName(), 'test')
+
+ def testSetUnicodeRetrieveUnicode(self):
+ # Set Python unicode string and retrieve unicode
+ obj = QObject()
+ obj.setObjectName('ümlaut')
+ self.assertEqual(obj.objectName(), 'ümlaut')
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtCore/versioninfo_test.py b/sources/pyside6/tests/QtCore/versioninfo_test.py
new file mode 100644
index 000000000..63414378a
--- /dev/null
+++ b/sources/pyside6/tests/QtCore/versioninfo_test.py
@@ -0,0 +1,32 @@
+# 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
+
+
+class TestVersionInfo(unittest.TestCase):
+ def testIt(self):
+
+ v = PySide6.__version_info__
+ self.assertEqual(type(v), tuple)
+ self.assertEqual(len(v), 5)
+ self.assertEqual(type(v[0]), int)
+ self.assertEqual(type(v[1]), int)
+ self.assertEqual(type(v[2]), int)
+ self.assertEqual(type(v[3]), str)
+ self.assertEqual(type(v[4]), str)
+
+ self.assertEqual(type(PySide6.__version__), str)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtDBus/CMakeLists.txt b/sources/pyside6/tests/QtDBus/CMakeLists.txt
new file mode 100644
index 000000000..bf2d2105a
--- /dev/null
+++ b/sources/pyside6/tests/QtDBus/CMakeLists.txt
@@ -0,0 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(ENABLE_UNIX)
+ PYSIDE_TEST(test_dbus.py)
+endif()
diff --git a/sources/pyside6/tests/QtDBus/QtDBus.pyproject b/sources/pyside6/tests/QtDBus/QtDBus.pyproject
new file mode 100644
index 000000000..76c3963e4
--- /dev/null
+++ b/sources/pyside6/tests/QtDBus/QtDBus.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["test_dbus.py"]
+}
diff --git a/sources/pyside6/tests/QtDBus/test_dbus.py b/sources/pyside6/tests/QtDBus/test_dbus.py
new file mode 100644
index 000000000..a37db9421
--- /dev/null
+++ b/sources/pyside6/tests/QtDBus/test_dbus.py
@@ -0,0 +1,44 @@
+# 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 cases for QDBus'''
+
+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
+
+import sys
+from PySide6.QtCore import QCoreApplication
+from PySide6.QtDBus import (QDBusConnection, QDBusConnectionInterface,
+ QDBusInterface, QDBusReply)
+
+
+def service_names():
+ session_bus = QDBusConnection.sessionBus()
+ if not QDBusConnection.sessionBus().isConnected():
+ print("Cannot connect to the D-Bus session bus.", file=sys.stderr)
+ return []
+ reply = session_bus.interface().registeredServiceNames()
+ if not reply.isValid():
+ print("Error:", reply.error().message(), file=sys.stderr)
+ return []
+ return reply.value()
+
+
+class TestDBus(UsesQApplication):
+ '''Simple Test case for QDBus'''
+
+ def test_service_names(self):
+ names = service_names()
+ print(names)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtDataVisualization/CMakeLists.txt b/sources/pyside6/tests/QtDataVisualization/CMakeLists.txt
new file mode 100644
index 000000000..61b347263
--- /dev/null
+++ b/sources/pyside6/tests/QtDataVisualization/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(datavisualization_test.py)
diff --git a/sources/pyside6/tests/QtDataVisualization/QtDataVisualization.pyproject b/sources/pyside6/tests/QtDataVisualization/QtDataVisualization.pyproject
new file mode 100644
index 000000000..23a8a141c
--- /dev/null
+++ b/sources/pyside6/tests/QtDataVisualization/QtDataVisualization.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["datavisualization_test.py"]
+}
diff --git a/sources/pyside6/tests/QtDataVisualization/datavisualization_test.py b/sources/pyside6/tests/QtDataVisualization/datavisualization_test.py
new file mode 100644
index 000000000..98ada6d47
--- /dev/null
+++ b/sources/pyside6/tests/QtDataVisualization/datavisualization_test.py
@@ -0,0 +1,104 @@
+#!/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
+
+'''Test cases for QtDataVisualization'''
+
+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 QTimer
+from PySide6.QtDataVisualization import (Q3DBars, QBar3DSeries, QBarDataItem,
+ QBarDataProxy, QCategory3DAxis,
+ QValue3DAxis, QValue3DAxisFormatter,
+ qDefaultSurfaceFormat)
+
+
+def dataToBarDataRow(data):
+ result = []
+ for d in data:
+ result.append(QBarDataItem(d))
+ return result
+
+
+def dataToBarDataArray(data):
+ result = []
+ for row in data:
+ result.append(dataToBarDataRow(row))
+ return result
+
+
+class QtDataVisualizationTestCase(UsesQApplication):
+ '''Tests related to QtDataVisualization'''
+
+ def testBars(self):
+ self.bars = Q3DBars()
+ self.columnAxis = QCategory3DAxis()
+ self.columnAxis.setTitle('Columns')
+ self.columnAxis.setTitleVisible(True)
+ self.columnAxis.setLabels(['Column1', 'Column2'])
+
+ self.rowAxis = QCategory3DAxis()
+ self.rowAxis.setTitle('Rows')
+ self.rowAxis.setTitleVisible(True)
+ self.rowAxis.setLabels(['Row1', 'Row2'])
+
+ self.valueAxis = QValue3DAxis()
+ self.valueAxis.setTitle('Values')
+ self.valueAxis.setTitleVisible(True)
+ self.valueAxis.setRange(0, 5)
+
+ self.bars.setRowAxis(self.rowAxis)
+ self.bars.setColumnAxis(self.columnAxis)
+ self.bars.setValueAxis(self.valueAxis)
+
+ self.series = QBar3DSeries()
+ self.arrayData = [[1, 2], [3, 4]]
+ self.series.dataProxy().addRows(dataToBarDataArray(self.arrayData))
+
+ self.bars.setPrimarySeries(self.series)
+
+ self.bars.show()
+ QTimer.singleShot(500, self.app.quit)
+ self.app.exec()
+
+ def testBarDataProxy(self):
+ '''PSYSIDE-1438, crashes in QBarDataProxy.addRow()'''
+ items = [QBarDataItem(v) for v in [1.0, 2.0]]
+ data_proxy = QBarDataProxy()
+ data_proxy.addRow(items)
+ data_proxy.addRow(items, 'bla')
+ data_proxy.insertRow(0, items)
+ data_proxy.insertRow(0, items, 'bla')
+ data_proxy.setRow(0, items)
+ data_proxy.setRow(0, items, 'bla')
+ self.assertTrue(data_proxy.rowCount(), 4)
+
+ def testDefaultSurfaceFormat(self):
+ format = qDefaultSurfaceFormat(True)
+ print(format)
+
+ def testQValue3DAxisFormatter(self):
+ """PYSIDE-2025: Test the added setters of QValue3DAxisFormatter."""
+ formatter = QValue3DAxisFormatter()
+ float_values = [float(10)]
+ formatter.setGridPositions(float_values)
+ self.assertEqual(formatter.gridPositions(), float_values)
+
+ formatter.setLabelPositions(float_values)
+ self.assertEqual(formatter.labelPositions(), float_values)
+
+ label_strings = ["bla"]
+ formatter.setLabelStrings(label_strings)
+ self.assertEqual(formatter.labelStrings(), label_strings)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtDesigner/CMakeLists.txt b/sources/pyside6/tests/QtDesigner/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtDesigner/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtGraphs/CMakeLists.txt b/sources/pyside6/tests/QtGraphs/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtGraphs/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtGui/CMakeLists.txt b/sources/pyside6/tests/QtGui/CMakeLists.txt
new file mode 100644
index 000000000..71a5c7eb9
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/CMakeLists.txt
@@ -0,0 +1,60 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#Keep this in alphabetical sort
+
+PYSIDE_TEST(bug_367.py)
+PYSIDE_TEST(bug_493.py)
+PYSIDE_TEST(bug_606.py)
+PYSIDE_TEST(bug_617.py)
+PYSIDE_TEST(bug_652.py)
+PYSIDE_TEST(bug_660.py)
+PYSIDE_TEST(bug_716.py)
+PYSIDE_TEST(bug_740.py)
+PYSIDE_TEST(bug_743.py)
+PYSIDE_TEST(bug_785.py)
+PYSIDE_TEST(bug_991.py)
+PYSIDE_TEST(bug_1091.py)
+PYSIDE_TEST(bug_PYSIDE-344.py)
+PYSIDE_TEST(deepcopy_test.py)
+PYSIDE_TEST(event_filter_test.py)
+PYSIDE_TEST(float_to_int_implicit_conversion_test.py)
+PYSIDE_TEST(pyside_reload_test.py)
+PYSIDE_TEST(qbrush_test.py)
+PYSIDE_TEST(qcolor_test.py)
+PYSIDE_TEST(qcolor_reduce_test.py)
+PYSIDE_TEST(qcursor_test.py)
+PYSIDE_TEST(qdatastream_gui_operators_test.py)
+PYSIDE_TEST(qdesktopservices_test.py)
+PYSIDE_TEST(qfont_test.py)
+PYSIDE_TEST(qfontmetrics_test.py)
+PYSIDE_TEST(qguiapplication_test.py)
+PYSIDE_TEST(qicon_test.py)
+PYSIDE_TEST(qimage_test.py)
+if(WIN32)
+ PYSIDE_TEST(qimage_win_test.py)
+endif()
+PYSIDE_TEST(qitemselection_test.py)
+PYSIDE_TEST(qpainter_test.py)
+PYSIDE_TEST(qpen_test.py)
+PYSIDE_TEST(qpdfwriter_test.py)
+PYSIDE_TEST(qpixelformat_test.py)
+PYSIDE_TEST(qpixmap_constructor.py)
+PYSIDE_TEST(qpixmap_test.py)
+PYSIDE_TEST(qpixmapcache_test.py)
+PYSIDE_TEST(qpolygonf_test.py)
+PYSIDE_TEST(qkeysequence_test.py)
+PYSIDE_TEST(qradialgradient_test.py)
+PYSIDE_TEST(qrasterwindow_test.py)
+PYSIDE_TEST(qregion_test.py)
+PYSIDE_TEST(qshortcut_test.py)
+PYSIDE_TEST(qstandarditemmodel_test.py)
+PYSIDE_TEST(qstring_qkeysequence_test.py)
+PYSIDE_TEST(qstylehints_test.py)
+PYSIDE_TEST(qtextdocument_functions.py)
+PYSIDE_TEST(qtextdocument_undoredo_test.py)
+PYSIDE_TEST(qtextdocumentwriter_test.py)
+PYSIDE_TEST(qtextline_test.py)
+PYSIDE_TEST(qtransform_test.py)
+PYSIDE_TEST(repr_test.py)
+PYSIDE_TEST(timed_app_and_patching_test.py)
diff --git a/sources/pyside6/tests/QtGui/QtGui.pyproject b/sources/pyside6/tests/QtGui/QtGui.pyproject
new file mode 100644
index 000000000..75b5e084f
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/QtGui.pyproject
@@ -0,0 +1,56 @@
+{
+ "files": ["bug_1091.py",
+ "bug_367.py",
+ "bug_493.py",
+ "bug_606.py",
+ "bug_617.py",
+ "bug_652.py",
+ "bug_660.py",
+ "bug_716.py",
+ "bug_740.py",
+ "bug_743.py",
+ "bug_785.py",
+ "bug_991.py",
+ "bug_PYSIDE-344.py",
+ "deepcopy_test.py",
+ "event_filter_test.py",
+ "float_to_int_implicit_conversion_test.py",
+ "pyside_reload_test.py",
+ "qbrush_test.py",
+ "qcolor_reduce_test.py",
+ "qcolor_test.py",
+ "qcursor_test.py",
+ "qdatastream_gui_operators_test.py",
+ "qdesktopservices_test.py",
+ "qfont_test.py",
+ "qfontmetrics_test.py",
+ "qguiapplication_test.py",
+ "qicon_test.py",
+ "qimage_test.py",
+ "qimage_win_test.py",
+ "qitemselection_test.py",
+ "qkeysequence_test.py",
+ "qpainter_test.py",
+ "qpdfwriter_test.py",
+ "qpen_test.py",
+ "qpixelformat_test.py",
+ "qpixmap_constructor.py",
+ "qpixmap_test.py",
+ "qpixmapcache_test.py",
+ "qpolygonf_test.py",
+ "qradialgradient_test.py",
+ "qrasterwindow_test.py",
+ "qregion_test.py",
+ "qshortcut_test.py",
+ "qstandarditemmodel_test.py",
+ "qstring_qkeysequence_test.py",
+ "qstylehints_test.py",
+ "qtextdocument_functions.py",
+ "qtextdocument_undoredo_test.py",
+ "qtextdocumentwriter_test.py",
+ "qtextline_test.py",
+ "qtransform_test.py",
+ "repr_test.py",
+ "timed_app_and_patching_test.py",
+ "xpm_data.py"]
+}
diff --git a/sources/pyside6/tests/QtGui/bug_1091.py b/sources/pyside6/tests/QtGui/bug_1091.py
new file mode 100644
index 000000000..9b9f35807
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_1091.py
@@ -0,0 +1,25 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+''' unit test for BUG #1091 '''
+
+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.QtGui import QPainter
+
+
+class QPainterTestCase(unittest.TestCase):
+ def testIt(self):
+ self.assertTrue("PixmapFragment" in dir(QPainter))
+ self.assertTrue("drawPixmapFragments" in dir(QPainter))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/bug_367.py b/sources/pyside6/tests/QtGui/bug_367.py
new file mode 100644
index 000000000..771fa5a4b
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_367.py
@@ -0,0 +1,35 @@
+# 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 bug 367: http://bugs.openbossa.org/show_bug.cgi?id=367'''
+
+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.QtGui import QStandardItem, QStandardItemModel
+
+
+class BugTest(UsesQApplication):
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testCase(self):
+ model = QStandardItemModel()
+ parentItem = model.invisibleRootItem()
+ for i in range(10):
+ item = QStandardItem()
+ rcount = sys.getrefcount(item)
+ parentItem.appendRow(item)
+ self.assertEqual(rcount + 1, sys.getrefcount(item))
+ parentItem = item
+
+ self.assertTrue(True)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/bug_493.py b/sources/pyside6/tests/QtGui/bug_493.py
new file mode 100644
index 000000000..ba8b67bbb
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_493.py
@@ -0,0 +1,32 @@
+# 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 Qt, QEvent
+from PySide6.QtGui import QGuiApplication, QKeyEvent, QKeySequence
+
+
+class TestBug493(unittest.TestCase):
+
+ def testIt(self):
+ # We need a qapp otherwise Qt will crash when trying to detect the
+ # current platform
+ app = QGuiApplication([])
+ ev1 = QKeyEvent(QEvent.KeyRelease, Qt.Key_Delete, Qt.NoModifier)
+ ev2 = QKeyEvent(QEvent.KeyRelease, Qt.Key_Copy, Qt.NoModifier)
+ ks = QKeySequence.Delete
+
+ self.assertTrue(ev1.matches(ks))
+ self.assertFalse(ev2.matches(ks))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/bug_606.py b/sources/pyside6/tests/QtGui/bug_606.py
new file mode 100644
index 000000000..80b79f640
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_606.py
@@ -0,0 +1,45 @@
+# 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.QtGui import QVector2D, QVector3D, QVector4D, qFuzzyCompare
+from PySide6.QtGui import QColor
+
+
+class testCases(unittest.TestCase):
+ def testQVector2DToTuple(self):
+ vec = QVector2D(1, 2)
+ self.assertEqual((1, 2), vec.toTuple())
+ self.assertTrue(qFuzzyCompare(vec, vec))
+ vec2 = QVector2D(1, 3)
+ self.assertFalse(qFuzzyCompare(vec, vec2))
+
+ def testQVector3DToTuple(self):
+ vec = QVector3D(1, 2, 3)
+ self.assertEqual((1, 2, 3), vec.toTuple())
+ vec2 = QVector3D(1, 3, 4)
+ self.assertFalse(qFuzzyCompare(vec, vec2))
+
+ def testQVector4DToTuple(self):
+ vec = QVector4D(1, 2, 3, 4)
+ self.assertEqual((1, 2, 3, 4), vec.toTuple())
+ self.assertTrue(qFuzzyCompare(vec, vec))
+ vec2 = QVector4D(1, 3, 4, 5)
+ self.assertFalse(qFuzzyCompare(vec, vec2))
+
+ def testQColorToTuple(self):
+ c = QColor(0, 0, 255)
+ c.setRgb(1, 2, 3)
+ self.assertEqual((1, 2, 3, 255), c.toTuple())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/bug_617.py b/sources/pyside6/tests/QtGui/bug_617.py
new file mode 100644
index 000000000..d90d1e754
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_617.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(False)
+
+from PySide6.QtCore import QEvent
+from PySide6.QtGui import QColor
+
+
+class MyEvent(QEvent):
+ def __init__(self):
+ QEvent.__init__(self, QEvent.Type(999))
+
+
+class Bug617(unittest.TestCase):
+ def testRepr(self):
+ c = QColor.fromRgb(1, 2, 3, 4)
+ s = c.spec()
+ self.assertEqual(repr(s), repr(QColor.Rgb))
+
+ def testOutOfBounds(self):
+ e = MyEvent()
+ self.assertEqual(repr(e.type()), "<Type.999: 999>")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/bug_652.py b/sources/pyside6/tests/QtGui/bug_652.py
new file mode 100644
index 000000000..17d6c3b77
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_652.py
@@ -0,0 +1,47 @@
+# 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.QtGui import QTextBlockUserData, QTextCursor, QTextDocument
+
+
+class MyData(QTextBlockUserData):
+ def __init__(self, data):
+ super().__init__()
+ self.data = data
+
+ def getMyNiceData(self):
+ return self.data
+
+
+class TestBug652(unittest.TestCase):
+ """Segfault when using QTextBlock::setUserData due to missing ownership transfer"""
+ def testIt(self):
+ td = QTextDocument()
+ tc = QTextCursor(td)
+ tc.insertText("Hello world")
+ heyHo = "hey ho!"
+ tc.block().setUserData(MyData(heyHo))
+ self.assertEqual(type(tc.block().userData()), MyData)
+ self.assertEqual(tc.block().userData().getMyNiceData(), heyHo)
+
+ del tc
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ tc = QTextCursor(td)
+ blk = tc.block()
+ self.assertEqual(type(blk.userData()), MyData)
+ self.assertEqual(blk.userData().getMyNiceData(), heyHo)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/bug_660.py b/sources/pyside6/tests/QtGui/bug_660.py
new file mode 100644
index 000000000..4ab8e9f19
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_660.py
@@ -0,0 +1,40 @@
+# 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.QtGui import QStandardItemModel, QStandardItem
+
+
+class MyItemModel(QStandardItemModel):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.appendRow([QStandardItem('Item 1'),])
+
+ def mimeTypes(self):
+ mtypes = super(MyItemModel, self).mimeTypes()
+ mtypes.append('application/my-form')
+ return mtypes
+
+ def mimeData(self, indexes):
+ self.__mimedata = super(MyItemModel, self).mimeData(indexes)
+ self.__mimedata.setData('application/my-form', bytes('hi', "UTF-8"))
+ return self.__mimedata
+
+
+class TestBug660(unittest.TestCase):
+ '''QMimeData type deleted prematurely when overriding mime-type in QStandardItemModel drag and drop'''
+ def testIt(self):
+ model = MyItemModel()
+ model.mimeData([model.index(0, 0)]) # if it doesn't raise an exception it's all right!
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/bug_716.py b/sources/pyside6/tests/QtGui/bug_716.py
new file mode 100644
index 000000000..90d78ea89
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_716.py
@@ -0,0 +1,20 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import Qt, QPersistentModelIndex, QStringListModel
+
+if __name__ == '__main__':
+ stringListModel = QStringListModel(['one', 'two'])
+ idx = stringListModel.index(1, 0)
+ persistentModelIndex = QPersistentModelIndex(idx)
+ stringListModel.data(persistentModelIndex, Qt.DisplayRole)
+
diff --git a/sources/pyside6/tests/QtGui/bug_740.py b/sources/pyside6/tests/QtGui/bug_740.py
new file mode 100644
index 000000000..ece314cc8
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_740.py
@@ -0,0 +1,25 @@
+# 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 QSize
+from PySide6.QtGui import QBitmap, QImage
+
+
+class TestQBitmap(UsesQApplication):
+ def testFromDataMethod(self):
+ dataBits = bytes('\x38\x28\x38\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\xfe\xfe\x7c\x7c\x38\x38\x10\x10', "UTF-8")
+ bim = QBitmap.fromData(QSize(8, 48), dataBits, QImage.Format_Mono) # missing function
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/bug_743.py b/sources/pyside6/tests/QtGui/bug_743.py
new file mode 100644
index 000000000..a870e4bf1
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_743.py
@@ -0,0 +1,27 @@
+# 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.QtGui import QMatrix4x4
+
+
+class TestQMatrix(unittest.TestCase):
+ def testOperator(self):
+ m = QMatrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
+ v = 1
+ for x in range(4):
+ for y in range(4):
+ self.assertEqual(m[x, y], v)
+ v += 1
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/bug_785.py b/sources/pyside6/tests/QtGui/bug_785.py
new file mode 100644
index 000000000..04425f063
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_785.py
@@ -0,0 +1,41 @@
+# 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 QItemSelection
+from PySide6.QtGui import QStandardItemModel, QStandardItem
+
+
+class Bug324(unittest.TestCase):
+ def testOperators(self):
+ model = QStandardItemModel()
+ for i in range(100):
+ model.appendRow(QStandardItem(f"Item: {i}"))
+
+ first = model.index(0, 0)
+ second = model.index(10, 0)
+ third = model.index(20, 0)
+ fourth = model.index(30, 0)
+
+ sel = QItemSelection(first, second)
+ sel2 = QItemSelection()
+ sel2.select(third, fourth)
+
+ sel3 = sel + sel2 # check operator +
+ self.assertEqual(len(sel3), 2)
+ sel4 = sel
+ sel4 += sel2 # check operator +=
+ self.assertEqual(len(sel4), 2)
+ self.assertEqual(sel4, sel3)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/bug_991.py b/sources/pyside6/tests/QtGui/bug_991.py
new file mode 100644
index 000000000..e74adc198
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_991.py
@@ -0,0 +1,28 @@
+# 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
+from PySide6.QtGui import QPen, QBrush
+
+
+class TestBug991 (unittest.TestCase):
+ def testReprFunction(self):
+ reprPen = repr(QPen())
+ self.assertTrue(reprPen.startswith("<PySide6.QtGui.QPen"))
+ reprBrush = repr(QBrush())
+ self.assertTrue(reprBrush.startswith("<PySide6.QtGui.QBrush"))
+ reprObject = repr(QObject())
+ self.assertTrue(reprObject.startswith("<PySide6.QtCore.QObject"))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/bug_PYSIDE-344.py b/sources/pyside6/tests/QtGui/bug_PYSIDE-344.py
new file mode 100644
index 000000000..6519eef61
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/bug_PYSIDE-344.py
@@ -0,0 +1,49 @@
+#!/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
+
+'''Test cases for PYSIDE-344, imul/idiv are used instead of mul/div, modifying the argument passed in'''
+
+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 QMargins, QPoint, QPointF, QSize, QSizeF
+from PySide6.QtGui import (QMatrix4x4, QQuaternion, QTransform, QVector2D,
+ QVector3D, QVector4D)
+
+
+def testList():
+ return [QPoint(10, 10), QPointF(1, 1), QSize(10, 10), QSizeF(1, 1),
+ QMargins(10, 10, 10, 10),
+ QTransform(), QMatrix4x4(),
+ QVector2D(1, 1), QVector3D(1, 1, 1), QVector4D(1, 1, 1, 1),
+ QQuaternion(1, 1, 1, 1)]
+
+
+class TestMulDiv(unittest.TestCase):
+
+ def testMultiplication(self):
+ fails = ''
+ for a in testList():
+ mul = (a * 2)
+ if a == mul:
+ fails += ' ' + type(a).__name__
+ self.assertEqual(fails, '')
+
+ def testDivision(self):
+ fails = ''
+ for a in testList():
+ div = (a * 2)
+ if a == div:
+ fails += ' ' + type(a).__name__
+ self.assertEqual(fails, '')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/deepcopy_test.py b/sources/pyside6/tests/QtGui/deepcopy_test.py
new file mode 100644
index 000000000..9a13eb485
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/deepcopy_test.py
@@ -0,0 +1,140 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+from copy import deepcopy
+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 QPoint
+from PySide6.QtGui import QMatrix2x2, QMatrix2x3, QMatrix2x4
+from PySide6.QtGui import QMatrix3x2, QMatrix3x3, QMatrix3x4
+from PySide6.QtGui import QMatrix4x2, QMatrix4x3, QMatrix4x4
+from PySide6.QtGui import QVector2D, QVector3D, QVector4D
+from PySide6.QtGui import QColor, QTransform, QKeySequence, QQuaternion
+from PySide6.QtGui import QPolygon
+
+
+class DeepCopyHelper:
+ def testCopy(self):
+ copy = deepcopy([self.original])[0]
+ self.assertTrue(copy is not self.original)
+ self.assertEqual(copy, self.original)
+
+
+class DeepCopyColorHelperF:
+ def testCopy(self):
+ copy = deepcopy([self.original])[0]
+ self.assertTrue(copy is not self.original)
+ self.assertEqual(copy.spec(), self.original.spec())
+ # impossible to compare float point
+ # self.assertEqual(copy, self.original)
+
+
+class QColorDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QColor("red")
+
+
+class QColorRGBDeepCopy(DeepCopyColorHelperF, unittest.TestCase):
+ def setUp(self):
+ self.original = QColor.fromRgbF(0.2, 0.3, 0.4, 0.5)
+
+
+class QColorHSLDeepCopy(DeepCopyColorHelperF, unittest.TestCase):
+ def setUp(self):
+ self.original = QColor.fromHslF(0.2, 0.3, 0.4, 0.5)
+
+
+class QColorHSVDeepCopy(DeepCopyColorHelperF, unittest.TestCase):
+ def setUp(self):
+ self.original = QColor.fromHsvF(0.2, 0.3, 0.4, 0.5)
+
+
+class QColorCMYKDeepCopy(DeepCopyColorHelperF, unittest.TestCase):
+ def setUp(self):
+ self.original = QColor.fromCmykF(0.2, 0.3, 0.4, 0.5, 0.6)
+
+
+class QTransformDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QTransform(1, 2, 3, 4, 5, 6, 7, 8, 9)
+
+
+class QKeySequenceDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QKeySequence("Ctrl+P")
+
+
+class QQuaternionDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QQuaternion(1, 2, 3, 4)
+
+
+class QVector2DDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QVector2D(1, 2)
+
+
+class QVector3DDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QVector3D(1, 2, 3)
+
+
+class QVector4DDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QVector4D(1, 2, 3, 4)
+
+
+class QPolygonDeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QPolygon([QPoint(1, 2), QPoint(3, 4), QPoint(5, 6)])
+
+
+# Avoid these tests until get gcc fixed
+# Related bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43247
+"""
+class QMatrix2x2DeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix2x2([1, 2, 3, 4])
+
+class QMatrix2x3DeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix2x3([1, 2, 3, 4, 5, 6])
+
+class QMatrix2x4DeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix2x4([1, 2, 3, 4, 5, 6, 7, 8])
+
+class QMatrix3x2DeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix3x2([1, 2, 3, 4, 5, 6])
+
+class QMatrix3x3DeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix3x3([1, 2, 3, 4, 5, 6, 7, 8, 9])
+
+class QMatrix3x4DeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix3x4([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
+
+class QMatrix4x2DeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix4x2([1, 2, 3, 4, 5, 6, 7, 8])
+
+class QMatrix4x3DeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix4x3([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
+
+class QMatrix4x4DeepCopy(DeepCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix4x4([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
+"""
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/event_filter_test.py b/sources/pyside6/tests/QtGui/event_filter_test.py
new file mode 100644
index 000000000..01d8fbc02
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/event_filter_test.py
@@ -0,0 +1,51 @@
+# 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 QObject, QEvent
+from PySide6.QtGui import QWindow
+
+
+class MyFilter(QObject):
+ def eventFilter(self, obj, event):
+ if event.type() == QEvent.KeyPress:
+ pass
+ return QObject.eventFilter(self, obj, event)
+
+
+class EventFilter(UsesQApplication):
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefCount(self):
+ o = QObject()
+ filt = MyFilter()
+ o.installEventFilter(filt)
+ self.assertEqual(sys.getrefcount(o), 2)
+
+ o.installEventFilter(filt)
+ self.assertEqual(sys.getrefcount(o), 2)
+
+ o.removeEventFilter(filt)
+ self.assertEqual(sys.getrefcount(o), 2)
+
+ def testObjectDestructorOrder(self):
+ w = QWindow()
+ filt = MyFilter()
+ filt.app = self.app
+ w.installEventFilter(filt)
+ w.show()
+ w.close()
+ w = None
+ self.assertTrue(True)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/float_to_int_implicit_conversion_test.py b/sources/pyside6/tests/QtGui/float_to_int_implicit_conversion_test.py
new file mode 100644
index 000000000..ba438f8e0
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/float_to_int_implicit_conversion_test.py
@@ -0,0 +1,45 @@
+# 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 cases for QImage'''
+
+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.QtGui import QImage, qRgb
+
+from helper.usesqapplication import UsesQApplication
+
+
+class SetPixelFloat(UsesQApplication):
+ '''Test case for calling setPixel with float as argument'''
+
+ def setUp(self):
+ # Acquire resources
+ super(SetPixelFloat, self).setUp()
+ self.color = qRgb(255, 0, 0)
+ self.image = QImage(200, 200, QImage.Format_RGB32)
+
+ def tearDown(self):
+ # Release resources
+ del self.color
+ del self.image
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(SetPixelFloat, self).tearDown()
+
+ def testFloat(self):
+ # QImage.setPixel(float, float, color) - Implicit conversion
+ self.image.setPixel(3.14, 4.2, self.color)
+ self.assertEqual(self.image.pixel(3.14, 4.2), self.color)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/pyside_reload_test.py b/sources/pyside6/tests/QtGui/pyside_reload_test.py
new file mode 100644
index 000000000..1ac65f709
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/pyside_reload_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 importlib
+import importlib.util
+import os
+import shutil
+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)
+
+
+orig_path = os.path.join(os.path.dirname(__file__))
+workdir = os.getcwd()
+src = os.path.normpath(os.path.join(orig_path, '..', 'QtWidgets', 'test_module_template.py'))
+dst = os.path.join(workdir, 'test_module.py')
+shutil.copyfile(src, dst)
+sys.path.append(workdir)
+
+
+def reload_module(moduleName):
+ importlib.reload(moduleName)
+
+
+def increment_module_value():
+ modfile = open(dst, 'a')
+ modfile.write('Sentinel.value += 1' + os.linesep)
+ modfile.flush()
+ modfile.close()
+ if not sys.dont_write_bytecode:
+ import importlib.util
+ cacheFile = importlib.util.cache_from_source(dst)
+ os.remove(cacheFile)
+
+
+class TestModuleReloading(unittest.TestCase):
+
+ def testModuleReloading(self):
+ '''Test module reloading with on-the-fly modifications.'''
+
+ import test_module
+ self.assertEqual(test_module.Sentinel.value, 10)
+
+ increment_module_value()
+ reload_module(sys.modules['test_module'])
+ self.assertEqual(test_module.Sentinel.value, 11)
+
+ reload_module(sys.modules['test_module'])
+ self.assertEqual(test_module.Sentinel.value, 11)
+
+ increment_module_value()
+ reload_module(sys.modules['test_module'])
+ self.assertEqual(test_module.Sentinel.value, 12)
+
+
+if __name__ == "__main__":
+ unittest.main()
+
+
diff --git a/sources/pyside6/tests/QtGui/qbrush_test.py b/sources/pyside6/tests/QtGui/qbrush_test.py
new file mode 100644
index 000000000..69262328b
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qbrush_test.py
@@ -0,0 +1,43 @@
+# 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 cases for QBrush'''
+
+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 Qt
+from PySide6.QtGui import QColor, QBrush, QConicalGradient
+
+from helper.usesqapplication import UsesQApplication
+
+
+class Constructor(UsesQApplication):
+ '''Test case for constructor of QBrush'''
+
+ def testQColor(self):
+ # QBrush(QColor) constructor
+ color = QColor('black')
+ obj = QBrush(color)
+ self.assertEqual(obj.color(), color)
+
+ obj = QBrush(Qt.blue)
+ self.assertEqual(obj.color(), Qt.blue)
+
+ def testGradient(self):
+ """Test type discovery on class hierarchies with non-virtual
+ destructors by specifying a polymorphic-id-expression without
+ polymorphic-name-function."""
+ gradient = QConicalGradient()
+ brush = QBrush(gradient)
+ self.assertEqual(type(brush.gradient()), type(gradient))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qcolor_reduce_test.py b/sources/pyside6/tests/QtGui/qcolor_reduce_test.py
new file mode 100644
index 000000000..609951be6
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qcolor_reduce_test.py
@@ -0,0 +1,44 @@
+# 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 pickle
+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.QtGui import QColor
+
+
+class TestQColor (unittest.TestCase):
+ def reduceColor(self, c):
+ p = pickle.dumps(c)
+ c2 = pickle.loads(p)
+ self.assertEqual(c.spec(), c2.spec())
+ self.assertEqual(c, c2)
+
+ def testReduceEmpty(self):
+ self.reduceColor(QColor())
+
+ def testReduceString(self):
+ self.reduceColor(QColor('gray'))
+
+ def testReduceRGB(self):
+ self.reduceColor(QColor.fromRgbF(0.1, 0.2, 0.3, 0.4))
+
+ def testReduceCMYK(self):
+ self.reduceColor(QColor.fromCmykF(0.1, 0.2, 0.3, 0.4, 0.5))
+
+ def testReduceHsl(self):
+ self.reduceColor(QColor.fromHslF(0.1, 0.2, 0.3, 0.4))
+
+ def testReduceHsv(self):
+ self.reduceColor(QColor.fromHsvF(0.1, 0.2, 0.3, 0.4))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qcolor_test.py b/sources/pyside6/tests/QtGui/qcolor_test.py
new file mode 100644
index 000000000..bbd558f10
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qcolor_test.py
@@ -0,0 +1,111 @@
+# 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 colorsys
+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)
+
+import PySide6
+from PySide6.QtCore import Qt
+from PySide6.QtGui import QColor, QColorConstants
+
+
+class QColorGetTest(unittest.TestCase):
+
+ def setUp(self):
+ self.color = QColor(20, 40, 60, 80)
+
+ def testGetRgb(self):
+ self.assertEqual(self.color.getRgb(), (20, 40, 60, 80))
+
+ def testGetHslF(self):
+ hls = colorsys.rgb_to_hls(20.0 / 255, 40.0 / 255, 60.0 / 255)
+ hsla = hls[0], hls[2], hls[1], self.color.alphaF()
+ for x, y in zip(self.color.getHslF(), hsla): # Due to rounding problems
+ self.assertTrue(x - y < 1 / 100000.0)
+
+ def testGetHsv(self):
+ hsv = colorsys.rgb_to_hsv(20.0 / 255, 40.0 / 255, 60.0 / 255)
+ hsva = int(hsv[0] * 360.0), int(hsv[1] * 255), int(hsv[2] * 256), self.color.alpha()
+ self.assertEqual(self.color.getHsv(), hsva)
+
+ def testGetCmyk(self): # not supported by colorsys
+ self.assertEqual(self.color.getCmyk(), (170, 85, 0, 195, 80))
+
+ def testGetCmykF(self): # not supported by colorsys
+ for x, y in zip(self.color.getCmykF(), (170 / 255.0, 85 / 255.0, 0, 195 / 255.0, 80 / 255.0)):
+ self.assertTrue(x - y < 1 / 10000.0)
+
+
+class QColorQRgbConstructor(unittest.TestCase):
+ '''QColor(QRgb) constructor'''
+ # Affected by bug #170 - QColor(QVariant) coming before QColor(uint)
+ # in overload sorting
+
+ def testBasic(self):
+ '''QColor(QRgb)'''
+ color = QColor(255, 0, 0)
+ # QRgb format #AARRGGBB
+ rgb = 0x00FF0000
+ self.assertEqual(QColor(rgb), color)
+
+
+class QColorEqualGlobalColor(unittest.TestCase):
+
+ def testEqualGlobalColor(self):
+ '''QColor == Qt::GlobalColor'''
+ self.assertEqual(QColor(255, 0, 0), Qt.red)
+
+
+class QColorCopy(unittest.TestCase):
+
+ def testDeepCopy(self):
+ '''QColor deepcopy'''
+
+ from copy import deepcopy
+
+ original = QColor(0, 0, 255)
+ copy = deepcopy([original])[0]
+
+ self.assertTrue(original is not copy)
+ self.assertEqual(original, copy)
+ del original
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertEqual(copy, QColor(0, 0, 255))
+
+ def testEmptyCopy(self):
+ from copy import deepcopy
+
+ original = QColor()
+ copy = deepcopy([original])[0]
+ self.assertTrue(original is not copy)
+ self.assertEqual(original, copy)
+ del original
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertEqual(copy, QColor())
+
+
+class QColorRepr(unittest.TestCase):
+ def testReprFunction(self):
+ # QColorConstants are disabled for MSVC/5.15, fixme: Check Qt 6
+ c = QColorConstants.Yellow if sys.platform != 'win32' else QColor(100, 120, 200)
+ c2 = eval(c.__repr__())
+ self.assertEqual(c, c2)
+
+ def testStrFunction(self):
+ c = QColor('red')
+ c2 = eval(c.__str__())
+ self.assertEqual(c, c2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qcursor_test.py b/sources/pyside6/tests/QtGui/qcursor_test.py
new file mode 100644
index 000000000..1494fe370
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qcursor_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
+
+'''Test for Bug 630 - Fails to resolve overload for QCursor(QBitmap, QBitmap, int, int)
+http://bugs.openbossa.org/show_bug.cgi?id=630
+'''
+
+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.QtGui import QBitmap, QCursor, QPixmap
+from helper.usesqapplication import UsesQApplication
+
+
+class TestQCursor(UsesQApplication):
+ def testQCursorConstructor(self):
+ bmp = QBitmap(16, 16)
+ cursor = QCursor(bmp, bmp, 16, 16)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtGui/qdatastream_gui_operators_test.py b/sources/pyside6/tests/QtGui/qdatastream_gui_operators_test.py
new file mode 100644
index 000000000..f2c86abf7
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qdatastream_gui_operators_test.py
@@ -0,0 +1,45 @@
+# 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 QDataStream, QByteArray, QIODevice, Qt
+from PySide6.QtGui import QPixmap, QColor
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QPixmapQDatastream(UsesQApplication):
+ '''QDataStream <<>> QPixmap'''
+
+ def setUp(self):
+ super(QPixmapQDatastream, self).setUp()
+ self.source_pixmap = QPixmap(100, 100)
+ # PYSIDE-1533: Use Qt.transparent to force Format_ARGB32_Premultiplied
+ # when converting to QImage in any case.
+ self.source_pixmap.fill(Qt.transparent)
+ self.output_pixmap = QPixmap()
+ self.buffer = QByteArray()
+ self.read_stream = QDataStream(self.buffer, QIODevice.ReadOnly)
+ self.write_stream = QDataStream(self.buffer, QIODevice.WriteOnly)
+
+ def testStream(self):
+ self.write_stream << self.source_pixmap
+
+ self.read_stream >> self.output_pixmap
+
+ image = self.output_pixmap.toImage()
+ pixel = image.pixel(10, 10)
+ self.assertEqual(pixel, QColor(Qt.transparent).rgba())
+ self.assertEqual(self.source_pixmap.toImage(), image)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qdesktopservices_test.py b/sources/pyside6/tests/QtGui/qdesktopservices_test.py
new file mode 100644
index 000000000..8d578152d
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qdesktopservices_test.py
@@ -0,0 +1,27 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Unit tests for QDesktopServices'''
+
+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.QtGui import QDesktopServices
+from PySide6.QtCore import QUrl
+
+
+class QDesktopServicesTest(unittest.TestCase):
+ def testOpenUrl(self):
+ # At the bare minimum check that they return false for invalid url's
+ url = QUrl()
+ self.assertEqual(QDesktopServices.openUrl(url), False)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qfont_test.py b/sources/pyside6/tests/QtGui/qfont_test.py
new file mode 100644
index 000000000..f81d47ec6
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qfont_test.py
@@ -0,0 +1,35 @@
+# 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.QtGui import QFont
+from helper.usesqapplication import UsesQApplication
+
+
+class QFontTest(UsesQApplication):
+
+ def testStringConstruction(self):
+ """PYSIDE-1685: Test that passing str to QFont works after addding
+ QFont(QStringList) by qtbase/d8602ce58b6ef268be84b9aa0166b0c3fa6a96e8"""
+ font_name = 'Times Roman'
+ font = QFont(font_name)
+ families = font.families()
+ self.assertEqual(len(families), 1)
+ self.assertEqual(families[0], font_name)
+
+ font = QFont([font_name])
+ families = font.families()
+ self.assertEqual(len(families), 1)
+ self.assertEqual(families[0], font_name)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qfontmetrics_test.py b/sources/pyside6/tests/QtGui/qfontmetrics_test.py
new file mode 100644
index 000000000..98c4c8f96
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qfontmetrics_test.py
@@ -0,0 +1,215 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Tests for inject codes and modifications on QFontMetrics
+ and QFontMetricsF'''
+
+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.QtGui import QFont, QFontMetrics, QFontMetricsF
+from PySide6.QtCore import QRect, QRectF, Qt, QSize, QSizeF
+from helper.usesqapplication import UsesQApplication
+
+
+class QFontMetricsTest(UsesQApplication):
+ '''Base class for QFontMetrics tests'''
+
+ def setUp(self):
+ super(QFontMetricsTest, self).setUp()
+ self.font = QFont()
+ self.metrics = QFontMetrics(self.font)
+
+ def tearDown(self):
+ del self.metrics
+ del self.font
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(QFontMetricsTest, self).tearDown()
+
+
+class BoundingRectTest(QFontMetricsTest):
+ '''Tests for QFontMetrics.boundingRect inject code'''
+
+ def testIntDefault(self):
+ '''QFontMetrics.boundingRect(int, int, int, int, ...) - default args'''
+ rect = self.metrics.boundingRect(0, 0, 0, 0,
+ Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT')
+ self.assertTrue(isinstance(rect, QRect))
+
+ def testIntWithArg(self):
+ '''QFontMetrics.boundingRect(int, int, int, int, ...) - single arg'''
+ rect = self.metrics.boundingRect(0, 0, 0, 0,
+ Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT', 2)
+ self.assertTrue(isinstance(rect, QRect))
+
+ def testIntWithFull(self):
+ '''QFontMetrics.boundingRect(int, int, int, int, ...) - all argss'''
+ rect = self.metrics.boundingRect(0, 0, 0, 0,
+ Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT', 20, [1, 2, 3, 4, 5])
+ self.assertTrue(isinstance(rect, QRect))
+
+ def testIntTypeError(self):
+ '''QFontMetrics.boundingRect(int, int, int, int, ...) - type error'''
+ self.assertRaises(TypeError, self.metrics.boundingRect, 0, 0, 0, 0,
+ Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT', 20, ['aaaa', 'ase'])
+
+ def testQRectDefault(self):
+ '''QFontMetrics.boundingRect(QRect, ...) - default args'''
+ arg = QRect(0, 0, 100, 200)
+ rect = self.metrics.boundingRect(arg, Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT')
+ self.assertTrue(isinstance(rect, QRect))
+
+ def testQRectWithArg(self):
+ '''QFontMetrics.boundingRect(QRect, ...) - only tabstops'''
+ arg = QRect(0, 0, 100, 200)
+ rect = self.metrics.boundingRect(arg, Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT', 2)
+ self.assertTrue(isinstance(rect, QRect))
+
+ def testQRectWithFull(self):
+ '''QFontMetrics.boundingRect(QRect, ...) - all arguments'''
+ arg = QRect(0, 0, 100, 200)
+ rect = self.metrics.boundingRect(arg, Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT', 20,
+ [1, 2, 3, 4, 5])
+ self.assertTrue(isinstance(rect, QRect))
+
+ def testQRectTypeError(self):
+ '''QFontMetrics.boundingRect(QRect, ...) - type error'''
+ arg = QRect(0, 0, 100, 200)
+ self.assertRaises(TypeError, self.metrics.boundingRect, arg,
+ Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT', 20, ['aaaa', 'ase'])
+
+
+class SizeTest(QFontMetricsTest):
+ '''Tests for QFontMetrics.size inject code'''
+
+ def testDefault(self):
+ '''QFontMetrics.size - default arguments'''
+ size = self.metrics.size(Qt.TextExpandTabs | Qt.TextSingleLine,
+ 'PySide by INdT')
+ self.assertTrue(isinstance(size, QSize))
+
+ def testWithTabStops(self):
+ '''QFontMetrics.size - only tabstops'''
+ size = self.metrics.size(Qt.TextExpandTabs | Qt.TextSingleLine,
+ 'PySide by INdT', 2)
+ self.assertTrue(isinstance(size, QSize))
+
+ def testFull(self):
+ '''QFontMetrics.size - all arguments'''
+ size = self.metrics.size(Qt.TextExpandTabs | Qt.TextSingleLine,
+ 'PySide by INdT', 2, [1, 2, 3, 4])
+ self.assertTrue(isinstance(size, QSize))
+
+ def testTypeError(self):
+ '''QFontMetrics.size - type error'''
+ self.assertRaises(TypeError, self.metrics.size,
+ Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT', 20, ['aaaa', 'ase'])
+
+
+class QFontMetricsFTest(UsesQApplication):
+ '''Base class for QFontMetrics tests'''
+
+ def setUp(self):
+ super(QFontMetricsFTest, self).setUp()
+ self.font = QFont()
+ self.metrics = QFontMetricsF(self.font)
+
+ def tearDown(self):
+ del self.metrics
+ del self.font
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(QFontMetricsFTest, self).tearDown()
+
+
+class FBoundingRectTest(QFontMetricsFTest):
+ '''Tests for QFontMetricsF.boundingRect inject code'''
+
+ def testQRectDefault(self):
+ '''QFontMetricsF.boundingRect(QRectF, ...) - default args'''
+ arg = QRectF(0, 0, 100, 200)
+ rect = self.metrics.boundingRect(arg, Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT')
+ self.assertTrue(isinstance(rect, QRectF))
+
+ def testQRectWithArg(self):
+ '''QFontMetricsF.boundingRect(QRectF, ...) - only tabstops'''
+ arg = QRectF(0, 0, 100, 200)
+ rect = self.metrics.boundingRect(arg, Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT', 2)
+ self.assertTrue(isinstance(rect, QRectF))
+
+ def testQRectWithFull(self):
+ '''QFontMetricsF.boundingRect(QRectF, ...) - all arguments'''
+ arg = QRectF(0, 0, 100, 200)
+ rect = self.metrics.boundingRect(arg, Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT', 20,
+ [1, 2, 3, 4, 5])
+ self.assertTrue(isinstance(rect, QRectF))
+
+ def testQRectTypeError(self):
+ '''QFontMetricsF.boundingRect(QRectF, ...) - type error'''
+ arg = QRectF(0, 0, 100, 200)
+ self.assertRaises(TypeError, self.metrics.boundingRect, arg,
+ Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT', 20, ['aaaa', 'ase'])
+
+
+class FSizeTest(QFontMetricsFTest):
+ '''Tests for QFontMetricsF.size inject code'''
+
+ def testDefault(self):
+ '''QFontMetricsF.size - default arguments'''
+ size = self.metrics.size(Qt.TextExpandTabs | Qt.TextSingleLine,
+ 'PySide by INdT')
+ self.assertTrue(isinstance(size, QSizeF))
+
+ def testWithTabStops(self):
+ '''QFontMetricsF.size - only tabstops'''
+ size = self.metrics.size(Qt.TextExpandTabs | Qt.TextSingleLine,
+ 'PySide by INdT', 2)
+ self.assertTrue(isinstance(size, QSizeF))
+
+ def testFull(self):
+ '''QFontMetricsF.size - all arguments'''
+ size = self.metrics.size(Qt.TextExpandTabs | Qt.TextSingleLine,
+ 'PySide by INdT', 2, [1, 2, 3, 4])
+ self.assertTrue(isinstance(size, QSizeF))
+
+ def testTypeError(self):
+ '''QFontMetricsF.size - type error'''
+ self.assertRaises(TypeError, self.metrics.size,
+ Qt.TextExpandTabs | Qt.AlignLeft,
+ 'PySide by INdT', 20, ['aaaa', 'ase'])
+
+
+class QCharTest(QFontMetricsFTest):
+
+ def testBoundingRect(self):
+ retCh = self.metrics.boundingRectChar('a')
+ self.assertEqual(type(retCh), QRectF)
+
+ def testWith(self):
+ retCh = self.metrics.horizontalAdvance('a')
+ self.assertTrue(retCh > 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qguiapplication_test.py b/sources/pyside6/tests/QtGui/qguiapplication_test.py
new file mode 100644
index 000000000..a3d0942aa
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qguiapplication_test.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)
+
+from PySide6.QtGui import QGuiApplication
+
+
+class TestQGuiApplication(unittest.TestCase):
+ def testNoArguments(self):
+ app = QGuiApplication()
+ self.assertIsInstance(app, QGuiApplication)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qicon_test.py b/sources/pyside6/tests/QtGui/qicon_test.py
new file mode 100644
index 000000000..18ef3d815
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qicon_test.py
@@ -0,0 +1,48 @@
+# 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.timedqguiapplication import TimedQGuiApplication
+from PySide6.QtGui import QIcon
+
+
+class QIconCtorWithNoneTest(TimedQGuiApplication):
+ '''Test made by seblin, see Bug #944: http://bugs.pyside.org/show_bug.cgi?id=944'''
+
+ def testQIconCtorWithNone(self):
+ icon = QIcon(None)
+ pixmap = icon.pixmap(48, 48)
+ self.app.exec()
+
+
+PIX_PATH = os.fspath(Path(__file__).resolve().parents[2]
+ / "doc/tutorials/basictutorial/icons.png")
+
+
+class QIconAddPixmapTest(TimedQGuiApplication):
+ '''PYSIDE-1669: check that addPixmap works'''
+
+ def testQIconSetPixmap(self):
+ icon = QIcon()
+ icon.addPixmap(PIX_PATH)
+ sizes = icon.availableSizes()
+ self.assertTrue(sizes)
+
+ def testQIconSetPixmapPathlike(self):
+ icon = QIcon()
+ pix_path = Path(PIX_PATH)
+ icon.addPixmap(pix_path)
+ sizes = icon.availableSizes()
+ self.assertTrue(sizes)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qimage_test.py b/sources/pyside6/tests/QtGui/qimage_test.py
new file mode 100644
index 000000000..5912bf318
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qimage_test.py
@@ -0,0 +1,56 @@
+# 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 cases for QImage'''
+
+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.QtGui import QImage
+from helper.usesqapplication import UsesQApplication
+from xpm_data import xpm
+
+
+class QImageTest(UsesQApplication):
+ '''Test case for calling setPixel with float as argument'''
+
+ def testQImageStringBuffer(self):
+ '''Test if the QImage signatures receiving string buffers exist.'''
+ file = Path(__file__).resolve().parent / 'sample.png'
+ self.assertTrue(file.is_file())
+ img0 = QImage(file)
+
+ # btw let's test the bits() method
+ img1 = QImage(img0.bits(), img0.width(), img0.height(), img0.format())
+ img1.setColorSpace(img0.colorSpace())
+ self.assertEqual(img0, img1)
+ img2 = QImage(img0.bits(), img0.width(), img0.height(), img0.bytesPerLine(), img0.format())
+ img2.setColorSpace(img0.colorSpace())
+ self.assertEqual(img0, img2)
+
+ ## test scanLine method
+ data1 = img0.scanLine(0)
+ data2 = img1.scanLine(0)
+ self.assertEqual(data1, data2)
+
+ def testEmptyBuffer(self):
+ img = QImage(bytes('', "UTF-8"), 100, 100, QImage.Format_ARGB32)
+
+ def testEmptyStringAsBuffer(self):
+ img = QImage(bytes('', "UTF-8"), 100, 100, QImage.Format_ARGB32)
+
+ def testXpmConstructor(self):
+ img = QImage(xpm)
+ self.assertFalse(img.isNull())
+ self.assertEqual(img.width(), 27)
+ self.assertEqual(img.height(), 22)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qimage_win_test.py b/sources/pyside6/tests/QtGui/qimage_win_test.py
new file mode 100644
index 000000000..2d9cb96f1
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qimage_win_test.py
@@ -0,0 +1,41 @@
+# 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 cases for QImage/Windows'''
+
+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 Qt
+from PySide6.QtGui import QImage
+from helper.usesqapplication import UsesQApplication
+
+
+def create_image():
+ result = QImage(20, 20, QImage.Format_RGB32)
+ result.fill(Qt.white)
+ return result
+
+
+class QImageWinTest(UsesQApplication):
+
+ def test_to_hbitmap(self):
+ """Test conversion to/from a Windows HBITMAP."""
+
+ image = create_image()
+ hbitmap = image.toHBITMAP()
+ self.assertTrue(hbitmap > 0)
+
+ image2 = QImage.fromHBITMAP(hbitmap)
+ image2.setColorSpace(image.colorSpace())
+ self.assertEqual(image, image2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qitemselection_test.py b/sources/pyside6/tests/QtGui/qitemselection_test.py
new file mode 100644
index 000000000..179bff745
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qitemselection_test.py
@@ -0,0 +1,31 @@
+# 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 QItemSelection
+from PySide6.QtGui import QStandardItemModel
+
+
+class QItemSelectionTest(UsesQApplication):
+ def testLen(self):
+ model = QStandardItemModel(2, 2)
+ model.insertRow(0)
+ model.insertRow(1)
+ model.insertColumn(0)
+ model.insertColumn(1)
+ selection = QItemSelection(model.index(0, 0), model.index(1, 1))
+ self.assertEqual(len(selection), 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtGui/qkeysequence_test.py b/sources/pyside6/tests/QtGui/qkeysequence_test.py
new file mode 100644
index 000000000..3d72fb50a
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qkeysequence_test.py
@@ -0,0 +1,36 @@
+# 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 Qt
+from PySide6.QtGui import QKeySequence, qt_set_sequence_auto_mnemonic
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QKeySequenceTest(UsesQApplication):
+
+ def testGetItemOperator(self):
+ # bug #774
+ # PYSIDE-1735: Remapped from Qt.Modifier to Qt.KeyboardModifier
+ # Note that Qt.(Keyboard)?Modifier will be no longer IntFlag.
+ ks = QKeySequence(Qt.ShiftModifier, Qt.ControlModifier, Qt.Key_P, Qt.Key_R)
+ self.assertEqual(ks[0].keyboardModifiers(), Qt.ShiftModifier)
+ self.assertEqual(ks[1].keyboardModifiers(), Qt.ControlModifier)
+ self.assertEqual(ks[2].key(), Qt.Key_P)
+ self.assertEqual(ks[3].key(), Qt.Key_R)
+
+ def testAutoMnemonic(self):
+ qt_set_sequence_auto_mnemonic(True)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qpainter_test.py b/sources/pyside6/tests/QtGui/qpainter_test.py
new file mode 100644
index 000000000..103b91ad6
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qpainter_test.py
@@ -0,0 +1,115 @@
+# 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 helper.usesqapplication import UsesQApplication
+from PySide6.QtGui import QPainter, QLinearGradient, QImage
+from PySide6.QtCore import QLine, QLineF, QPoint, QPointF, QRect, QRectF, Qt
+
+
+try:
+ import numpy as np
+ HAVE_NUMPY = True
+except ModuleNotFoundError:
+ HAVE_NUMPY = False
+
+
+class QPainterDrawText(UsesQApplication):
+ def setUp(self):
+ super(QPainterDrawText, self).setUp()
+ self.image = QImage(32, 32, QImage.Format_ARGB32)
+ self.painter = QPainter(self.image)
+ self.text = 'teste!'
+
+ def tearDown(self):
+ del self.text
+ self.painter.end()
+ del self.painter
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(QPainterDrawText, self).tearDown()
+
+ def testDrawText(self):
+ # bug #254
+ rect = self.painter.drawText(100, 100, 100, 100,
+ Qt.AlignCenter | Qt.TextWordWrap,
+ self.text)
+ self.assertTrue(isinstance(rect, QRect))
+
+ def testDrawTextWithRect(self):
+ # bug #225
+ rect = QRect(100, 100, 100, 100)
+ newRect = self.painter.drawText(rect, Qt.AlignCenter | Qt.TextWordWrap,
+ self.text)
+
+ self.assertTrue(isinstance(newRect, QRect))
+
+ def testDrawTextWithRectF(self):
+ '''QPainter.drawText(QRectF, ... ,QRectF*) inject code'''
+ rect = QRectF(100, 52.3, 100, 100)
+ newRect = self.painter.drawText(rect, Qt.AlignCenter | Qt.TextWordWrap,
+ self.text)
+
+ self.assertTrue(isinstance(newRect, QRectF))
+
+ def testDrawOverloads(self):
+ '''Calls QPainter.drawLines overloads, if something is
+ wrong Exception and chaos ensues. Bug #395'''
+ self.painter.drawLines([QLine(QPoint(0, 0), QPoint(1, 1))])
+ self.painter.drawLines([QPoint(0, 0), QPoint(1, 1)])
+ self.painter.drawLines([QPointF(0, 0), QPointF(1, 1)])
+ self.painter.drawLines([QLineF(QPointF(0, 0), QPointF(1, 1))])
+ self.painter.drawPoints([QPoint(0, 0), QPoint(1, 1)])
+ self.painter.drawPoints([QPointF(0, 0), QPointF(1, 1)])
+ self.painter.drawConvexPolygon([QPointF(10.0, 80.0),
+ QPointF(20.0, 10.0),
+ QPointF(80.0, 30.0),
+ QPointF(90.0, 70.0)])
+ self.painter.drawConvexPolygon([QPoint(10.0, 80.0),
+ QPoint(20.0, 10.0),
+ QPoint(80.0, 30.0),
+ QPoint(90.0, 70.0)])
+ self.painter.drawPolygon([QPointF(10.0, 80.0),
+ QPointF(20.0, 10.0),
+ QPointF(80.0, 30.0),
+ QPointF(90.0, 70.0)])
+ self.painter.drawPolygon([QPoint(10.0, 80.0),
+ QPoint(20.0, 10.0),
+ QPoint(80.0, 30.0),
+ QPoint(90.0, 70.0)])
+ self.painter.drawPolyline([QPointF(10.0, 80.0),
+ QPointF(20.0, 10.0),
+ QPointF(80.0, 30.0),
+ QPointF(90.0, 70.0)])
+ self.painter.drawPolyline([QPoint(10.0, 80.0),
+ QPoint(20.0, 10.0),
+ QPoint(80.0, 30.0),
+ QPoint(90.0, 70.0)])
+ if HAVE_NUMPY:
+ x = np.array([10.0, 20.0, 80.0, 90.0])
+ y = np.array([80.0, 10.0, 30.0, 70.0])
+ self.painter.drawPointsNp(x, y)
+
+
+class SetBrushWithOtherArgs(UsesQApplication):
+ '''Using qpainter.setBrush with args other than QBrush'''
+
+ def testSetBrushGradient(self):
+ image = QImage(32, 32, QImage.Format_ARGB32)
+ with QPainter(image) as painter:
+ gradient = QLinearGradient(0, 0, 0, 0)
+ painter.setBrush(gradient)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtGui/qpdfwriter_test.py b/sources/pyside6/tests/QtGui/qpdfwriter_test.py
new file mode 100644
index 000000000..2dca2aca2
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qpdfwriter_test.py
@@ -0,0 +1,32 @@
+# 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.QtGui import QPageLayout, QPageSize, QPdfWriter, QTextDocument
+from PySide6.QtCore import QDir, QMarginsF, QTemporaryFile
+
+
+class QPdfWriterTest(UsesQApplication):
+
+ def testWrite(self):
+ temporaryFile = QTemporaryFile(QDir.tempPath() + "/pdfwriter_test_XXXXXX.pdf")
+ self.assertTrue(temporaryFile.open())
+ pdfWriter = QPdfWriter(temporaryFile)
+ pdfWriter.setPageLayout(QPageLayout(QPageSize(QPageSize.A4), QPageLayout.Portrait, QMarginsF(10, 10, 10, 10)))
+ doc = QTextDocument("Some text")
+ doc.print_(pdfWriter)
+ temporaryFile.close()
+ self.assertTrue(temporaryFile.size() > 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qpen_test.py b/sources/pyside6/tests/QtGui/qpen_test.py
new file mode 100644
index 000000000..7e8604606
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qpen_test.py
@@ -0,0 +1,57 @@
+# 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 Qt, QTimer
+from PySide6.QtGui import QPen, QPainter, QRasterWindow
+
+
+class Painting(QRasterWindow):
+ def __init__(self):
+ super().__init__()
+ self.penFromEnum = None
+ self.penFromInteger = None
+
+ def paintEvent(self, event):
+ with QPainter(self) as painter:
+ painter.setPen(Qt.NoPen)
+ self.penFromEnum = painter.pen()
+ intVal = Qt.NoPen.value
+ painter.setPen(intVal)
+ self.penFromInteger = painter.pen()
+ QTimer.singleShot(20, self.close)
+
+
+class QPenTest(UsesQApplication):
+
+ def testCtorWithCreatedEnums(self):
+ '''A simple case of QPen creation using created enums.'''
+ width = 0
+ style = Qt.PenStyle(0)
+ cap = Qt.PenCapStyle(0)
+ join = Qt.PenJoinStyle(0)
+ pen = QPen(Qt.blue, width, style, cap, join)
+
+ def testSetPenWithPenStyleEnum(self):
+ '''Calls QPainter.setPen with both enum and integer. Bug #511.'''
+ w = Painting()
+ w.show()
+ w.setTitle("qpen_test")
+ self.app.exec()
+ self.assertEqual(w.penFromEnum.style(), Qt.NoPen)
+ self.assertEqual(w.penFromInteger.style(), Qt.SolidLine)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtGui/qpixelformat_test.py b/sources/pyside6/tests/QtGui/qpixelformat_test.py
new file mode 100644
index 000000000..869d15952
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qpixelformat_test.py
@@ -0,0 +1,40 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Unit test for QPixelFormat'''
+
+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 QSize, Qt
+from PySide6.QtGui import QColor, QImage, QPixelFormat, qPixelFormatRgba
+
+
+class QPixelFormatTest(UsesQApplication):
+ def test(self):
+ image = QImage(QSize(200, 200), QImage.Format_ARGB32)
+ image.fill(QColor(Qt.red))
+ pixelFormat = image.pixelFormat()
+ print(pixelFormat.greenSize())
+ self.assertEqual(pixelFormat.alphaSize(), 8)
+ self.assertEqual(pixelFormat.redSize(), 8)
+ self.assertEqual(pixelFormat.greenSize(), 8)
+ self.assertEqual(pixelFormat.blueSize(), 8)
+ self.assertEqual(pixelFormat.bitsPerPixel(), 32)
+
+ def testHelpers(self):
+ format = qPixelFormatRgba(8, 8, 8, 8, QPixelFormat.UsesAlpha,
+ QPixelFormat.AtBeginning, QPixelFormat.Premultiplied,
+ QPixelFormat.UnsignedByte)
+ self.assertEqual(format.redSize(), 8)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qpixmap_constructor.py b/sources/pyside6/tests/QtGui/qpixmap_constructor.py
new file mode 100644
index 000000000..dd658af52
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qpixmap_constructor.py
@@ -0,0 +1,260 @@
+#!/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.QtGui import QPixmap
+
+from helper.usesqapplication import UsesQApplication
+
+xpm = [
+ "27 22 206 2",
+ " c None",
+ ". c #FEFEFE",
+ "+ c #FFFFFF",
+ "@ c #F9F9F9",
+ "# c #ECECEC",
+ "$ c #D5D5D5",
+ "% c #A0A0A0",
+ "& c #767676",
+ "* c #525252",
+ "= c #484848",
+ "- c #4E4E4E",
+ "; c #555555",
+ "> c #545454",
+ ", c #5A5A5A",
+ "' c #4B4B4B",
+ ") c #4A4A4A",
+ "! c #4F4F4F",
+ "~ c #585858",
+ "{ c #515151",
+ "] c #4C4C4C",
+ "^ c #B1B1B1",
+ "/ c #FCFCFC",
+ "( c #FDFDFD",
+ "_ c #C1C1C1",
+ ": c #848484",
+ "< c #616161",
+ "[ c #5E5E5E",
+ "} c #CECECE",
+ "| c #E2E2E2",
+ "1 c #E4E4E4",
+ "2 c #DFDFDF",
+ "3 c #D2D2D2",
+ "4 c #D8D8D8",
+ "5 c #D4D4D4",
+ "6 c #E6E6E6",
+ "7 c #F1F1F1",
+ "8 c #838383",
+ "9 c #8E8E8E",
+ "0 c #8F8F8F",
+ "a c #CBCBCB",
+ "b c #CCCCCC",
+ "c c #E9E9E9",
+ "d c #F2F2F2",
+ "e c #EDEDED",
+ "f c #B5B5B5",
+ "g c #A6A6A6",
+ "h c #ABABAB",
+ "i c #BBBBBB",
+ "j c #B0B0B0",
+ "k c #EAEAEA",
+ "l c #6C6C6C",
+ "m c #BCBCBC",
+ "n c #F5F5F5",
+ "o c #FAFAFA",
+ "p c #B6B6B6",
+ "q c #F3F3F3",
+ "r c #CFCFCF",
+ "s c #FBFBFB",
+ "t c #CDCDCD",
+ "u c #DDDDDD",
+ "v c #999999",
+ "w c #F0F0F0",
+ "x c #2B2B2B",
+ "y c #C3C3C3",
+ "z c #A4A4A4",
+ "A c #D7D7D7",
+ "B c #E7E7E7",
+ "C c #6E6E6E",
+ "D c #9D9D9D",
+ "E c #BABABA",
+ "F c #AEAEAE",
+ "G c #898989",
+ "H c #646464",
+ "I c #BDBDBD",
+ "J c #CACACA",
+ "K c #2A2A2A",
+ "L c #212121",
+ "M c #B7B7B7",
+ "N c #F4F4F4",
+ "O c #737373",
+ "P c #828282",
+ "Q c #4D4D4D",
+ "R c #000000",
+ "S c #151515",
+ "T c #B2B2B2",
+ "U c #D6D6D6",
+ "V c #D3D3D3",
+ "W c #2F2F2F",
+ "X c #636363",
+ "Y c #A1A1A1",
+ "Z c #BFBFBF",
+ "` c #E0E0E0",
+ " . c #6A6A6A",
+ ".. c #050505",
+ "+. c #A3A3A3",
+ "@. c #202020",
+ "#. c #5F5F5F",
+ "$. c #B9B9B9",
+ "%. c #C7C7C7",
+ "&. c #D0D0D0",
+ "*. c #3E3E3E",
+ "=. c #666666",
+ "-. c #DBDBDB",
+ ";. c #424242",
+ ">. c #C2C2C2",
+ ",. c #1A1A1A",
+ "'. c #2C2C2C",
+ "). c #F6F6F6",
+ "!. c #AAAAAA",
+ "~. c #DCDCDC",
+ "{. c #2D2D2D",
+ "]. c #2E2E2E",
+ "^. c #A7A7A7",
+ "/. c #656565",
+ "(. c #333333",
+ "_. c #464646",
+ ":. c #C4C4C4",
+ "<. c #B8B8B8",
+ "[. c #292929",
+ "}. c #979797",
+ "|. c #EFEFEF",
+ "1. c #909090",
+ "2. c #8A8A8A",
+ "3. c #575757",
+ "4. c #676767",
+ "5. c #C5C5C5",
+ "6. c #7A7A7A",
+ "7. c #797979",
+ "8. c #989898",
+ "9. c #EEEEEE",
+ "0. c #707070",
+ "a. c #C8C8C8",
+ "b. c #111111",
+ "c. c #AFAFAF",
+ "d. c #474747",
+ "e. c #565656",
+ "f. c #E3E3E3",
+ "g. c #494949",
+ "h. c #5B5B5B",
+ "i. c #222222",
+ "j. c #353535",
+ "k. c #D9D9D9",
+ "l. c #0A0A0A",
+ "m. c #858585",
+ "n. c #E5E5E5",
+ "o. c #0E0E0E",
+ "p. c #9A9A9A",
+ "q. c #6F6F6F",
+ "r. c #868686",
+ "s. c #060606",
+ "t. c #1E1E1E",
+ "u. c #E8E8E8",
+ "v. c #A5A5A5",
+ "w. c #0D0D0D",
+ "x. c #030303",
+ "y. c #272727",
+ "z. c #131313",
+ "A. c #1F1F1F",
+ "B. c #757575",
+ "C. c #F7F7F7",
+ "D. c #414141",
+ "E. c #080808",
+ "F. c #6B6B6B",
+ "G. c #313131",
+ "H. c #C0C0C0",
+ "I. c #C9C9C9",
+ "J. c #0B0B0B",
+ "K. c #232323",
+ "L. c #434343",
+ "M. c #3D3D3D",
+ "N. c #282828",
+ "O. c #7C7C7C",
+ "P. c #252525",
+ "Q. c #3A3A3A",
+ "R. c #F8F8F8",
+ "S. c #1B1B1B",
+ "T. c #949494",
+ "U. c #3B3B3B",
+ "V. c #242424",
+ "W. c #383838",
+ "X. c #6D6D6D",
+ "Y. c #818181",
+ "Z. c #939393",
+ "`. c #9E9E9E",
+ " + c #929292",
+ ".+ c #7D7D7D",
+ "++ c #ADADAD",
+ "@+ c #DADADA",
+ "#+ c #919191",
+ "$+ c #E1E1E1",
+ "%+ c #BEBEBE",
+ "&+ c #ACACAC",
+ "*+ c #9C9C9C",
+ "=+ c #B3B3B3",
+ "-+ c #808080",
+ ";+ c #A8A8A8",
+ ">+ c #393939",
+ ",+ c #747474",
+ "'+ c #7F7F7F",
+ ")+ c #D1D1D1",
+ "!+ c #606060",
+ "~+ c #5C5C5C",
+ "{+ c #686868",
+ "]+ c #7E7E7E",
+ "^+ c #787878",
+ "/+ c #595959",
+ ". . . + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / . . + + ",
+ ". ( + _ : < [ & } | 1 2 $ 3 4 5 3 6 7 + + 8 9 + . + . ",
+ ". + 0 9 a ( 3 a b c d e c f g h i g j $ k + l m + . + ",
+ "+ 2 8 n o p | ( q r s . # t + + + u ^ v e w + x + + + ",
+ "+ y z . @ A k B 7 n + ( s | p 8 C D 2 E 4 + + F G + . ",
+ "# H I $ J G K L - M N . 2 O P Q R R S T U s s V W j + ",
+ "X Y Z @ o ` _ g ...+.( 4 @.#.m G $.%.7 &.X *.=.-.;.&.",
+ "Q >.C ,.'.} e + ).!.k + . + + . ~.{.> ].x f 7 ^./.k (.",
+ "_.:.4 @ <.[.}.|.1.2.+ + + >.} 4 B + ( @ _ 3.4.5.6.r 7.",
+ "3.8.9.~ 0.+ a.Q b.+ + c.d.#.=.$ |.b #.e.z ^ ; ^. .f.g.",
+ "-.h.+ i.S M + # p j.% n 9.5.k.H l.m.V ^.n.o.M + M p.q.",
+ "7 r.N s.1.R t.<.|.| u.v.~ w.x.E + s y.z.A.B.C.+ 5 D.q ",
+ ").p.2 E.0.9 F.%.O {._ @.+ + i { [ i.G.H.P I.+ s q.} + ",
+ ").p.6 J.R b.K.L.M.A.! b.g.K [.R M k + N.I + + >.O.+ . ",
+ ").8.9.N.P...R R R R E.t.W n.+ Q.R.6 @.| + . + S.+ + . ",
+ "n }.w T.U.B.<.i.@ Y + + U.+ c u V.= B B 7 u.W.c + . + ",
+ "N T.# + }.X.Y.,.8.F.8 Z.[.`. +.+}.4 ++@+O.< ~.+ ( . + ",
+ "d #+1 + _ ~.u.$+b $.y @+| $+%+I.&+k.h W +.9.+ ( . + . ",
+ "w 0 |.*+. >.<.=+++++p a.p -+;+5.k.>+,+@ + . . + . + + ",
+ "q '+9.R.^ I.t b %.I.)+4 $+n.I.,+ .|.+ . . . + . + + + ",
+ ". p !+( + + + + + + E 0. .-+8.f.+ + . . + + . + + + + ",
+ ". ( A ~+{+]+^+l > /+D f.c q . + . . + + . + + + + + + "
+]
+
+
+class QStringSequenceTest(UsesQApplication):
+ def testQPixmapConstructor(self):
+ pixmap1 = QPixmap(xpm)
+ self.assertFalse(pixmap1.isNull())
+ self.assertEqual(pixmap1.width(), 27)
+ self.assertEqual(pixmap1.height(), 22)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qpixmap_test.py b/sources/pyside6/tests/QtGui/qpixmap_test.py
new file mode 100644
index 000000000..b80ae2ad5
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qpixmap_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 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.QtGui import QColor, QPixmap
+from PySide6.QtCore import QFile, QIODevice, QObject, QSize, Qt
+
+
+class QPixmapTest(UsesQApplication):
+ def testQVariantConstructor(self):
+ obj = QObject()
+ pixmap = QPixmap()
+ obj.setProperty('foo', pixmap)
+ self.assertEqual(type(obj.property('foo')), QPixmap)
+
+ def testQSizeConstructor(self):
+ pixmap = QPixmap(QSize(10, 20))
+ self.assertTrue(pixmap.size().height(), 20)
+
+ def testQStringConstructor(self):
+ pixmap = QPixmap("Testing!")
+
+ def testQPixmapLoadFromDataWithQFile(self):
+ f = QFile(os.path.join(os.path.dirname(__file__), 'sample.png'))
+ self.assertTrue(f.open(QIODevice.ReadOnly))
+ data = f.read(f.size())
+ f.close()
+ pixmap = QPixmap()
+ self.assertTrue(pixmap.loadFromData(data))
+
+ def testQPixmapLoadFromDataWithPython(self):
+ data = open(os.path.join(os.path.dirname(__file__), 'sample.png'), 'rb').read()
+ pixmap = QPixmap()
+ self.assertTrue(pixmap.loadFromData(data))
+
+
+class QPixmapToImage(UsesQApplication):
+
+ def testFilledImage(self):
+ '''QPixmap.fill + toImage + image.pixel'''
+ pixmap = QPixmap(100, 200)
+ pixmap.fill(Qt.red) # Default Qt.white
+
+ self.assertEqual(pixmap.height(), 200)
+ self.assertEqual(pixmap.width(), 100)
+
+ image = pixmap.toImage()
+
+ self.assertEqual(image.height(), 200)
+ self.assertEqual(image.width(), 100)
+
+ pixel = image.pixel(10, 10)
+ self.assertEqual(pixel, QColor(Qt.red).rgba())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtGui/qpixmapcache_test.py b/sources/pyside6/tests/QtGui/qpixmapcache_test.py
new file mode 100644
index 000000000..2ecb439d3
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qpixmapcache_test.py
@@ -0,0 +1,56 @@
+# 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.QtGui import QPixmapCache, QPixmap
+
+
+class QPixmapCacheTest(UsesQApplication):
+
+ def testWithString(self):
+ pm1 = QPixmap()
+ ok = QPixmapCache.find('img', pm1)
+ self.assertFalse(ok)
+
+ self.assertEqual(QPixmapCache.find('img'), None)
+
+ pm2 = QPixmap()
+ ok = QPixmapCache.insert('img', pm2)
+ self.assertTrue(ok)
+
+ pm3 = QPixmap()
+ ok = QPixmapCache.find('img', pm3)
+ self.assertTrue(ok)
+ b1 = QPixmapCache.find('img').toImage().bits()
+ b2 = pm3.toImage().bits()
+ self.assertEqual(QPixmapCache.find('img').toImage().bits(), pm3.toImage().bits())
+
+ def testWithKey(self):
+ pm1 = QPixmap()
+ ok = QPixmapCache.find(QPixmapCache.Key(), pm1)
+ self.assertFalse(ok)
+
+ self.assertEqual(QPixmapCache.find(QPixmapCache.Key()), None)
+
+ pm2 = QPixmap()
+ key = QPixmapCache.insert(pm2)
+
+ pm3 = QPixmap()
+ ok = QPixmapCache.find(key, pm3)
+ self.assertTrue(ok)
+
+ self.assertEqual(QPixmapCache.find(key).toImage().bits(), pm3.toImage().bits())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtGui/qpolygonf_test.py b/sources/pyside6/tests/QtGui/qpolygonf_test.py
new file mode 100644
index 000000000..8a283fddc
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qpolygonf_test.py
@@ -0,0 +1,42 @@
+# 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 QPoint, QPointF
+from PySide6.QtGui import QPolygon, QPolygonF
+
+
+class QPolygonFNotIterableTest(unittest.TestCase):
+ """Test if a QPolygonF is iterable"""
+
+ def testIt(self):
+ points = []
+ for i in range(0, 4):
+ points.append(QPointF(float(i), float(i)))
+
+ p = QPolygonF(points)
+ self.assertEqual(len(p), 4)
+
+ i = 0
+ for point in p:
+ self.assertEqual(int(point.x()), i)
+ self.assertEqual(int(point.y()), i)
+ i += 1
+
+ def testPolygonShiftOperators(self):
+ p = QPolygon()
+ self.assertEqual(len(p), 0)
+ p << QPoint(10, 20) << QPoint(20, 30) << [QPoint(20, 30), QPoint(40, 50)]
+ self.assertEqual(len(p), 4)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qradialgradient_test.py b/sources/pyside6/tests/QtGui/qradialgradient_test.py
new file mode 100644
index 000000000..ebab42b15
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qradialgradient_test.py
@@ -0,0 +1,41 @@
+# 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.QtGui import QRadialGradient
+from PySide6.QtCore import QPointF
+
+
+class QRadialGradientConstructor(unittest.TestCase):
+ def _compare(self, qptf, tpl):
+ self.assertEqual((qptf.x(), qptf.y()), tpl)
+
+ def _assertValues(self, grad):
+ self._compare(grad.center(), (1.0, 2.0))
+ self._compare(grad.focalPoint(), (3.0, 4.0))
+ self.assertEqual(grad.radius(), 5.0)
+
+ def testAllInt(self):
+ grad = QRadialGradient(1, 2, 5, 3, 4)
+ self._assertValues(grad)
+
+ def testQPointF(self):
+ grad = QRadialGradient(QPointF(1, 2), 5, QPointF(3, 4))
+ self._assertValues(grad)
+
+ def testSetQPointF(self):
+ grad = QRadialGradient()
+ grad.setCenter(QPointF(1, 2))
+ self._compare(grad.center(), (1.0, 2.0))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qrasterwindow_test.py b/sources/pyside6/tests/QtGui/qrasterwindow_test.py
new file mode 100644
index 000000000..4920902d5
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qrasterwindow_test.py
@@ -0,0 +1,77 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Unit test for QBackingStore, QRasterWindow and QStaticText'''
+
+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 QPoint, QRect, QSize, QTimer, Qt
+from PySide6.QtGui import (QColor, QPainter, QRasterWindow, QStaticText,
+ QTextCursor, QTextDocument, QAbstractTextDocumentLayout)
+
+
+# Window using convenience class QRasterWindow
+class StaticTextRasterWindow(QRasterWindow):
+ def __init__(self):
+ super().__init__()
+ self.text = QStaticText("QRasterWindow")
+
+ def paintEvent(self, event):
+ clientRect = QRect(QPoint(0, 0), self.size())
+ with QPainter(self) as painter:
+ painter.fillRect(clientRect, QColor(Qt.red))
+ painter.drawStaticText(QPoint(10, 10), self.text)
+
+
+class TextDocumentWindow(QRasterWindow):
+ """PYSIDE-2252, drawing with QAbstractTextDocumentLayout.PaintContext"""
+
+ def __init__(self):
+ super().__init__()
+ self.m_document = QTextDocument()
+ self.m_document.setPlainText("bla bla")
+
+ def paintEvent(self, event):
+ with QPainter(self) as painter:
+ clientRect = QRect(QPoint(0, 0), self.size())
+ painter.fillRect(clientRect, QColor(Qt.white))
+ ctx = QAbstractTextDocumentLayout.PaintContext()
+ ctx.clip = clientRect
+
+ sel = QAbstractTextDocumentLayout.Selection()
+ cursor = QTextCursor(self.m_document)
+ cursor.movePosition(QTextCursor.Start)
+ cursor.movePosition(QTextCursor.NextWord, QTextCursor.KeepAnchor)
+ sel.cursor = cursor
+ sel.format.setForeground(Qt.red)
+ ctx.selections = [sel]
+
+ self.m_document.documentLayout().draw(painter, ctx)
+
+
+class QRasterWindowTest(UsesQApplication):
+ def test(self):
+ rasterWindow = StaticTextRasterWindow()
+ rasterWindow.setFramePosition(QPoint(100, 100))
+ rasterWindow.resize(QSize(400, 400))
+ rasterWindow.show()
+
+ rasterWindow2 = TextDocumentWindow()
+ rasterWindow2.setFramePosition(rasterWindow.frameGeometry().topRight() + QPoint(20, 0))
+ rasterWindow2.resize(QSize(400, 400))
+ rasterWindow2.show()
+
+ QTimer.singleShot(100, self.app.quit)
+ self.app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qregion_test.py b/sources/pyside6/tests/QtGui/qregion_test.py
new file mode 100644
index 000000000..df14fc3e0
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qregion_test.py
@@ -0,0 +1,40 @@
+# 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.QtGui import QRegion
+from PySide6.QtCore import QPoint, QRect, QSize
+from helper.usesqapplication import UsesQApplication
+
+
+class QRegionTest(UsesQApplication):
+
+ def testFunctionUnit(self):
+ r = QRegion(0, 0, 10, 10)
+ r2 = QRegion(5, 5, 10, 10)
+
+ ru = r.united(r2)
+ self.assertTrue(ru.contains(QPoint(0, 0)))
+ self.assertTrue(ru.contains(QPoint(5, 5)))
+ self.assertTrue(ru.contains(QPoint(10, 10)))
+ self.assertTrue(ru.contains(QPoint(14, 14)))
+
+ def testSequence(self):
+ region = QRegion()
+ region += QRect(QPoint(0, 0), QSize(10, 10))
+ region += QRect(QPoint(10, 0), QSize(20, 20))
+ self.assertEqual(len(region), 2)
+ for r in region:
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qshortcut_test.py b/sources/pyside6/tests/QtGui/qshortcut_test.py
new file mode 100644
index 000000000..f2650589a
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qshortcut_test.py
@@ -0,0 +1,60 @@
+# 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 the QShortcut constructor'''
+
+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 Qt, QTimer
+from PySide6.QtGui import QGuiApplication, QKeySequence, QShortcut, QWindow
+
+
+class Foo(QWindow):
+ def __init__(self):
+ super().__init__()
+ self.ok = False
+ self.copy = False
+
+ def slot_of_foo(self):
+ self.ok = True
+
+ def slot_of_copy(self):
+ self.copy = True
+
+
+class MyShortcut(QShortcut):
+ def __init__(self, keys, wdg, slot):
+ QShortcut.__init__(self, keys, wdg, slot)
+
+ def emit_signal(self):
+ self.activated.emit()
+
+
+class QAppPresence(unittest.TestCase):
+
+ def testQShortcut(self):
+ self.qapp = QGuiApplication([])
+ f = Foo()
+
+ self.sc = MyShortcut(QKeySequence(Qt.Key_Return), f, f.slot_of_foo)
+ self.scstd = MyShortcut(QKeySequence.Copy, f, f.slot_of_copy)
+ QTimer.singleShot(0, self.init)
+ self.qapp.exec()
+ self.assertEqual(f.ok, True)
+ self.assertEqual(f.copy, True)
+
+ def init(self):
+ self.sc.emit_signal()
+ self.scstd.emit_signal()
+ self.qapp.quit()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qstandarditemmodel_test.py b/sources/pyside6/tests/QtGui/qstandarditemmodel_test.py
new file mode 100644
index 000000000..55aca9113
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qstandarditemmodel_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 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
+from PySide6.QtGui import QStandardItemModel, QStandardItem
+from shiboken6 import Shiboken
+from helper.usesqapplication import UsesQApplication
+
+
+class QStandardItemModelTest(UsesQApplication):
+
+ def setUp(self):
+ super(QStandardItemModelTest, self).setUp()
+ self.parent = QObject()
+ self.model = QStandardItemModel(0, 3, self.parent)
+
+ def tearDown(self):
+ del self.parent
+ del self.model
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(QStandardItemModelTest, self).tearDown()
+
+ def testInsertRow(self):
+ # bug #227
+ self.model.insertRow(0)
+
+ def testClear(self):
+
+ model = QStandardItemModel()
+ root = model.invisibleRootItem()
+ model.clear()
+ self.assertFalse(Shiboken.isValid(root))
+
+
+class QStandardItemModelRef(UsesQApplication):
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefCount(self):
+ model = QStandardItemModel(5, 5)
+ items = []
+ for r in range(5):
+ row = []
+ for c in range(5):
+ row.append(QStandardItem(f"{r},{c}"))
+ self.assertEqual(sys.getrefcount(row[c]), 2)
+
+ model.insertRow(r, row)
+
+ for c in range(5):
+ ref_after = sys.getrefcount(row[c])
+ # check if the ref count was incremented after insertRow
+ self.assertEqual(ref_after, 3)
+
+ items.append(row)
+ row = None
+
+ for r in range(3):
+ my_row = model.takeRow(0)
+ my_row = None
+ for c in range(5):
+ # only rest 1 reference
+ self.assertEqual(sys.getrefcount(items[r][c]), 2)
+
+ my_i = model.item(0, 0)
+ # ref(my_i) + parent_ref + items list ref
+ self.assertEqual(sys.getrefcount(my_i), 4)
+
+ model.clear()
+ # ref(my_i)
+ self.assertEqual(sys.getrefcount(my_i), 3)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtGui/qstring_qkeysequence_test.py b/sources/pyside6/tests/QtGui/qstring_qkeysequence_test.py
new file mode 100644
index 000000000..f68374263
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qstring_qkeysequence_test.py
@@ -0,0 +1,42 @@
+#!/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
+
+'''Tests conversions of QString to and from QKeySequence.'''
+
+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.QtGui import QAction, QKeySequence
+
+
+class QStringQKeySequenceTest(UsesQApplication):
+ '''Tests conversions of QString to and from QKeySequence.'''
+
+ def testQStringFromQKeySequence(self):
+ '''Creates a QString from a QKeySequence.'''
+ keyseq = 'Ctrl+A'
+ a = QKeySequence(keyseq)
+ self.assertEqual(a, keyseq)
+
+ def testPythonStringAsQKeySequence(self):
+ '''Passes a Python string to an argument expecting a QKeySequence.'''
+ keyseq = 'Ctrl+A'
+ action = QAction(None)
+ action.setShortcut(keyseq)
+ shortcut = action.shortcut()
+ self.assertTrue(isinstance(shortcut, QKeySequence))
+ self.assertEqual(shortcut.toString(), keyseq)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtGui/qstylehints_test.py b/sources/pyside6/tests/QtGui/qstylehints_test.py
new file mode 100644
index 000000000..d2b21d30d
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qstylehints_test.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
+
+'''Unit test for QStyleHints'''
+
+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.QtGui import QStyleHints
+
+
+class QStyleHintsTest(UsesQApplication):
+ def test(self):
+ styleHints = self.app.styleHints()
+ self.assertTrue(styleHints.startDragDistance() > 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qtextdocument_functions.py b/sources/pyside6/tests/QtGui/qtextdocument_functions.py
new file mode 100644
index 000000000..2ac72df56
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qtextdocument_functions.py
@@ -0,0 +1,37 @@
+# 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.QtGui import QPageRanges, Qt
+
+
+class QTextDocumentFunctions(unittest.TestCase):
+
+ def testFunctions(self):
+ self.assertFalse(Qt.mightBeRichText('bla'))
+ self.assertTrue(Qt.mightBeRichText('<html><head/><body><p>bla</p></body></html>'))
+ html = Qt.convertFromPlainText("A & B", Qt.WhiteSpaceNormal)
+ self.assertEqual(html, '<p>A &amp; B</p>')
+
+
+class QPageRangesTest(unittest.TestCase):
+ """PYSIDE-2237: Test that field QPageRanges.Range.from is properly mangled."""
+
+ def test(self):
+ pr = QPageRanges()
+ pr.addPage(1)
+ r0 = pr.toRangeList()[0]
+ self.assertEqual(r0.from_, 1)
+ self.assertEqual(r0.to, 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qtextdocument_undoredo_test.py b/sources/pyside6/tests/QtGui/qtextdocument_undoredo_test.py
new file mode 100644
index 000000000..b74c6704f
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qtextdocument_undoredo_test.py
@@ -0,0 +1,42 @@
+# 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.QtGui import QTextDocument, QTextCursor
+
+
+class QTextDocumentTest(unittest.TestCase):
+
+ def testUndoRedo(self):
+ text = 'foobar'
+ doc = QTextDocument(text)
+
+ self.assertFalse(doc.isRedoAvailable())
+ self.assertTrue(doc.isUndoAvailable())
+ self.assertEqual(doc.toPlainText(), text)
+
+ cursor = QTextCursor(doc)
+ doc.undo(cursor)
+
+ self.assertTrue(doc.isRedoAvailable())
+ self.assertFalse(doc.isUndoAvailable())
+ self.assertEqual(doc.toPlainText(), '')
+
+ doc.redo(cursor)
+
+ self.assertFalse(doc.isRedoAvailable())
+ self.assertTrue(doc.isUndoAvailable())
+ self.assertEqual(doc.toPlainText(), text)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtGui/qtextdocumentwriter_test.py b/sources/pyside6/tests/QtGui/qtextdocumentwriter_test.py
new file mode 100644
index 000000000..4f72b98e7
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qtextdocumentwriter_test.py
@@ -0,0 +1,31 @@
+# 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.QtGui import QTextDocumentWriter, QTextDocument
+from PySide6.QtCore import QBuffer
+
+
+class QTextDocumentWriterTest(unittest.TestCase):
+
+ def testWrite(self):
+ text = 'foobar'
+ doc = QTextDocument(text)
+ b = QBuffer()
+ b.open(QBuffer.ReadWrite)
+ writer = QTextDocumentWriter(b, bytes("plaintext", "UTF-8"))
+ writer.write(doc)
+ b.close()
+ self.assertEqual(b.buffer(), text)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/qtextline_test.py b/sources/pyside6/tests/QtGui/qtextline_test.py
new file mode 100644
index 000000000..c34a4c98a
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qtextline_test.py
@@ -0,0 +1,39 @@
+# 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.QtGui import QTextLayout, QTextOption
+from helper.usesqapplication import UsesQApplication
+
+
+class QTextLineTest(UsesQApplication):
+
+ def testCursorToX(self):
+ textLayout = QTextLayout()
+ textLayout.beginLayout()
+ line = textLayout.createLine()
+ self.assertTrue(line.isValid())
+ x, cursorPos = line.cursorToX(0)
+ self.assertEqual(type(x), float)
+ self.assertEqual(type(cursorPos), int)
+ x, cursorPos = line.cursorToX(1)
+ self.assertEqual(type(x), float)
+ self.assertEqual(type(cursorPos), int)
+
+ def testTextOption(self):
+ """PYSIDE-2088, large enum values causing MSVC issues."""
+ v = QTextOption.IncludeTrailingSpaces | QTextOption.ShowTabsAndSpaces
+ self.assertEqual(v.value, 2147483649)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtGui/qtransform_test.py b/sources/pyside6/tests/QtGui/qtransform_test.py
new file mode 100644
index 000000000..dc51a74e6
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/qtransform_test.py
@@ -0,0 +1,90 @@
+# 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 QPointF
+from PySide6.QtGui import QTransform, QPolygonF, QPolygonF, QQuaternion, QVector3D
+
+
+class QTransformTest(unittest.TestCase):
+
+ def testMap(self):
+ transform = QTransform()
+ values = (10.0, 20.0)
+ tx, ty = transform.map(*values)
+ self.assertTrue(isinstance(tx, float))
+ self.assertTrue(isinstance(ty, float))
+ self.assertEqual((tx, ty), values)
+
+ def testquadToQuad(self):
+ q1 = QPolygonF()
+ q1.append(QPointF(10.0, 10.0))
+ q1.append(QPointF(20.0, 10.0))
+ q1.append(QPointF(10.0, -10.0))
+ q1.append(QPointF(20.0, -10.0))
+
+ q2 = QPolygonF()
+ q2.append(QPointF(20.0, 20.0))
+ q2.append(QPointF(30.0, 20.0))
+ q2.append(QPointF(20.0, -20.0))
+ q2.append(QPointF(30.0, -20.0))
+
+ t1 = QTransform()
+ r1 = QTransform.quadToQuad(q1, q2, t1)
+ r2 = QTransform.quadToQuad(q1, q2)
+
+ self.assertTrue(r1)
+ self.assertTrue(r2)
+
+ self.assertEqual(t1, r2)
+
+ def testquadToSquare(self):
+ q1 = QPolygonF()
+ q1.append(QPointF(10.0, 10.0))
+ q1.append(QPointF(20.0, 10.0))
+ q1.append(QPointF(10.0, -10.0))
+ q1.append(QPointF(20.0, -10.0))
+
+ t1 = QTransform()
+ r1 = QTransform.quadToSquare(q1, t1)
+ r2 = QTransform.quadToSquare(q1)
+
+ self.assertTrue(r1)
+ self.assertTrue(r2)
+
+ self.assertEqual(t1, r2)
+
+ def testsquareToQuad(self):
+ q1 = QPolygonF()
+ q1.append(QPointF(10.0, 10.0))
+ q1.append(QPointF(20.0, 10.0))
+ q1.append(QPointF(10.0, -10.0))
+ q1.append(QPointF(20.0, -10.0))
+
+ t1 = QTransform()
+ r1 = QTransform.squareToQuad(q1, t1)
+ r2 = QTransform.squareToQuad(q1)
+
+ self.assertTrue(r1)
+ self.assertTrue(r2)
+
+ self.assertEqual(t1, r2)
+
+ def testQQuaternion(self):
+ """Test return tuples."""
+ q = QQuaternion(1, 1, 1, 1)
+ self.assertEqual(len(q.getAxisAndAngle()), 2)
+ self.assertEqual(len(q.getEulerAngles()), 3)
+
+
+if __name__ == "__main__":
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtGui/repr_test.py b/sources/pyside6/tests/QtGui/repr_test.py
new file mode 100644
index 000000000..2858e7175
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/repr_test.py
@@ -0,0 +1,96 @@
+# 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
+from PySide6.QtCore import QPoint
+from PySide6.QtGui import QMatrix2x2, QMatrix2x3, QMatrix2x4
+from PySide6.QtGui import QMatrix3x2, QMatrix3x3, QMatrix3x4
+from PySide6.QtGui import QMatrix4x2, QMatrix4x3, QMatrix4x4
+from PySide6.QtGui import QVector2D, QVector3D, QVector4D
+from PySide6.QtGui import QColor, QTransform, QKeySequence, QQuaternion
+from PySide6.QtGui import QPolygon
+
+
+class ReprCopyHelper:
+ def testCopy(self):
+ copy = eval(self.original.__repr__())
+ self.assertTrue(copy is not self.original)
+ self.assertEqual(copy, self.original)
+
+
+class QTransformReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QTransform(1, 2, 3, 4, 5, 6, 7, 8, 9)
+
+
+class QQuaternionReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QQuaternion(1, 2, 3, 4)
+
+
+class QVector2DReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QVector2D(1, 2)
+
+
+class QVector3DReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QVector3D(1, 2, 3)
+
+
+class QVector4DReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QVector4D(1, 2, 3, 4)
+
+
+# Avoid these tests until get gcc fixed
+# Related bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43247
+"""
+class QMatrix2x2ReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix2x2([1, 2, 3, 4])
+
+class QMatrix2x3ReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix2x3([1, 2, 3, 4, 5, 6])
+
+class QMatrix2x4ReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix2x4([1, 2, 3, 4, 5, 6, 7, 8])
+
+class QMatrix3x2ReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix3x2([1, 2, 3, 4, 5, 6])
+
+class QMatrix3x3ReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix3x3([1, 2, 3, 4, 5, 6, 7, 8, 9])
+
+class QMatrix3x4ReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix3x4([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
+
+class QMatrix4x2ReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix4x2([1, 2, 3, 4, 5, 6, 7, 8])
+
+class QMatrix4x3ReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix4x3([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
+
+class QMatrix4x4ReprCopy(ReprCopyHelper, unittest.TestCase):
+ def setUp(self):
+ self.original = QMatrix4x4([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
+"""
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/sample.png b/sources/pyside6/tests/QtGui/sample.png
new file mode 100644
index 000000000..60450f0dc
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/sample.png
Binary files differ
diff --git a/sources/pyside6/tests/QtGui/timed_app_and_patching_test.py b/sources/pyside6/tests/QtGui/timed_app_and_patching_test.py
new file mode 100644
index 000000000..6e9a661ce
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/timed_app_and_patching_test.py
@@ -0,0 +1,27 @@
+# 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 # noqa: E402
+init_test_paths(False)
+
+from helper.timedqguiapplication import TimedQGuiApplication
+
+
+class TestTimedApp(TimedQGuiApplication):
+ '''Simple test case for TimedQGuiApplication'''
+
+ def testFoo(self):
+ # Simple test of TimedQGuiApplication
+ self.app.exec()
+
+# deprecated.py is no longer needed.
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtGui/xpm_data.py b/sources/pyside6/tests/QtGui/xpm_data.py
new file mode 100644
index 000000000..3603d8190
--- /dev/null
+++ b/sources/pyside6/tests/QtGui/xpm_data.py
@@ -0,0 +1,237 @@
+# 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 data for QImage'''
+
+
+xpm = [
+ "27 22 206 2",
+ " c None",
+ ". c #FEFEFE",
+ "+ c #FFFFFF",
+ "@ c #F9F9F9",
+ "# c #ECECEC",
+ "$ c #D5D5D5",
+ "% c #A0A0A0",
+ "& c #767676",
+ "* c #525252",
+ "= c #484848",
+ "- c #4E4E4E",
+ "; c #555555",
+ "> c #545454",
+ ", c #5A5A5A",
+ "' c #4B4B4B",
+ ") c #4A4A4A",
+ "! c #4F4F4F",
+ "~ c #585858",
+ "{ c #515151",
+ "] c #4C4C4C",
+ "^ c #B1B1B1",
+ "/ c #FCFCFC",
+ "( c #FDFDFD",
+ "_ c #C1C1C1",
+ ": c #848484",
+ "< c #616161",
+ "[ c #5E5E5E",
+ "} c #CECECE",
+ "| c #E2E2E2",
+ "1 c #E4E4E4",
+ "2 c #DFDFDF",
+ "3 c #D2D2D2",
+ "4 c #D8D8D8",
+ "5 c #D4D4D4",
+ "6 c #E6E6E6",
+ "7 c #F1F1F1",
+ "8 c #838383",
+ "9 c #8E8E8E",
+ "0 c #8F8F8F",
+ "a c #CBCBCB",
+ "b c #CCCCCC",
+ "c c #E9E9E9",
+ "d c #F2F2F2",
+ "e c #EDEDED",
+ "f c #B5B5B5",
+ "g c #A6A6A6",
+ "h c #ABABAB",
+ "i c #BBBBBB",
+ "j c #B0B0B0",
+ "k c #EAEAEA",
+ "l c #6C6C6C",
+ "m c #BCBCBC",
+ "n c #F5F5F5",
+ "o c #FAFAFA",
+ "p c #B6B6B6",
+ "q c #F3F3F3",
+ "r c #CFCFCF",
+ "s c #FBFBFB",
+ "t c #CDCDCD",
+ "u c #DDDDDD",
+ "v c #999999",
+ "w c #F0F0F0",
+ "x c #2B2B2B",
+ "y c #C3C3C3",
+ "z c #A4A4A4",
+ "A c #D7D7D7",
+ "B c #E7E7E7",
+ "C c #6E6E6E",
+ "D c #9D9D9D",
+ "E c #BABABA",
+ "F c #AEAEAE",
+ "G c #898989",
+ "H c #646464",
+ "I c #BDBDBD",
+ "J c #CACACA",
+ "K c #2A2A2A",
+ "L c #212121",
+ "M c #B7B7B7",
+ "N c #F4F4F4",
+ "O c #737373",
+ "P c #828282",
+ "Q c #4D4D4D",
+ "R c #000000",
+ "S c #151515",
+ "T c #B2B2B2",
+ "U c #D6D6D6",
+ "V c #D3D3D3",
+ "W c #2F2F2F",
+ "X c #636363",
+ "Y c #A1A1A1",
+ "Z c #BFBFBF",
+ "` c #E0E0E0",
+ " . c #6A6A6A",
+ ".. c #050505",
+ "+. c #A3A3A3",
+ "@. c #202020",
+ "#. c #5F5F5F",
+ "$. c #B9B9B9",
+ "%. c #C7C7C7",
+ "&. c #D0D0D0",
+ "*. c #3E3E3E",
+ "=. c #666666",
+ "-. c #DBDBDB",
+ ";. c #424242",
+ ">. c #C2C2C2",
+ ",. c #1A1A1A",
+ "'. c #2C2C2C",
+ "). c #F6F6F6",
+ "!. c #AAAAAA",
+ "~. c #DCDCDC",
+ "{. c #2D2D2D",
+ "]. c #2E2E2E",
+ "^. c #A7A7A7",
+ "/. c #656565",
+ "(. c #333333",
+ "_. c #464646",
+ ":. c #C4C4C4",
+ "<. c #B8B8B8",
+ "[. c #292929",
+ "}. c #979797",
+ "|. c #EFEFEF",
+ "1. c #909090",
+ "2. c #8A8A8A",
+ "3. c #575757",
+ "4. c #676767",
+ "5. c #C5C5C5",
+ "6. c #7A7A7A",
+ "7. c #797979",
+ "8. c #989898",
+ "9. c #EEEEEE",
+ "0. c #707070",
+ "a. c #C8C8C8",
+ "b. c #111111",
+ "c. c #AFAFAF",
+ "d. c #474747",
+ "e. c #565656",
+ "f. c #E3E3E3",
+ "g. c #494949",
+ "h. c #5B5B5B",
+ "i. c #222222",
+ "j. c #353535",
+ "k. c #D9D9D9",
+ "l. c #0A0A0A",
+ "m. c #858585",
+ "n. c #E5E5E5",
+ "o. c #0E0E0E",
+ "p. c #9A9A9A",
+ "q. c #6F6F6F",
+ "r. c #868686",
+ "s. c #060606",
+ "t. c #1E1E1E",
+ "u. c #E8E8E8",
+ "v. c #A5A5A5",
+ "w. c #0D0D0D",
+ "x. c #030303",
+ "y. c #272727",
+ "z. c #131313",
+ "A. c #1F1F1F",
+ "B. c #757575",
+ "C. c #F7F7F7",
+ "D. c #414141",
+ "E. c #080808",
+ "F. c #6B6B6B",
+ "G. c #313131",
+ "H. c #C0C0C0",
+ "I. c #C9C9C9",
+ "J. c #0B0B0B",
+ "K. c #232323",
+ "L. c #434343",
+ "M. c #3D3D3D",
+ "N. c #282828",
+ "O. c #7C7C7C",
+ "P. c #252525",
+ "Q. c #3A3A3A",
+ "R. c #F8F8F8",
+ "S. c #1B1B1B",
+ "T. c #949494",
+ "U. c #3B3B3B",
+ "V. c #242424",
+ "W. c #383838",
+ "X. c #6D6D6D",
+ "Y. c #818181",
+ "Z. c #939393",
+ "`. c #9E9E9E",
+ " + c #929292",
+ ".+ c #7D7D7D",
+ "++ c #ADADAD",
+ "@+ c #DADADA",
+ "#+ c #919191",
+ "$+ c #E1E1E1",
+ "%+ c #BEBEBE",
+ "&+ c #ACACAC",
+ "*+ c #9C9C9C",
+ "=+ c #B3B3B3",
+ "-+ c #808080",
+ ";+ c #A8A8A8",
+ ">+ c #393939",
+ ",+ c #747474",
+ "'+ c #7F7F7F",
+ ")+ c #D1D1D1",
+ "!+ c #606060",
+ "~+ c #5C5C5C",
+ "{+ c #686868",
+ "]+ c #7E7E7E",
+ "^+ c #787878",
+ "/+ c #595959",
+ ". . . + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / . . + + ",
+ ". ( + _ : < [ & } | 1 2 $ 3 4 5 3 6 7 + + 8 9 + . + . ",
+ ". + 0 9 a ( 3 a b c d e c f g h i g j $ k + l m + . + ",
+ "+ 2 8 n o p | ( q r s . # t + + + u ^ v e w + x + + + ",
+ "+ y z . @ A k B 7 n + ( s | p 8 C D 2 E 4 + + F G + . ",
+ "# H I $ J G K L - M N . 2 O P Q R R S T U s s V W j + ",
+ "X Y Z @ o ` _ g ...+.( 4 @.#.m G $.%.7 &.X *.=.-.;.&.",
+ "Q >.C ,.'.} e + ).!.k + . + + . ~.{.> ].x f 7 ^./.k (.",
+ "_.:.4 @ <.[.}.|.1.2.+ + + >.} 4 B + ( @ _ 3.4.5.6.r 7.",
+ "3.8.9.~ 0.+ a.Q b.+ + c.d.#.=.$ |.b #.e.z ^ ; ^. .f.g.",
+ "-.h.+ i.S M + # p j.% n 9.5.k.H l.m.V ^.n.o.M + M p.q.",
+ "7 r.N s.1.R t.<.|.| u.v.~ w.x.E + s y.z.A.B.C.+ 5 D.q ",
+ ").p.2 E.0.9 F.%.O {._ @.+ + i { [ i.G.H.P I.+ s q.} + ",
+ ").p.6 J.R b.K.L.M.A.! b.g.K [.R M k + N.I + + >.O.+ . ",
+ ").8.9.N.P...R R R R E.t.W n.+ Q.R.6 @.| + . + S.+ + . ",
+ "n }.w T.U.B.<.i.@ Y + + U.+ c u V.= B B 7 u.W.c + . + ",
+ "N T.# + }.X.Y.,.8.F.8 Z.[.`. +.+}.4 ++@+O.< ~.+ ( . + ",
+ "d #+1 + _ ~.u.$+b $.y @+| $+%+I.&+k.h W +.9.+ ( . + . ",
+ "w 0 |.*+. >.<.=+++++p a.p -+;+5.k.>+,+@ + . . + . + + ",
+ "q '+9.R.^ I.t b %.I.)+4 $+n.I.,+ .|.+ . . . + . + + + ",
+ ". p !+( + + + + + + E 0. .-+8.f.+ + . . + + . + + + + ",
+ ". ( A ~+{+]+^+l > /+D f.c q . + . . + + . + + + + + + "
+]
diff --git a/sources/pyside6/tests/QtHelp/CMakeLists.txt b/sources/pyside6/tests/QtHelp/CMakeLists.txt
new file mode 100644
index 000000000..422dc51c7
--- /dev/null
+++ b/sources/pyside6/tests/QtHelp/CMakeLists.txt
@@ -0,0 +1,2 @@
+PYSIDE_TEST(help_test.py)
+PYSIDE_TEST(helpsearchengine_test.py)
diff --git a/sources/pyside6/tests/QtHelp/QtHelp.pyproject b/sources/pyside6/tests/QtHelp/QtHelp.pyproject
new file mode 100644
index 000000000..939dca5ba
--- /dev/null
+++ b/sources/pyside6/tests/QtHelp/QtHelp.pyproject
@@ -0,0 +1,4 @@
+{
+ "files": ["help_test.py",
+ "helpsearchengine_test.py"]
+}
diff --git a/sources/pyside6/tests/QtHelp/help_test.py b/sources/pyside6/tests/QtHelp/help_test.py
new file mode 100644
index 000000000..4ded7763c
--- /dev/null
+++ b/sources/pyside6/tests/QtHelp/help_test.py
@@ -0,0 +1,25 @@
+# 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.QtHelp import QHelpEngine
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QHelpEngineCreation(UsesQApplication):
+
+ def testConstructor(self):
+ helpEngine = QHelpEngine('mycollection.qch')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtHelp/helpsearchengine_test.py b/sources/pyside6/tests/QtHelp/helpsearchengine_test.py
new file mode 100644
index 000000000..b25e643f6
--- /dev/null
+++ b/sources/pyside6/tests/QtHelp/helpsearchengine_test.py
@@ -0,0 +1,28 @@
+# 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.QtHelp import QHelpEngineCore, QHelpSearchEngine, QHelpSearchResult
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QHelpSearchEngineTest(UsesQApplication):
+
+ def testQHelpSearchEngine(self):
+ helpEngineCore = QHelpEngineCore('')
+ helpSearchEngine = QHelpSearchEngine(helpEngineCore)
+ helpSearchResult = helpSearchEngine.searchResults(0, 0)
+ self.assertEqual(len(helpSearchResult), 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtHttpServer/CMakeLists.txt b/sources/pyside6/tests/QtHttpServer/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtHttpServer/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtLocation/CMakeLists.txt b/sources/pyside6/tests/QtLocation/CMakeLists.txt
new file mode 100644
index 000000000..b97ac1098
--- /dev/null
+++ b/sources/pyside6/tests/QtLocation/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(location.py)
diff --git a/sources/pyside6/tests/QtLocation/QtLocation.pyproject b/sources/pyside6/tests/QtLocation/QtLocation.pyproject
new file mode 100644
index 000000000..6ca661a96
--- /dev/null
+++ b/sources/pyside6/tests/QtLocation/QtLocation.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["location.py"]
+}
diff --git a/sources/pyside6/tests/QtLocation/location.py b/sources/pyside6/tests/QtLocation/location.py
new file mode 100644
index 000000000..8fbd55f02
--- /dev/null
+++ b/sources/pyside6/tests/QtLocation/location.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
+
+'''Unit test for Location'''
+
+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.QtLocation import QGeoServiceProvider
+
+
+class QLocationTestCase(unittest.TestCase):
+ def test(self):
+ geoServiceProvider = QGeoServiceProvider("none")
+ self.assertEqual(geoServiceProvider.errorString(),
+ 'The geoservices provider none is not supported.')
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtMultimedia/CMakeLists.txt b/sources/pyside6/tests/QtMultimedia/CMakeLists.txt
new file mode 100644
index 000000000..62150eb79
--- /dev/null
+++ b/sources/pyside6/tests/QtMultimedia/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(audio_test.py)
diff --git a/sources/pyside6/tests/QtMultimedia/QtMultimedia.pyproject b/sources/pyside6/tests/QtMultimedia/QtMultimedia.pyproject
new file mode 100644
index 000000000..622ceea3c
--- /dev/null
+++ b/sources/pyside6/tests/QtMultimedia/QtMultimedia.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["audio_test.py"]
+}
diff --git a/sources/pyside6/tests/QtMultimedia/audio_test.py b/sources/pyside6/tests/QtMultimedia/audio_test.py
new file mode 100644
index 000000000..af359e525
--- /dev/null
+++ b/sources/pyside6/tests/QtMultimedia/audio_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
+
+'''Test cases for QHttp'''
+
+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 QByteArray
+from PySide6.QtMultimedia import QAudioBuffer, QAudioFormat, QMediaDevices
+
+
+class testAudioDevices(UsesQApplication):
+
+ def setUp(self):
+ super().setUp()
+ self._devices = []
+ for d in QMediaDevices.audioOutputs():
+ if d:
+ self._devices.append(d)
+
+ def test_list_devices(self):
+ if not self._devices:
+ print("No audio outputs found")
+ return
+
+ for dev_info in self._devices:
+ print("Testing ", dev_info.id())
+ fmt = QAudioFormat()
+ for sample_format in dev_info.supportedSampleFormats():
+ fmt.setSampleFormat(sample_format)
+ fmt.setChannelCount(dev_info.maximumChannelCount())
+ fmt.setSampleRate(dev_info.maximumSampleRate())
+ self.assertTrue(dev_info.isFormatSupported(fmt))
+
+ def test_audiobuffer(self):
+ """PYSIDE-1947: Test QAudioBuffer.data()."""
+ if not self._devices:
+ print("No audio outputs found")
+ return
+ size = 256
+ byte_array = QByteArray(size, '7')
+ buffer = QAudioBuffer(byte_array, self._devices[0].preferredFormat())
+ self.assertEqual(buffer.byteCount(), 256)
+ data = buffer.data()
+ actual_byte_array = QByteArray(bytearray(data))
+ self.assertEqual(byte_array, actual_byte_array)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtMultimediaWidgets/CMakeLists.txt b/sources/pyside6/tests/QtMultimediaWidgets/CMakeLists.txt
new file mode 100644
index 000000000..2fc655f89
--- /dev/null
+++ b/sources/pyside6/tests/QtMultimediaWidgets/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(qmultimediawidgets.py)
diff --git a/sources/pyside6/tests/QtMultimediaWidgets/QtMultimediaWidgets.pyproject b/sources/pyside6/tests/QtMultimediaWidgets/QtMultimediaWidgets.pyproject
new file mode 100644
index 000000000..6627af561
--- /dev/null
+++ b/sources/pyside6/tests/QtMultimediaWidgets/QtMultimediaWidgets.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["qmultimediawidgets.py"]
+}
diff --git a/sources/pyside6/tests/QtMultimediaWidgets/qmultimediawidgets.py b/sources/pyside6/tests/QtMultimediaWidgets/qmultimediawidgets.py
new file mode 100644
index 000000000..968558a13
--- /dev/null
+++ b/sources/pyside6/tests/QtMultimediaWidgets/qmultimediawidgets.py
@@ -0,0 +1,44 @@
+# 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 cases for QtMultimediaWidgets'''
+
+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.QtMultimediaWidgets import QGraphicsVideoItem, QVideoWidget
+from PySide6.QtWidgets import QGraphicsScene, QGraphicsView, QVBoxLayout, QWidget
+from PySide6.QtCore import QTimer
+
+
+class MyWidget(QWidget):
+ def __init__(self):
+ super().__init__()
+
+ layout = QVBoxLayout(self)
+ layout.addWidget(QVideoWidget())
+
+ graphicsScene = QGraphicsScene()
+ graphicsView = QGraphicsView(graphicsScene)
+ graphicsScene.addItem(QGraphicsVideoItem())
+ layout.addWidget(graphicsView)
+
+
+class QMultimediaWidgetsTest(UsesQApplication):
+ def testMultimediaWidgets(self):
+ w = MyWidget()
+ w.show()
+
+ timer = QTimer.singleShot(100, self.app.quit)
+ self.app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtNetwork/CMakeLists.txt b/sources/pyside6/tests/QtNetwork/CMakeLists.txt
new file mode 100644
index 000000000..bff3580a8
--- /dev/null
+++ b/sources/pyside6/tests/QtNetwork/CMakeLists.txt
@@ -0,0 +1,13 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+PYSIDE_TEST(bug_446.py)
+PYSIDE_TEST(bug_1084.py)
+PYSIDE_TEST(accessManager_test.py)
+PYSIDE_TEST(dnslookup_test.py)
+# Qt${QT_MAJOR_VERSION}: QHttp is gone PYSIDE_TEST(http_test.py)
+PYSIDE_TEST(qhostinfo_test.py)
+PYSIDE_TEST(qpassworddigestor_test.py)
+PYSIDE_TEST(tcpserver_test.py)
+PYSIDE_TEST(udpsocket_test.py)
+PYSIDE_TEST(qipv6address_test.py)
diff --git a/sources/pyside6/tests/QtNetwork/QtNetwork.pyproject b/sources/pyside6/tests/QtNetwork/QtNetwork.pyproject
new file mode 100644
index 000000000..0ba3f5947
--- /dev/null
+++ b/sources/pyside6/tests/QtNetwork/QtNetwork.pyproject
@@ -0,0 +1,11 @@
+{
+ "files": ["accessManager_test.py",
+ "bug_1084.py",
+ "bug_446.py",
+ "dnslookup_test.py",
+ "qhostinfo_test.py",
+ "qipv6address_test.py",
+ "qpassworddigestor_test.py",
+ "tcpserver_test.py",
+ "udpsocket_test.py"]
+}
diff --git a/sources/pyside6/tests/QtNetwork/accessManager_test.py b/sources/pyside6/tests/QtNetwork/accessManager_test.py
new file mode 100644
index 000000000..87711b278
--- /dev/null
+++ b/sources/pyside6/tests/QtNetwork/accessManager_test.py
@@ -0,0 +1,55 @@
+# 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 cases for QHttp'''
+
+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 QUrl
+from PySide6.QtNetwork import QNetworkAccessManager, QNetworkReply, QNetworkRequest
+from helper.usesqapplication import UsesQApplication
+from httpd import TestServer
+
+
+class AccessManagerCase(UsesQApplication):
+
+ def setUp(self):
+ super(AccessManagerCase, self).setUp()
+ self.httpd = TestServer()
+ self.httpd.start()
+ self.called = False
+
+ def tearDown(self):
+ super(AccessManagerCase, self).tearDown()
+ if self.httpd:
+ self.httpd.shutdown()
+ self.httpd = None
+
+ def goAway(self):
+ self.httpd.shutdown()
+ self.app.quit()
+ self.httpd = None
+
+ def slot_replyFinished(self, reply):
+ self.assertEqual(type(reply), QNetworkReply)
+ self.called = True
+ self.goAway()
+
+ def testNetworkRequest(self):
+ manager = QNetworkAccessManager()
+ manager.finished.connect(self.slot_replyFinished)
+ port = self.httpd.port()
+ manager.get(QNetworkRequest(QUrl(f"http://127.0.0.1:{port}")))
+ self.app.exec()
+ self.assertTrue(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtNetwork/bug_1084.py b/sources/pyside6/tests/QtNetwork/bug_1084.py
new file mode 100644
index 000000000..515220c80
--- /dev/null
+++ b/sources/pyside6/tests/QtNetwork/bug_1084.py
@@ -0,0 +1,28 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+''' unit test for BUG #1084 '''
+
+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.QtNetwork import QTcpSocket
+
+
+class QTcpSocketTestCase(unittest.TestCase):
+ def setUp(self):
+ self.sock = QTcpSocket()
+ self.sock.connectToHost('127.0.0.1', 25)
+
+ def testIt(self):
+ self.sock.write(bytes('quit', "UTF-8"))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtNetwork/bug_446.py b/sources/pyside6/tests/QtNetwork/bug_446.py
new file mode 100644
index 000000000..f28ddb369
--- /dev/null
+++ b/sources/pyside6/tests/QtNetwork/bug_446.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)
+
+from PySide6.QtNetwork import QHostAddress, QTcpServer, QTcpSocket
+from helper.usesqapplication import UsesQApplication
+
+
+class HttpSignalsCase(UsesQApplication):
+ '''Test case for launching QHttp signals'''
+ DATA = bytes("PySide rocks", "UTF-8")
+
+ def onError(self):
+ self.assertTrue(False)
+
+ def onNewConnection(self):
+ self.serverConnection = self.server.nextPendingConnection()
+ self.serverConnection.errorOccurred.connect(self.onError)
+ self.serverConnection.write(HttpSignalsCase.DATA)
+ self.server.close()
+
+ def onReadReady(self):
+ data = self.client.read(100)
+ self.assertEqual(len(data), len(HttpSignalsCase.DATA))
+ self.assertEqual(data, HttpSignalsCase.DATA)
+ self.done()
+
+ def onClientConnect(self):
+ self.client.readyRead.connect(self.onReadReady)
+
+ def initServer(self):
+ self.server = QTcpServer()
+ self.server.newConnection.connect(self.onNewConnection)
+ self.assertTrue(self.server.listen())
+ self.client = QTcpSocket()
+ self.client.connected.connect(self.onClientConnect)
+ self.client.connectToHost(QHostAddress(QHostAddress.LocalHost), self.server.serverPort())
+
+ def done(self):
+ self.serverConnection.close()
+ self.client.close()
+ self.app.quit()
+
+ def testRun(self):
+ self.initServer()
+ self.app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtNetwork/dnslookup_test.py b/sources/pyside6/tests/QtNetwork/dnslookup_test.py
new file mode 100644
index 000000000..c50a6b5d4
--- /dev/null
+++ b/sources/pyside6/tests/QtNetwork/dnslookup_test.py
@@ -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
+
+'''Test cases for QDnsLookup'''
+
+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 QCoreApplication
+from PySide6.QtNetwork import QDnsLookup
+
+
+class DnsLookupTestCase(unittest.TestCase):
+ '''Test case for QDnsLookup'''
+
+ def setUp(self):
+ self._app = QCoreApplication([])
+ self._lookup = QDnsLookup(QDnsLookup.ANY, 'www.qt.io')
+ self._lookup.finished.connect(self._finished)
+
+ def tearDown(self):
+ del self._lookup
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def _finished(self):
+ if self._lookup.error() == QDnsLookup.NoError:
+ nameRecords = self._lookup.canonicalNameRecords()
+ if nameRecords:
+ print(nameRecords[0].name())
+ self._app.quit()
+
+ def testLookup(self):
+ self._lookup.lookup()
+ self._app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtNetwork/qhostinfo_test.py b/sources/pyside6/tests/QtNetwork/qhostinfo_test.py
new file mode 100644
index 000000000..8d8d2cae4
--- /dev/null
+++ b/sources/pyside6/tests/QtNetwork/qhostinfo_test.py
@@ -0,0 +1,76 @@
+# 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 case for QHostInfo.'''
+
+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 (QCoreApplication, QElapsedTimer, QObject, QThread,
+ Slot, SLOT)
+from PySide6.QtNetwork import QHostInfo
+
+
+HOST = 'www.qt.io'
+
+
+TIMEOUT = 30000
+
+
+class Receiver(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._slot_called = False
+
+ def slot_called(self):
+ return self._slot_called
+
+ @Slot(QHostInfo)
+ def info_received(self, host_info):
+ name = host_info.hostName()
+ if host_info.error() == QHostInfo.NoError:
+ addresses = [a.toString() for a in host_info.addresses()]
+ addresses_str = ', '.join(addresses)
+ print(f'"{name}" resolved to {addresses_str}')
+ else:
+ error = host_info.errorString()
+ print(f'Unable to resolve "{name}": {error}', file=sys.stderr)
+ self._slot_called = True
+
+
+class QHostInfoTest(UsesQApplication):
+ '''Test case for QHostInfo.'''
+ def setUp(self):
+ UsesQApplication.setUp(self)
+ self._timer = QElapsedTimer()
+
+ def testStringBasedLookup(self):
+ receiver = Receiver()
+ self._timer.restart()
+ QHostInfo.lookupHost(HOST, receiver, SLOT('info_received(QHostInfo)'))
+ while not receiver.slot_called() and self._timer.elapsed() < TIMEOUT:
+ QCoreApplication.processEvents()
+ QThread.msleep(10)
+ print(f'String-based: Elapsed {self._timer.elapsed()}ms')
+ self.assertTrue(receiver.slot_called())
+
+ def testCallableLookup(self):
+ receiver = Receiver()
+ self._timer.restart()
+ QHostInfo.lookupHost(HOST, receiver.info_received)
+ while not receiver.slot_called() and self._timer.elapsed() < TIMEOUT:
+ QCoreApplication.processEvents()
+ QThread.msleep(10)
+ print(f'Callable: Elapsed {self._timer.elapsed()}ms')
+ self.assertTrue(receiver.slot_called())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtNetwork/qipv6address_test.py b/sources/pyside6/tests/QtNetwork/qipv6address_test.py
new file mode 100644
index 000000000..67b103d3c
--- /dev/null
+++ b/sources/pyside6/tests/QtNetwork/qipv6address_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
+
+'''Test cases for QIPv6Address'''
+
+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.QtNetwork import QIPv6Address
+
+
+class QIPv6AddressGetItemTest(unittest.TestCase):
+ def testLength(self):
+ ip = QIPv6Address()
+ self.assertEqual(len(ip), 16)
+
+ def testSetItemNegativeIndex(self):
+ ip = QIPv6Address()
+ ip[-1] = 8
+ self.assertEqual(ip[-1], 8)
+
+ def testSetItemLargeIndex(self):
+ ip = QIPv6Address()
+ self.assertRaises(IndexError, ip.__setitem__, 32, 16)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtNetwork/qpassworddigestor_test.py b/sources/pyside6/tests/QtNetwork/qpassworddigestor_test.py
new file mode 100644
index 000000000..db7a90da9
--- /dev/null
+++ b/sources/pyside6/tests/QtNetwork/qpassworddigestor_test.py
@@ -0,0 +1,28 @@
+#!/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
+
+'''Test cases for QPasswordDigestor'''
+
+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 QByteArray, QCryptographicHash
+from PySide6.QtNetwork import QPasswordDigestor
+
+
+class TestPasswordDigestor(unittest.TestCase):
+ def test(self):
+ b = QPasswordDigestor.deriveKeyPbkdf1(QCryptographicHash.Sha1,
+ b'test', b'saltnpep', 10, 20)
+ self.assertEqual(b.size(), 20)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtNetwork/tcpserver_test.py b/sources/pyside6/tests/QtNetwork/tcpserver_test.py
new file mode 100644
index 000000000..845afdfae
--- /dev/null
+++ b/sources/pyside6/tests/QtNetwork/tcpserver_test.py
@@ -0,0 +1,39 @@
+# 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 cases for QTCPServer'''
+
+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.QtNetwork import QTcpServer
+
+
+class ListenDefaultArgsCase(unittest.TestCase):
+ '''Test case for TcpServer.listen with default args'''
+
+ def setUp(self):
+ # Acquire resources
+ self.server = QTcpServer()
+
+ def tearDown(self):
+ # Release resources
+ del self.server
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testDefaultArgs(self):
+ # @bug 108
+ # Default arguments for QTcpServer.listen
+ self.server.listen()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtNetwork/udpsocket_test.py b/sources/pyside6/tests/QtNetwork/udpsocket_test.py
new file mode 100644
index 000000000..950849801
--- /dev/null
+++ b/sources/pyside6/tests/QtNetwork/udpsocket_test.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
+
+'''Test cases for QUdpSocket'''
+
+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 QUrl, QObject, SIGNAL, QCoreApplication, QTimer
+from PySide6.QtNetwork import QUdpSocket, QHostAddress
+
+
+class HttpSignalsCase(unittest.TestCase):
+ '''Test case for bug #124 - readDatagram signature
+
+ QUdpSocket.readDatagram must return a tuple with the datagram, host and
+ port, while receiving only the max payload size.'''
+
+ def setUp(self):
+ # Acquire resources
+ self.called = False
+ self.app = QCoreApplication([])
+
+ self.socket = QUdpSocket()
+
+ self.server = QUdpSocket()
+ self.server.bind(QHostAddress(QHostAddress.LocalHost), 45454)
+
+ def tearDown(self):
+ # Release resources
+ del self.socket
+ del self.server
+ del self.app
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def sendPackage(self):
+ addr = QHostAddress(QHostAddress.LocalHost)
+ self.socket.writeDatagram(bytes('datagram', "UTF-8"), addr, 45454)
+
+ def callback(self):
+ while self.server.hasPendingDatagrams():
+ datagram, host, port = self.server.readDatagram(self.server.pendingDatagramSize())
+ self.called = True
+ self.app.quit()
+
+ def testDefaultArgs(self):
+ # QUdpSocket.readDatagram pythonic return
+ # @bug 124
+ self.server.readyRead.connect(self.callback)
+ self.sendPackage()
+ self.app.exec()
+
+ self.assertTrue(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtNetworkAuth/CMakeLists.txt b/sources/pyside6/tests/QtNetworkAuth/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtNetworkAuth/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtNfc/CMakeLists.txt b/sources/pyside6/tests/QtNfc/CMakeLists.txt
new file mode 100644
index 000000000..fafa0b76b
--- /dev/null
+++ b/sources/pyside6/tests/QtNfc/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(test_nfc.py)
diff --git a/sources/pyside6/tests/QtNfc/QtNfc.pyproject b/sources/pyside6/tests/QtNfc/QtNfc.pyproject
new file mode 100644
index 000000000..680de8ea2
--- /dev/null
+++ b/sources/pyside6/tests/QtNfc/QtNfc.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["test_nfc.py"]
+}
diff --git a/sources/pyside6/tests/QtNfc/test_nfc.py b/sources/pyside6/tests/QtNfc/test_nfc.py
new file mode 100644
index 000000000..a73c52153
--- /dev/null
+++ b/sources/pyside6/tests/QtNfc/test_nfc.py
@@ -0,0 +1,29 @@
+#!/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
+
+'''Test cases for QtNfc'''
+
+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.QtNfc import QNearFieldManager
+
+from helper.usesqapplication import UsesQApplication
+
+
+class TestNfc(UsesQApplication):
+
+ def test(self):
+ manager = QNearFieldManager()
+ print(manager.isEnabled())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtOpenGL/CMakeLists.txt b/sources/pyside6/tests/QtOpenGL/CMakeLists.txt
new file mode 100644
index 000000000..92b4afbac
--- /dev/null
+++ b/sources/pyside6/tests/QtOpenGL/CMakeLists.txt
@@ -0,0 +1,2 @@
+PYSIDE_TEST(qopenglbuffer_test.py)
+PYSIDE_TEST(qopenglwindow_test.py)
diff --git a/sources/pyside6/tests/QtOpenGL/QtOpenGL.pyproject b/sources/pyside6/tests/QtOpenGL/QtOpenGL.pyproject
new file mode 100644
index 000000000..9a19a32b6
--- /dev/null
+++ b/sources/pyside6/tests/QtOpenGL/QtOpenGL.pyproject
@@ -0,0 +1,4 @@
+{
+ "files": ["qopenglbuffer_test.py",
+ "qopenglwindow_test.py"]
+}
diff --git a/sources/pyside6/tests/QtOpenGL/qopenglbuffer_test.py b/sources/pyside6/tests/QtOpenGL/qopenglbuffer_test.py
new file mode 100644
index 000000000..e4ff6feb4
--- /dev/null
+++ b/sources/pyside6/tests/QtOpenGL/qopenglbuffer_test.py
@@ -0,0 +1,77 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Unit tests for QOpenGLBuffer'''
+
+import ctypes
+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.QtGui import QOffscreenSurface, QOpenGLContext, QSurface, QWindow
+from PySide6.QtOpenGL import QOpenGLBuffer
+
+
+def createSurface(surfaceClass):
+ if surfaceClass == QSurface.Window:
+ window = QWindow()
+ window.setSurfaceType(QWindow.OpenGLSurface)
+ window.setGeometry(0, 0, 10, 10)
+ window.create()
+ return window
+ elif surfaceClass == QSurface.Offscreen:
+ # Create a window and get the format from that. For example, if an EGL
+ # implementation provides 565 and 888 configs for PBUFFER_BIT but only
+ # 888 for WINDOW_BIT, we may end up with a pbuffer surface that is
+ # incompatible with the context since it could choose the 565 while the
+ # window and the context uses a config with 888.
+ format = QSurfaceFormat
+ if format.redBufferSize() == -1:
+ window = QWindow()
+ window.setSurfaceType(QWindow.OpenGLSurface)
+ window.setGeometry(0, 0, 10, 10)
+ window.create()
+ format = window.format()
+ offscreenSurface = QOffscreenSurface()
+ offscreenSurface.setFormat(format)
+ offscreenSurface.create()
+ return offscreenSurface
+ return 0
+
+
+class QOpenGLBufferTest(UsesQApplication):
+ def testBufferCreate(self):
+ surface = createSurface(QSurface.Window)
+ ctx = QOpenGLContext()
+ ctx.create()
+ ctx.makeCurrent(surface)
+
+ buf = QOpenGLBuffer()
+
+ self.assertTrue(not buf.isCreated())
+
+ self.assertTrue(buf.create())
+ self.assertTrue(buf.isCreated())
+
+ self.assertEqual(buf.type(), QOpenGLBuffer.VertexBuffer)
+
+ buf.bind()
+ buf.allocate(128)
+ self.assertEqual(buf.size(), 128)
+
+ buf.release()
+
+ buf.destroy()
+ self.assertTrue(not buf.isCreated())
+
+ ctx.doneCurrent()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtOpenGL/qopenglwindow_test.py b/sources/pyside6/tests/QtOpenGL/qopenglwindow_test.py
new file mode 100644
index 000000000..3e6bc4c9d
--- /dev/null
+++ b/sources/pyside6/tests/QtOpenGL/qopenglwindow_test.py
@@ -0,0 +1,96 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Unit test for QOpenGLContext, QOpenGLTexture, QOpenGLWindow and related classes'''
+
+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 QSize, QTimer, Qt
+from PySide6.QtGui import (QColor, QGuiApplication, QImage, QOpenGLContext,
+ QSurfaceFormat)
+from PySide6.QtOpenGL import QOpenGLTexture, QOpenGLWindow
+
+
+try:
+ from OpenGL import GL
+ from PySide6.QtOpenGL import QOpenGLVersionProfile, QOpenGLVersionFunctionsFactory
+except ImportError:
+ print("Skipping test due to missing OpenGL module/GLES only build")
+ sys.exit(0)
+
+
+class OpenGLWindow(QOpenGLWindow):
+ def __init__(self):
+ super().__init__()
+
+ self.m_functions = None
+ self.m_texture = None
+ self.visibleChanged.connect(self.slotVisibleChanged)
+
+ def slotVisibleChanged(self, visible):
+ if not visible and self.m_texture is not None and self.context().makeCurrent(self):
+ self.m_texture = None
+ self.context().doneCurrent()
+
+ def initializeGL(self):
+ profile = QOpenGLVersionProfile()
+ profile.setVersion(1, 3)
+ profile.setProfile(QSurfaceFormat.CompatibilityProfile)
+ self.m_functions = QOpenGLVersionFunctionsFactory.get(profile)
+ self.m_functions.initializeOpenGLFunctions()
+
+ print("GL_MAX_LIGHTS=", self.m_functions.glGetIntegerv(GL.GL_MAX_LIGHTS))
+ image = QImage(QSize(200, 200), QImage.Format_RGBA8888)
+ image.fill(QColor(Qt.red))
+ self.m_texture = QOpenGLTexture(image)
+
+ def paintGL(self):
+ self.m_functions.glMatrixMode(GL.GL_MODELVIEW)
+ self.m_functions.glLoadIdentity()
+
+ self.m_functions.glMatrixMode(GL.GL_PROJECTION)
+ self.m_functions.glLoadIdentity()
+ self.m_functions.glOrtho(0, 1, 1, 0, -1, 1)
+
+ self.m_functions.glClear(GL.GL_COLOR_BUFFER_BIT)
+ self.m_functions.glEnable(GL.GL_TEXTURE_2D)
+ self.m_texture.bind()
+
+ d = 0.5
+ self.m_functions.glBegin(GL.GL_QUADS)
+ self.m_functions.glTexCoord2f(0, 0)
+ self.m_functions.glVertex2f(0, 0)
+ self.m_functions.glTexCoord2f(d, 0)
+ self.m_functions.glVertex2f(d, 0)
+ self.m_functions.glTexCoord2f(d, d)
+ self.m_functions.glVertex2f(d, d)
+ self.m_functions.glTexCoord2f(0, d)
+ self.m_functions.glVertex2f(0, d)
+ self.m_functions.glEnd()
+ self.m_texture.release()
+
+ def resizeGL(self, w, h):
+ self.m_functions.glViewport(0, 0, self.width(), self.height())
+
+
+class QOpenGLWindowTest(UsesQApplication):
+ # On macOS, glClear(), glViewport() are rejected due to GLbitfield/GLint not being resolved properly
+ def test(self):
+ openGlWindow = OpenGLWindow()
+ openGlWindow.resize(640, 480)
+ openGlWindow.show()
+ QTimer.singleShot(100, openGlWindow.close)
+ self.app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtOpenGLWidgets/CMakeLists.txt b/sources/pyside6/tests/QtOpenGLWidgets/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtOpenGLWidgets/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtPdf/CMakeLists.txt b/sources/pyside6/tests/QtPdf/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtPdf/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtPdfWidgets/CMakeLists.txt b/sources/pyside6/tests/QtPdfWidgets/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtPdfWidgets/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtPositioning/CMakeLists.txt b/sources/pyside6/tests/QtPositioning/CMakeLists.txt
new file mode 100644
index 000000000..b9f7631b1
--- /dev/null
+++ b/sources/pyside6/tests/QtPositioning/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(positioning.py)
diff --git a/sources/pyside6/tests/QtPositioning/QtPositioning.pyproject b/sources/pyside6/tests/QtPositioning/QtPositioning.pyproject
new file mode 100644
index 000000000..e90ccd8a2
--- /dev/null
+++ b/sources/pyside6/tests/QtPositioning/QtPositioning.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["positioning.py"]
+}
diff --git a/sources/pyside6/tests/QtPositioning/positioning.py b/sources/pyside6/tests/QtPositioning/positioning.py
new file mode 100644
index 000000000..d8e670247
--- /dev/null
+++ b/sources/pyside6/tests/QtPositioning/positioning.py
@@ -0,0 +1,28 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Unit test for Positioning'''
+
+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.QtPositioning import QGeoPositionInfoSource
+
+
+class QPositioningTestCase(unittest.TestCase):
+ def test(self):
+ source = QGeoPositionInfoSource.createDefaultSource(None)
+ self.assertTrue(source is not None)
+ name = source.sourceName()
+ print(f"QtPositioning source: {name}")
+ self.assertTrue(name)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtPrintSupport/CMakeLists.txt b/sources/pyside6/tests/QtPrintSupport/CMakeLists.txt
new file mode 100644
index 000000000..510c5fe0b
--- /dev/null
+++ b/sources/pyside6/tests/QtPrintSupport/CMakeLists.txt
@@ -0,0 +1,2 @@
+PYSIDE_TEST(bug_500.py)
+PYSIDE_TEST(returnquadruplesofnumbers_test.py)
diff --git a/sources/pyside6/tests/QtPrintSupport/QtPrintSupport.pyproject b/sources/pyside6/tests/QtPrintSupport/QtPrintSupport.pyproject
new file mode 100644
index 000000000..dbc9641d7
--- /dev/null
+++ b/sources/pyside6/tests/QtPrintSupport/QtPrintSupport.pyproject
@@ -0,0 +1,4 @@
+{
+ "files": ["bug_500.py",
+ "returnquadruplesofnumbers_test.py"]
+}
diff --git a/sources/pyside6/tests/QtPrintSupport/bug_500.py b/sources/pyside6/tests/QtPrintSupport/bug_500.py
new file mode 100644
index 000000000..1ba5b35e2
--- /dev/null
+++ b/sources/pyside6/tests/QtPrintSupport/bug_500.py
@@ -0,0 +1,25 @@
+#!/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.QtPrintSupport import QPrintDialog
+from helper.usesqapplication import UsesQApplication
+
+
+class NeverDiesTest(UsesQApplication):
+
+ def testIt(self):
+ QPrintDialog()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtPrintSupport/returnquadruplesofnumbers_test.py b/sources/pyside6/tests/QtPrintSupport/returnquadruplesofnumbers_test.py
new file mode 100644
index 000000000..97b3505da
--- /dev/null
+++ b/sources/pyside6/tests/QtPrintSupport/returnquadruplesofnumbers_test.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 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.QtGui import QTextCursor
+from PySide6.QtPrintSupport import QPrinter, QPrinterInfo
+from PySide6.QtWidgets import QLayout, QWidget, QGraphicsLayout, QGraphicsLayoutItem
+
+from helper.usesqapplication import UsesQApplication
+
+
+class Layout(QLayout):
+ def __init__(self):
+ super().__init__()
+
+
+class GraphicsLayout(QGraphicsLayout):
+ def __init__(self):
+ super().__init__()
+
+
+class GraphicsLayoutItem(QGraphicsLayoutItem):
+ def __init__(self):
+ super().__init__()
+
+
+class ReturnsQuadruplesOfNumbers(UsesQApplication):
+ def compareTuples(self, ta, tb):
+ for va, vb in zip(ta, tb):
+ if round(va) != round(vb):
+ return False
+ return True
+
+ def testQGraphicsLayoutGetContentsMargins(self):
+ obj = GraphicsLayout()
+ values = (10.0, 20.0, 30.0, 40.0)
+ obj.setContentsMargins(*values)
+ self.assertTrue(self.compareTuples(obj.getContentsMargins(), values))
+
+ def testQGraphicsLayoutItemGetContentsMargins(self):
+ obj = GraphicsLayoutItem()
+ self.assertTrue(self.compareTuples(obj.getContentsMargins(), (0.0, 0.0, 0.0, 0.0)))
+
+ def testQLayoutGetContentsMargins(self):
+ obj = Layout()
+ values = (10, 20, 30, 40)
+ obj.setContentsMargins(*values)
+ self.assertTrue(self.compareTuples(obj.getContentsMargins(), values))
+
+ def testQTextCursorSelectedTableCells(self):
+ obj = QTextCursor()
+ self.assertEqual(obj.selectedTableCells(), (-1, -1, -1, -1))
+
+
+if __name__ == "__main__":
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtQml/CMakeLists.txt b/sources/pyside6/tests/QtQml/CMakeLists.txt
new file mode 100644
index 000000000..30bf7e786
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/CMakeLists.txt
@@ -0,0 +1,37 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+PYSIDE_TEST(bug_451.py)
+PYSIDE_TEST(bug_456.py)
+PYSIDE_TEST(bug_557.py)
+PYSIDE_TEST(bug_726.py)
+PYSIDE_TEST(bug_814.py)
+PYSIDE_TEST(bug_825_old.py)
+PYSIDE_TEST(bug_825.py)
+PYSIDE_TEST(bug_847.py)
+PYSIDE_TEST(bug_915.py)
+PYSIDE_TEST(bug_926.py)
+PYSIDE_TEST(bug_951.py)
+PYSIDE_TEST(bug_995.py)
+PYSIDE_TEST(bug_997.py)
+PYSIDE_TEST(bug_1029.py)
+PYSIDE_TEST(groupedproperty.py)
+PYSIDE_TEST(listproperty.py)
+PYSIDE_TEST(qmlregistertype_test.py)
+PYSIDE_TEST(qqmlapplicationengine_test.py)
+PYSIDE_TEST(qqmlnetwork_test.py)
+PYSIDE_TEST(qqmlcomponent_test.py)
+PYSIDE_TEST(qquickview_test.py)
+PYSIDE_TEST(connect_python_qml.py)
+PYSIDE_TEST(registerattached.py)
+PYSIDE_TEST(registerextended.py)
+PYSIDE_TEST(registerparserstatus.py)
+PYSIDE_TEST(registertype.py)
+PYSIDE_TEST(registerforeign.py)
+PYSIDE_TEST(registerqmlfile.py)
+PYSIDE_TEST(registeruncreatabletype.py)
+PYSIDE_TEST(registersingletontype.py)
+PYSIDE_TEST(javascript_exceptions.py)
+PYSIDE_TEST(qqmlincubator_incubateWhile.py)
+PYSIDE_TEST(qquickitem_grabToImage.py)
+PYSIDE_TEST(signal_arguments.py)
diff --git a/sources/pyside6/tests/QtQml/ModuleType.qml b/sources/pyside6/tests/QtQml/ModuleType.qml
new file mode 100644
index 000000000..d7e5e653c
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/ModuleType.qml
@@ -0,0 +1,8 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQml
+
+QtObject {
+ objectName: "moduleType"
+}
diff --git a/sources/pyside6/tests/QtQml/QtQml.pyproject b/sources/pyside6/tests/QtQml/QtQml.pyproject
new file mode 100644
index 000000000..5a05c71a1
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/QtQml.pyproject
@@ -0,0 +1,65 @@
+{
+ "files": ["ModuleType.qml",
+ "bug_1029.py",
+ "bug_1029.qml",
+ "bug_451.py",
+ "bug_451.qml",
+ "bug_456.py",
+ "bug_456.qml",
+ "bug_557.py",
+ "bug_726.py",
+ "bug_726.qml",
+ "bug_814.py",
+ "bug_814.qml",
+ "bug_825.py",
+ "bug_825.qml",
+ "bug_847.py",
+ "bug_847.qml",
+ "bug_915.py",
+ "bug_926.py",
+ "bug_926.qml",
+ "bug_951.py",
+ "bug_951.qml",
+ "bug_995.py",
+ "bug_995.qml",
+ "bug_997.py",
+ "bug_997.qml",
+ "connect_python_qml.py",
+ "connect_python_qml.qml",
+ "groupedproperty.py",
+ "groupedproperty.qml",
+ "hw.qml",
+ "javascript_exceptions.py",
+ "javascript_exceptions.qml",
+ "listproperty.py",
+ "qqmlapplicationengine.qml",
+ "qqmlapplicationengine_test.py",
+ "qqmlincubator_incubateWhile.py",
+ "qqmlincubator_incubateWhile.qml",
+ "qqmlincubator_incubateWhile_component.qml",
+ "qqmlnetwork_test.py",
+ "qquickitem_grabToImage.py",
+ "qquickitem_grabToImage.qml",
+ "qquickview_test.py",
+ "registerattached.py",
+ "registerattached.qml",
+ "registerextended.py",
+ "registerextended.qml",
+ "registerforeign.py",
+ "registerforeign.qml",
+ "registerparserstatus.py",
+ "registerparserstatus.qml",
+ "registerqmlfile.py",
+ "registersingletontype.py",
+ "registersingletontype.qml",
+ "registertype.py",
+ "registertype.qml",
+ "registeruncreatable.qml",
+ "registeruncreatabletype.py",
+ "signal_arguments.py",
+ "signal_arguments.qml",
+ "signal_types.py",
+ "signal_types.qml",
+ "view.qml",
+ "viewmodel.qml"]
+}
diff --git a/sources/pyside6/tests/QtQml/bug_1029.py b/sources/pyside6/tests/QtQml/bug_1029.py
new file mode 100644
index 000000000..69ca5c18d
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_1029.py
@@ -0,0 +1,43 @@
+# 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 QUrl
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import qmlRegisterType
+from PySide6.QtQuick import QQuickView, QQuickItem
+
+
+def register_qml_types():
+ class TestClass(QQuickItem):
+ def __init__(self, parent=None):
+ QQuickItem.__init__(self, parent)
+
+ qmlRegisterType(TestClass, "UserTypes", 1, 0, "TestClass")
+
+
+def main():
+ app = QGuiApplication([])
+
+ # reg qml types here
+ register_qml_types()
+
+ # force gc to run
+ gc.collect()
+
+ view = QQuickView()
+ url = QUrl(__file__.replace(".py", ".qml"))
+ view.setSource(url)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/sources/pyside6/tests/QtQml/bug_1029.qml b/sources/pyside6/tests/QtQml/bug_1029.qml
new file mode 100644
index 000000000..e4e95f865
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_1029.qml
@@ -0,0 +1,18 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import UserTypes 1.0
+
+Rectangle
+{
+ width: 200
+ height: 200
+
+ color: "#ff0000"
+
+ TestClass
+ {
+
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/bug_451.py b/sources/pyside6/tests/QtQml/bug_451.py
new file mode 100644
index 000000000..d81a99d94
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_451.py
@@ -0,0 +1,93 @@
+# 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 bug 451: http://bugs.openbossa.org/show_bug.cgi?id=451
+
+An archive of said bug:
+https://srinikom.github.io/pyside-bz-archive/451.html
+'''
+
+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.helper import quickview_errorstring
+
+from PySide6.QtCore import QObject, QUrl, Property
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQuick import QQuickView
+from PySide6.QtQml import QmlElement
+
+
+QML_IMPORT_NAME = "test.PythonObject"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class PythonObject(QObject):
+ def __init__(self):
+ super().__init__(None)
+ self._called = ""
+ self._arg1 = None
+ self._arg2 = None
+
+ def setCalled(self, v):
+ self._called = v
+
+ def setArg1(self, v):
+ self._arg1 = v
+
+ def setArg2(self, v):
+ self._arg2 = v
+
+ def getCalled(self):
+ return self._called
+
+ def getArg1(self):
+ return self._arg1
+
+ def getArg2(self):
+ return self._arg2
+
+ called = Property(str, getCalled, setCalled)
+ arg1 = Property(int, getArg1, setArg1)
+ arg2 = Property('QVariant', getArg2, setArg2)
+
+
+class TestBug(unittest.TestCase):
+ def testQMLFunctionCall(self):
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+
+ obj = PythonObject()
+ view.setInitialProperties({"python": obj})
+ file = Path(__file__).resolve().parent / 'bug_451.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ root = view.rootObject()
+ self.assertTrue(root, quickview_errorstring(view))
+ root.simpleFunction()
+ self.assertEqual(obj.called, "simpleFunction")
+
+ root.oneArgFunction(42)
+ self.assertEqual(obj.called, "oneArgFunction")
+ self.assertEqual(obj.arg1, 42)
+
+ root.twoArgFunction(10, app)
+ self.assertEqual(obj.called, "twoArgFunction")
+ self.assertEqual(obj.arg1, 10)
+ self.assertEqual(obj.arg2, app)
+
+ rvalue = root.returnFunction()
+ self.assertEqual(obj.called, "returnFunction")
+ self.assertEqual(rvalue, 42)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/bug_451.qml b/sources/pyside6/tests/QtQml/bug_451.qml
new file mode 100644
index 000000000..0867b861f
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_451.qml
@@ -0,0 +1,31 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import test.PythonObject 1.0
+
+Rectangle {
+ id: page
+ required property PythonObject python
+
+ function simpleFunction() {
+ python.called = "simpleFunction"
+ }
+
+ function oneArgFunction(x) {
+ python.called = "oneArgFunction"
+ python.arg1 = x
+ }
+
+ function twoArgFunction(x, y) {
+ python.called = "twoArgFunction"
+ python.arg1 = x
+ python.arg2 = y
+ }
+
+ function returnFunction() {
+ python.called = "returnFunction"
+ return 42
+ }
+
+}
diff --git a/sources/pyside6/tests/QtQml/bug_456.py b/sources/pyside6/tests/QtQml/bug_456.py
new file mode 100644
index 000000000..7743ee3fd
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_456.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(False)
+
+from helper.helper import quickview_errorstring
+from helper.timedqguiapplication import TimedQGuiApplication
+from PySide6.QtCore import QObject, QTimer, QUrl, Property, Slot
+from PySide6.QtQuick import QQuickView
+from PySide6.QtQml import QmlElement
+
+QML_IMPORT_NAME = "test.RotateValue"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class RotateValue(QObject):
+ def __init__(self):
+ super().__init__()
+
+ @Slot(result=int)
+ def val(self):
+ return 100
+
+ def setRotation(self, v):
+ self._rotation = v
+
+ def getRotation(self):
+ return self._rotation
+
+ rotation = Property(int, getRotation, setRotation)
+
+
+class TestConnectionWithInvalidSignature(TimedQGuiApplication):
+
+ def testSlotRetur(self):
+ view = QQuickView()
+ rotatevalue = RotateValue()
+
+ timer = QTimer()
+ timer.start(2000)
+
+ view.setInitialProperties({"rotatevalue": rotatevalue})
+ file = Path(__file__).resolve().parent / 'bug_456.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ root = view.rootObject()
+ self.assertTrue(root, quickview_errorstring(view))
+ button = root.findChild(QObject, "buttonMouseArea")
+ view.show()
+ button.entered.emit()
+ self.assertEqual(rotatevalue.rotation, 100)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/bug_456.qml b/sources/pyside6/tests/QtQml/bug_456.qml
new file mode 100644
index 000000000..092cca325
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_456.qml
@@ -0,0 +1,36 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import test.RotateValue 1.0
+
+Rectangle {
+ id: page
+
+ width: 500; height: 200
+ color: "lightgray"
+ required property RotateValue rotatevalue
+
+ Rectangle {
+ id: button
+ width: 150; height: 40
+ color: "darkgray"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 120
+ MouseArea {
+ id: buttonMouseArea
+ objectName: "buttonMouseArea"
+ anchors.fill: parent
+ onEntered: {
+ rotatevalue.rotation = rotatevalue.val()
+ }
+ }
+ Text {
+ id: buttonText
+ text: "Press me!"
+ anchors.horizontalCenter: button.horizontalCenter
+ anchors.verticalCenter: button.verticalCenter
+ font.pointSize: 16;
+ }
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/bug_557.py b/sources/pyside6/tests/QtQml/bug_557.py
new file mode 100644
index 000000000..eb43973f6
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_557.py
@@ -0,0 +1,28 @@
+# 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.helper import adjust_filename
+
+from PySide6.QtCore import QUrl
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import QQmlEngine, QQmlComponent
+
+app = QGuiApplication(sys.argv)
+
+engine = QQmlEngine()
+component = QQmlComponent(engine)
+
+# This should segfault if the QDeclarativeComponent has not QQmlEngine
+file = Path(__file__).resolve().parent / 'foo.qml'
+assert (not file.is_file())
+component.loadUrl(QUrl.fromLocalFile(file))
+
diff --git a/sources/pyside6/tests/QtQml/bug_726.py b/sources/pyside6/tests/QtQml/bug_726.py
new file mode 100644
index 000000000..56c1e70f1
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_726.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(False)
+
+from helper.helper import quickview_errorstring
+from helper.timedqguiapplication import TimedQGuiApplication
+from PySide6.QtCore import QObject, QUrl, Slot
+from PySide6.QtQuick import QQuickView
+from PySide6.QtQml import QmlElement
+
+QML_IMPORT_NAME = "test.ProxyObject"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class ProxyObject(QObject):
+ def __init__(self):
+ super().__init__()
+ self._o = None
+ self._receivedName = ""
+
+ @Slot(result='QObject*')
+ def getObject(self):
+ if self._o:
+ return self._o
+
+ self._o = QObject()
+ self._o.setObjectName("PySideObject")
+ return self._o
+
+ @Slot(str)
+ def receivedObject(self, name):
+ self._receivedName = name
+
+
+class TestConnectionWithInvalidSignature(TimedQGuiApplication):
+
+ def testSlotRetur(self):
+ view = QQuickView()
+ proxy = ProxyObject()
+
+ view.setInitialProperties({"proxy": proxy})
+ file = Path(__file__).resolve().parent / 'bug_726.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ root = view.rootObject()
+ self.assertTrue(root, quickview_errorstring(view))
+ button = root.findChild(QObject, "buttonMouseArea")
+ view.show()
+ button.entered.emit()
+ self.assertEqual(proxy._receivedName, "PySideObject")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/bug_726.qml b/sources/pyside6/tests/QtQml/bug_726.qml
new file mode 100644
index 000000000..f80c9cdda
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_726.qml
@@ -0,0 +1,36 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import test.ProxyObject 1.0
+
+Rectangle {
+ id: page
+
+ width: 500; height: 200
+ color: "lightgray"
+ required property ProxyObject proxy
+
+ Rectangle {
+ id: button
+ width: 150; height: 40
+ color: "darkgray"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 120
+ MouseArea {
+ id: buttonMouseArea
+ objectName: "buttonMouseArea"
+ anchors.fill: parent
+ onEntered: {
+ proxy.receivedObject(proxy.getObject().objectName)
+ }
+ }
+ Text {
+ id: buttonText
+ text: "Press me!"
+ anchors.horizontalCenter: button.horizontalCenter
+ anchors.verticalCenter: button.verticalCenter
+ font.pointSize: 16;
+ }
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/bug_814.py b/sources/pyside6/tests/QtQml/bug_814.py
new file mode 100644
index 000000000..0e7858b6c
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_814.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2011 Thomas Perl <m@thp.io>
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+# Test case for PySide bug 814
+# http://bugs.pyside.org/show_bug.cgi?id=814
+# archive:
+# https://srinikom.github.io/pyside-bz-archive/814.html
+# 2011-04-08 Thomas Perl <m@thp.io>
+# Released under the same terms as PySide itself
+
+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.helper import quickview_errorstring
+from helper.timedqguiapplication import TimedQGuiApplication
+
+from PySide6.QtCore import QUrl, QAbstractListModel, QModelIndex, Qt
+from PySide6.QtQuick import QQuickView
+from PySide6.QtQml import QmlElement
+
+QML_IMPORT_NAME = "test.ListModel"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class ListModel(QAbstractListModel):
+ def __init__(self):
+ super().__init__()
+
+ def roleNames(self):
+ return {Qt.DisplayRole: b'pysideModelData'}
+
+ def rowCount(self, parent=QModelIndex()):
+ return 3
+
+ def data(self, index, role):
+ if index.isValid() and role == Qt.DisplayRole:
+ return 'blubb'
+ return None
+
+
+class TestBug814(TimedQGuiApplication):
+ def testAbstractItemModelTransferToQML(self):
+ view = QQuickView()
+ model = ListModel()
+ view.setInitialProperties({"pythonModel": model})
+ file = Path(__file__).resolve().parent / 'bug_814.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ root = view.rootObject()
+ self.assertTrue(root, quickview_errorstring(view))
+ view.show()
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtQml/bug_814.qml b/sources/pyside6/tests/QtQml/bug_814.qml
new file mode 100644
index 000000000..4331e424f
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_814.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import test.ListModel 1.0
+
+ListView {
+ required property ListModel pythonModel
+ width: 300; height: 300
+ delegate: Text { text: pysideModelData }
+ model: pythonModel
+}
+
diff --git a/sources/pyside6/tests/QtQml/bug_825.py b/sources/pyside6/tests/QtQml/bug_825.py
new file mode 100644
index 000000000..a8bd304ec
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_825.py
@@ -0,0 +1,80 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+"""
+This is the corrected version for Python 3.
+Unfortunately, this touches a Python 3.8 error that was fixed 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 helper.helper import quickview_errorstring
+
+from PySide6.QtCore import Qt, QUrl, QTimer
+from PySide6.QtGui import QGuiApplication, QPen
+from PySide6.QtWidgets import QGraphicsItem
+from PySide6.QtQml import qmlRegisterType
+from PySide6.QtQuick import QQuickView, QQuickItem, QQuickPaintedItem
+
+paintCalled = False
+
+
+class MetaA(type):
+ pass
+
+
+class A(object, metaclass=MetaA):
+ pass
+
+
+MetaB = type(QQuickPaintedItem)
+B = QQuickPaintedItem
+
+
+class MetaC(MetaA, MetaB):
+ pass
+
+
+class C(A, B, metaclass=MetaC):
+ pass
+
+
+class Bug825 (C):
+ def __init__(self, parent=None):
+ QQuickPaintedItem.__init__(self, parent)
+
+ def paint(self, painter):
+ global paintCalled
+ pen = QPen(Qt.black, 2)
+ painter.setPen(pen)
+ painter.drawPie(self.boundingRect(), 0, 128)
+ paintCalled = True
+
+
+class TestBug825 (unittest.TestCase):
+ def testIt(self):
+ global paintCalled
+ app = QGuiApplication([])
+ qmlRegisterType(Bug825, 'bugs', 1, 0, 'Bug825')
+ self.assertRaises(TypeError, qmlRegisterType, A, 'bugs', 1, 0, 'A')
+
+ view = QQuickView()
+ file = Path(__file__).resolve().parent / 'bug_825.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+ view.show()
+ QTimer.singleShot(250, view.close)
+ app.exec()
+ self.assertTrue(paintCalled)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/bug_825.qml b/sources/pyside6/tests/QtQml/bug_825.qml
new file mode 100644
index 000000000..77c6b5014
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_825.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import bugs 1.0
+
+Item {
+ width: 300; height: 200
+
+ Bug825 {
+ anchors.fill: parent
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/bug_825_old.py b/sources/pyside6/tests/QtQml/bug_825_old.py
new file mode 100644
index 000000000..c44fa75f4
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_825_old.py
@@ -0,0 +1,80 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+"""
+This is the now incorrect old version from Python 2.
+It happens to work in another way and will be retained.
+"""
+
+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.helper import quickview_errorstring
+
+from PySide6.QtCore import Qt, QUrl, QTimer
+from PySide6.QtGui import QGuiApplication, QPen
+from PySide6.QtWidgets import QGraphicsItem
+from PySide6.QtQml import qmlRegisterType
+from PySide6.QtQuick import QQuickView, QQuickItem, QQuickPaintedItem
+
+paintCalled = False
+
+
+class MetaA(type):
+ pass
+
+
+class A(object):
+ __metaclass__ = MetaA
+
+
+MetaB = type(QQuickPaintedItem)
+B = QQuickPaintedItem
+
+
+class MetaC(MetaA, MetaB):
+ pass
+
+
+class C(A, B):
+ __metaclass__ = MetaC
+
+
+class Bug825 (C):
+ def __init__(self, parent=None):
+ QQuickPaintedItem.__init__(self, parent)
+
+ def paint(self, painter):
+ global paintCalled
+ pen = QPen(Qt.black, 2)
+ painter.setPen(pen)
+ painter.drawPie(self.boundingRect(), 0, 128)
+ paintCalled = True
+
+
+class TestBug825 (unittest.TestCase):
+ def testIt(self):
+ global paintCalled
+ app = QGuiApplication([])
+ qmlRegisterType(Bug825, 'bugs', 1, 0, 'Bug825')
+ self.assertRaises(TypeError, qmlRegisterType, A, 'bugs', 1, 0, 'A')
+
+ view = QQuickView()
+ file = Path(__file__).resolve().parent / 'bug_825.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+ view.show()
+ QTimer.singleShot(250, view.close)
+ app.exec()
+ self.assertTrue(paintCalled)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/bug_847.py b/sources/pyside6/tests/QtQml/bug_847.py
new file mode 100644
index 000000000..947eb494e
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_847.py
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2011 Thomas Perl <m@thp.io>
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+# Testcase for PySide bug 847
+# Released under the same terms as PySide itself
+# 2011-05-04 Thomas Perl <m@thp.io>
+
+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.helper import quickview_errorstring
+from helper.usesqapplication import UsesQApplication
+
+from PySide6.QtCore import Slot, Signal, QUrl, QTimer, QCoreApplication
+from PySide6.QtQuick import QQuickView
+
+
+class View(QQuickView):
+ def __init__(self):
+ super().__init__()
+
+ called = Signal(int, int)
+
+ @Slot(int, int)
+ def blubb(self, x, y):
+ self.called.emit(x, y)
+
+
+class TestQML(UsesQApplication):
+ def done(self, x, y):
+ self._sucess = True
+ self.app.quit()
+ print("done called")
+
+ def testPythonSlot(self):
+ self._sucess = False
+ view = View()
+
+ # Connect first, then set the property.
+ view.called.connect(self.done)
+ file = Path(__file__).resolve().parent / 'bug_847.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ while view.status() == QQuickView.Loading:
+ self.app.processEvents()
+ self.assertEqual(view.status(), QQuickView.Ready)
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+ view.rootObject().setProperty('pythonObject', view)
+
+ view.show()
+ while not view.isExposed():
+ self.app.processEvents()
+
+ # Essentially a timeout in case method invocation fails.
+ QTimer.singleShot(30000, QCoreApplication.instance().quit)
+ self.app.exec()
+ self.assertTrue(self._sucess)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtQml/bug_847.qml b/sources/pyside6/tests/QtQml/bug_847.qml
new file mode 100644
index 000000000..18efd80ce
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_847.qml
@@ -0,0 +1,37 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+
+Rectangle {
+ width: 500
+ height: 500
+ color: 'red'
+
+ property variant pythonObject: undefined
+
+ Text {
+ anchors.centerIn: parent
+ text: 'click me'
+ color: 'white'
+ }
+
+ onPythonObjectChanged: {
+ if (pythonObject) {
+ // Delay execution of method invocation, so that the event loop has a chance to start,
+ // which will subsequently be stopped by the method.
+ timer.start()
+ }
+ }
+
+ Timer {
+ id: timer
+ interval: 100; running: false;
+ onTriggered: {
+ if (pythonObject) {
+ pythonObject.blubb(42, 84)
+ }
+ }
+ }
+}
+
diff --git a/sources/pyside6/tests/QtQml/bug_915.py b/sources/pyside6/tests/QtQml/bug_915.py
new file mode 100644
index 000000000..3095eba2a
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_915.py
@@ -0,0 +1,40 @@
+#!/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 helper.timedqguiapplication import TimedQGuiApplication
+
+from PySide6.QtQuick import QQuickView, QQuickItem
+
+
+class TestBug915(TimedQGuiApplication):
+ def testReturnPolicy(self):
+ view = QQuickView()
+
+ item1 = QQuickItem()
+ item1.setObjectName("Item1")
+ item1.setParentItem(view.contentItem())
+ self.assertEqual(item1.objectName(), "Item1") # check if the item still valid
+
+ item2 = QQuickItem()
+ item2.setObjectName("Item2")
+ item2.setParentItem(view.contentItem())
+ item1 = None
+ self.assertEqual(item2.objectName(), "Item2") # check if the item still valid
+
+ view = None
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
diff --git a/sources/pyside6/tests/QtQml/bug_926.py b/sources/pyside6/tests/QtQml/bug_926.py
new file mode 100644
index 000000000..085e9a68f
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_926.py
@@ -0,0 +1,57 @@
+# 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 sys
+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.helper import quickview_errorstring
+
+from PySide6.QtCore import QUrl, QTimer, QObject, Signal, Property
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import qmlRegisterType
+from PySide6.QtQuick import QQuickView
+
+
+class MyClass (QObject):
+
+ def __init__(self):
+ super().__init__()
+ self.__url = QUrl()
+
+ def getUrl(self):
+ return self.__url
+
+ def setUrl(self, value):
+ newUrl = QUrl(value)
+ if (newUrl != self.__url):
+ self.__url = newUrl
+ self.urlChanged.emit()
+
+ urlChanged = Signal()
+ urla = Property(QUrl, getUrl, setUrl, notify=urlChanged)
+
+
+class TestBug926 (unittest.TestCase):
+ def testIt(self):
+ app = QGuiApplication([])
+ qmlRegisterType(MyClass, 'Example', 1, 0, 'MyClass')
+ view = QQuickView()
+ file = Path(__file__).resolve().parent / 'bug_926.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+
+ view.show()
+ QTimer.singleShot(0, app.quit)
+ app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/bug_926.qml b/sources/pyside6/tests/QtQml/bug_926.qml
new file mode 100644
index 000000000..6f7b608d0
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_926.qml
@@ -0,0 +1,20 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import Example 1.0
+
+Rectangle {
+ width: 100
+ height: 62
+
+ MyClass {
+ id: myClass
+ urla: "http://www.pyside.org"
+ }
+
+ Text {
+ id: name
+ text: myClass.urla
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/bug_951.py b/sources/pyside6/tests/QtQml/bug_951.py
new file mode 100644
index 000000000..8a512d06f
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_951.py
@@ -0,0 +1,51 @@
+# 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.helper import quickview_errorstring
+from helper.timedqguiapplication import TimedQGuiApplication
+
+from PySide6.QtCore import QUrl
+from PySide6.QtQml import qmlRegisterType
+from PySide6.QtQuick import QQuickItem, QQuickView
+
+
+class MyItem(QQuickItem):
+ COMPONENT_COMPLETE_CALLED = False
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setObjectName("myitem")
+
+ def componentComplete(self):
+ MyItem.COMPONENT_COMPLETE_CALLED = True
+ super(MyItem, self).componentComplete()
+
+
+class TestRegisterQMLType(TimedQGuiApplication):
+ def setup(self):
+ super.setup(100 * 3) # 3s
+
+ def testSignalEmission(self):
+ qmlRegisterType(MyItem, "my.item", 1, 0, "MyItem")
+
+ view = QQuickView()
+ file = Path(__file__).resolve().parent / 'bug_951.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+
+ self.app.exec()
+ self.assertTrue(MyItem.COMPONENT_COMPLETE_CALLED)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/bug_951.qml b/sources/pyside6/tests/QtQml/bug_951.qml
new file mode 100644
index 000000000..02bf0c708
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_951.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import my.item 1.0
+Rectangle{
+ width:10
+ height:10
+ MyItem{ }
+}
diff --git a/sources/pyside6/tests/QtQml/bug_995.py b/sources/pyside6/tests/QtQml/bug_995.py
new file mode 100644
index 000000000..868c584e2
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_995.py
@@ -0,0 +1,31 @@
+# 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.helper import adjust_filename
+from helper.usesqapplication import UsesQApplication
+
+from PySide6.QtCore import QUrl
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQuick import QQuickView
+
+app = QGuiApplication([])
+file = Path(__file__).resolve().parent / 'bug_995.qml'
+assert (file.is_file())
+view = QQuickView(QUrl.fromLocalFile(file))
+view.show()
+view.resize(200, 200)
+contentItem = view.contentItem()
+item = contentItem.childAt(100, 100)
+
+# it CAN NOT crash here
+print(item)
+
diff --git a/sources/pyside6/tests/QtQml/bug_995.qml b/sources/pyside6/tests/QtQml/bug_995.qml
new file mode 100644
index 000000000..4f47cbd05
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_995.qml
@@ -0,0 +1,15 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+
+Rectangle {
+ width: 100
+ height: 100
+ color: "red"
+
+ Text {
+ text: "Hello World"
+ anchors.centerIn: parent
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/bug_997.py b/sources/pyside6/tests/QtQml/bug_997.py
new file mode 100644
index 000000000..501c221c3
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_997.py
@@ -0,0 +1,51 @@
+# 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.helper import quickview_errorstring
+from helper.usesqapplication import UsesQApplication
+from PySide6.QtCore import QCoreApplication, QTimer, QUrl, Slot
+from PySide6.QtQml import QQmlPropertyMap
+from PySide6.QtQuick import QQuickView
+
+
+class TestBug(UsesQApplication):
+
+ def setUp(self):
+ super().setUp()
+ self._complete = False
+
+ @Slot()
+ def complete(self):
+ self._complete = True
+ self.app.quit()
+
+ def testQMLFunctionCall(self):
+ ownerData = QQmlPropertyMap()
+ ownerData.insert('name', 'John Smith')
+ ownerData.insert('phone', '555-5555')
+ ownerData.insert('newValue', '')
+
+ self._view = QQuickView()
+ self._view.engine().quit.connect(self.complete)
+ self._view.setInitialProperties({'owner': ownerData})
+ file = Path(__file__).resolve().parent / 'bug_997.qml'
+ self.assertTrue(file.is_file())
+ self._view.setSource(QUrl.fromLocalFile(file))
+ self.assertTrue(self._view.rootObject(), quickview_errorstring(self._view))
+ self._view.show()
+ if not self._complete:
+ self.app.exec()
+ self.assertEqual(ownerData.value('newName'), ownerData.value('name'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/bug_997.qml b/sources/pyside6/tests/QtQml/bug_997.qml
new file mode 100644
index 000000000..23188f31f
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/bug_997.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+
+Text {
+ required property var owner
+ text: owner.name + " " + owner.phone
+ Component.onCompleted: {
+ owner.newName = owner.name
+ Qt.quit()
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/connect_python_qml.py b/sources/pyside6/tests/QtQml/connect_python_qml.py
new file mode 100644
index 000000000..2e60aec4f
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/connect_python_qml.py
@@ -0,0 +1,55 @@
+# 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 case for bug #442
+
+archive:
+https://srinikom.github.io/pyside-bz-archive/442.html
+'''
+
+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.helper import quickview_errorstring
+from helper.timedqguiapplication import TimedQGuiApplication
+from PySide6.QtCore import QObject, QUrl, SIGNAL
+from PySide6.QtGui import QColor
+from PySide6.QtQuick import QQuickItem, QQuickView
+
+
+class TestConnectionWithInvalidSignature(TimedQGuiApplication):
+ def onButtonClicked(self):
+ self.buttonClicked = True
+ self.app.quit()
+
+ def onButtonFailClicked(self):
+ pass
+
+ def testFailConnection(self):
+ self.buttonClicked = False
+ self.buttonFailClicked = False
+ view = QQuickView()
+ file = Path(__file__).resolve().parent / 'connect_python_qml.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ root = view.rootObject()
+ self.assertTrue(root, quickview_errorstring(view))
+ button = root.findChild(QObject, "buttonMouseArea")
+ self.assertRaises(TypeError, QObject.connect,
+ [button, SIGNAL('entered()'), self.onButtonFailClicked])
+ button.entered.connect(self.onButtonClicked)
+ button.entered.emit()
+ view.show()
+ self.app.exec()
+ self.assertTrue(self.buttonClicked)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/connect_python_qml.qml b/sources/pyside6/tests/QtQml/connect_python_qml.qml
new file mode 100644
index 000000000..1ed171e96
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/connect_python_qml.qml
@@ -0,0 +1,23 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+
+Rectangle {
+ id: page
+ width: 500; height: 200
+ color: "lightgray"
+
+ Rectangle {
+ id: button
+ width: 150; height: 40
+ color: "darkgray"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 150
+ MouseArea {
+ id: buttonMouseArea
+ objectName: "buttonMouseArea"
+ anchors.fill: parent
+ }
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/groupedproperty.py b/sources/pyside6/tests/QtQml/groupedproperty.py
new file mode 100644
index 000000000..4554d4b31
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/groupedproperty.py
@@ -0,0 +1,112 @@
+# 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 grouped properties (PYSIDE-1836)."""
+
+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 (QCoreApplication, QUrl, QObject, Property)
+from PySide6.QtQml import (QQmlComponent, QQmlEngine, QmlAnonymous, QmlElement)
+
+
+QML_IMPORT_NAME = "grouped"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlAnonymous
+class ShoeDescription(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._brand = ""
+ self._size = 0
+ self._price = 0
+
+ @Property(str)
+ def brand(self):
+ return self._brand
+
+ @brand.setter
+ def brand(self, b):
+ self._brand = b
+
+ @Property(int)
+ def size(self):
+ return self._size
+
+ @size.setter
+ def size(self, s):
+ self._size = s
+
+ @Property(int)
+ def price(self):
+ return self._price
+
+ @price.setter
+ def price(self, p):
+ self._price = p
+
+
+@QmlElement
+class Person(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._name = ""
+ self._shoe = ShoeDescription()
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, n):
+ self._name = n
+
+ @Property(ShoeDescription)
+ def shoe(self):
+ return self._shoe
+
+
+def component_error(component):
+ result = ""
+ for e in component.errors():
+ if result:
+ result += "\n"
+ result += str(e)
+ return result
+
+
+class TestQmlGroupedProperties(unittest.TestCase):
+ def testIt(self):
+ app = QCoreApplication(sys.argv)
+ file = Path(__file__).resolve().parent / "groupedproperty.qml"
+ url = QUrl.fromLocalFile(file)
+ engine = QQmlEngine()
+ component = QQmlComponent(engine, url)
+ person = component.create()
+ self.assertTrue(person, component_error(component))
+
+ # Check the meta type of the property
+ meta_object = person.metaObject()
+ index = meta_object.indexOfProperty("shoe")
+ self.assertTrue(index > 0)
+ meta_property = meta_object.property(index)
+ meta_type = meta_property.metaType()
+ self.assertTrue(meta_type.isValid())
+
+ # Check the values
+ self.assertEqual(person.shoe.brand, "Bikey")
+ self.assertEqual(person.shoe.price, 90)
+ self.assertEqual(person.shoe.size, 12)
+
+ del engine
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/groupedproperty.qml b/sources/pyside6/tests/QtQml/groupedproperty.qml
new file mode 100644
index 000000000..d32bd6005
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/groupedproperty.qml
@@ -0,0 +1,9 @@
+// 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 grouped
+
+Person {
+ name: "Bob Jones"
+ shoe { size: 12; brand: "Bikey"; price: 90 }
+}
diff --git a/sources/pyside6/tests/QtQml/hw.qml b/sources/pyside6/tests/QtQml/hw.qml
new file mode 100644
index 000000000..723901d96
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/hw.qml
@@ -0,0 +1,23 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+
+Rectangle {
+ id: page
+ width: 500; height: 200
+ color: "lightgray"
+
+ Text {
+ id: helloText
+ text: "Hello world!"
+ y: 30
+ anchors.horizontalCenter: page.horizontalCenter
+ font.pointSize: 24; font.bold: true
+ }
+
+ Image {
+ // It's okay for this to fail.
+ source: "http://localhost/logo.png"
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/javascript_exceptions.py b/sources/pyside6/tests/QtQml/javascript_exceptions.py
new file mode 100644
index 000000000..e2b530aaf
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/javascript_exceptions.py
@@ -0,0 +1,91 @@
+# 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.helper import quickview_errorstring
+from helper.usesqapplication import UsesQApplication
+
+from PySide6.QtCore import Slot, Property, Signal, QObject, QUrl
+from PySide6.QtQml import QJSEngine, qmlRegisterType
+from PySide6.QtQuick import QQuickView
+
+test_error_message = "This is an error."
+
+method_test_string = """
+(function (obj) {
+ obj.methodThrows();
+})
+"""
+
+property_test_string = """
+(function (obj) {
+ obj.propertyThrows;
+})
+"""
+
+test_1 = False
+test_2 = False
+
+
+class TestClass(QObject):
+ @Slot()
+ def methodThrows(self):
+ raise TypeError(test_error_message)
+
+ @Property(str)
+ def propertyThrows(self):
+ raise TypeError(test_error_message)
+
+ @Slot(int)
+ def passTest(self, test):
+ global test_1, test_2
+
+ if test == 1:
+ test_1 = True
+ else:
+ test_2 = True
+
+
+class JavaScriptExceptionsTest(UsesQApplication):
+ def test_jsengine(self):
+ engine = QJSEngine()
+ test_object = TestClass()
+ test_value = engine.newQObject(test_object)
+
+ result_1 = engine.evaluate(method_test_string).call([test_value])
+
+ self.assertTrue(result_1.isError())
+ self.assertEqual(result_1.property('message').toString(), test_error_message)
+ self.assertEqual(result_1.property('name').toString(), 'TypeError')
+
+ result_2 = engine.evaluate(property_test_string).call([test_value])
+
+ self.assertTrue(result_2.isError())
+ self.assertEqual(result_2.property('message').toString(), test_error_message)
+ self.assertEqual(result_2.property('name').toString(), 'TypeError')
+
+ def test_qml_type(self):
+ qmlRegisterType(TestClass, 'JavaScriptExceptions', 1, 0, 'JavaScriptExceptions')
+
+ view = QQuickView()
+ file = Path(__file__).resolve().parent / 'javascript_exceptions.qml'
+ self.assertTrue(file.is_file())
+ qml_url = QUrl.fromLocalFile(file)
+
+ view.setSource(qml_url)
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+
+ self.assertTrue(test_1)
+ self.assertTrue(test_2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/javascript_exceptions.qml b/sources/pyside6/tests/QtQml/javascript_exceptions.qml
new file mode 100644
index 000000000..1ab0fa3bb
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/javascript_exceptions.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import QtQuick.Controls 2.0
+import JavaScriptExceptions 1.0
+
+Rectangle {
+ JavaScriptExceptions {
+ id: obj
+ }
+
+ Component.onCompleted: {
+ // Method call test
+ try {
+ obj.methodThrows();
+ } catch(e) {
+ obj.passTest(1);
+ }
+
+ // Property accessor test
+ try {
+ obj.propertyThrows;
+ } catch(e) {
+ obj.passTest(2);
+ }
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/listproperty.py b/sources/pyside6/tests/QtQml/listproperty.py
new file mode 100644
index 000000000..884600d29
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/listproperty.py
@@ -0,0 +1,136 @@
+# 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 # noqa: E402
+init_test_paths(False)
+
+from helper.usesqapplication import UsesQApplication # noqa: E402, F401
+
+from PySide6.QtCore import QObject, QUrl, Property, qInstallMessageHandler # noqa: E402
+from PySide6.QtQml import ListProperty, QmlElement # noqa: E402
+from PySide6.QtQuick import QQuickView # noqa: E402
+
+
+QML_IMPORT_NAME = "test.ListPropertyTest"
+QML_IMPORT_MAJOR_VERSION = 1
+
+output_messages = []
+
+
+def message_handler(mode, context, message):
+ global output_messages
+ output_messages.append(f"{message}")
+
+
+class InheritsQObject(QObject):
+ pass
+
+
+def dummyFunc():
+ pass
+
+
+@QmlElement
+class Person(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent=None)
+ self._name = ''
+ self._friends = []
+
+ def appendFriend(self, friend):
+ self._friends.append(friend)
+
+ def friendCount(self):
+ return len(self._friends)
+
+ def friend(self, index):
+ return self._friends[index]
+
+ def removeLastItem(self):
+ if len(self._friends) > 0:
+ self._friends.pop()
+
+ def replace(self, index, friend):
+ if 0 <= index < len(self._friends):
+ self._friends[index] = friend
+
+ def clear(self):
+ self._friends.clear()
+
+ @Property(str, final=True)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, value):
+ self._name = value
+
+ friends = ListProperty(QObject, append=appendFriend, count=friendCount, at=friend,
+ removeLast=removeLastItem, replace=replace, clear=clear)
+
+
+class TestListProperty(UsesQApplication):
+ def testIt(self):
+
+ # Verify that type checking works properly
+ type_check_error = False
+
+ try:
+ ListProperty(QObject)
+ ListProperty(InheritsQObject)
+ except Exception:
+ type_check_error = True
+
+ self.assertFalse(type_check_error)
+
+ try:
+ ListProperty(int)
+ except TypeError:
+ type_check_error = True
+
+ self.assertTrue(type_check_error)
+
+ # Verify that method validation works properly
+ method_check_error = False
+
+ try:
+ ListProperty(QObject, append=None, at=None, count=None, replace=None, clear=None,
+ removeLast=None) # Explicitly setting None
+ ListProperty(QObject, append=dummyFunc)
+ ListProperty(QObject, count=dummyFunc, at=dummyFunc)
+ except Exception:
+ method_check_error = True
+
+ self.assertFalse(method_check_error)
+
+ try:
+ ListProperty(QObject, append=QObject())
+ except Exception:
+ method_check_error = True
+
+ self.assertTrue(method_check_error)
+
+ def testListPropParameters(self):
+ global output_messages
+ qInstallMessageHandler(message_handler)
+ view = QQuickView()
+ file = Path(__file__).resolve().parent / 'listproperty.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ view.show()
+ self.assertEqual(output_messages[0], "List length: 3")
+ self.assertEqual(output_messages[1], "First element: Alice")
+ self.assertEqual(output_messages[2], "Removing last item: Charlie")
+ self.assertEqual(output_messages[3], "Replacing last item: Bob")
+ self.assertEqual(output_messages[4], "Replaced last item: David")
+ self.assertEqual(output_messages[5], "List length after clearing: 0")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/listproperty.qml b/sources/pyside6/tests/QtQml/listproperty.qml
new file mode 100644
index 000000000..7b71e30ba
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/listproperty.qml
@@ -0,0 +1,50 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick 2.0
+import test.ListPropertyTest
+
+Rectangle {
+ width: 360
+ height: 360
+
+ Person {
+ id: person
+ friends: [
+ Person{
+ name: "Alice"
+ },
+ Person{
+ name: "Bob"
+ },
+ Person{
+ name: "Charlie"
+ }
+ ]
+ }
+
+ Person{
+ id: david
+ name: "David"
+ }
+
+ Component.onCompleted: {
+ // Access the length of the list
+ console.log("List length: " + person.friends.length);
+
+ // Access the first element of the list
+ console.log("First element: " + person.friends[0].name);
+
+ // Remove the last item of the list
+ console.log("Removing last item: " + person.friends.pop().name);
+
+ // Repalce the last item of the list
+ console.log("Replacing last item: " + person.friends[person.friends.length - 1].name);
+ person.friends[person.friends.length - 1] = david;
+ console.log("Replaced last item: " + person.friends[person.friends.length - 1].name);
+
+ // Clear the list
+ person.friends = [];
+ console.log("List length after clearing: " + person.friends.length);
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/qmlregistertype_test.py b/sources/pyside6/tests/QtQml/qmlregistertype_test.py
new file mode 100644
index 000000000..0042d6fd3
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/qmlregistertype_test.py
@@ -0,0 +1,53 @@
+# Copyright (C) 2024 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 QCoreApplication, QObject # noqa: F401
+from PySide6.QtQml import QQmlApplicationEngine, qmlRegisterType
+
+
+class BaseClass(QObject):
+ def __init__(self, p=None):
+ super().__init__(p)
+
+
+class ChildClass(BaseClass):
+ def __init__(self, p=None):
+ super().__init__(p)
+
+
+class TestQmlRegisterType(UsesQApplication):
+ """Test the legacy QML register functions."""
+
+ def test(self):
+ qmlRegisterType(BaseClass, 'test', 1, 0, 'BaseClass')
+ qmlRegisterType(ChildClass, 'test', 1, 0, 'ChildClass')
+ # PYSIDE-2709: qmlRegisterType() would set additional class info
+ # on the meta objects for registration which caused another meta
+ # object to be created, breaking inheritance.
+ child = ChildClass()
+ base = BaseClass()
+ self.assertTrue(child.metaObject().inherits(base.metaObject()))
+
+ engine = QQmlApplicationEngine()
+ file = Path(__file__).resolve().parent / 'qmlregistertype_test.qml'
+
+ engine.load(file)
+ rootObjects = engine.rootObjects()
+ self.assertTrue(rootObjects)
+ self.assertTrue(type(rootObjects[0]), ChildClass)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/qmlregistertype_test.qml b/sources/pyside6/tests/QtQml/qmlregistertype_test.qml
new file mode 100644
index 000000000..108bb84b1
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/qmlregistertype_test.qml
@@ -0,0 +1,7 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import test
+
+ChildClass {
+}
diff --git a/sources/pyside6/tests/QtQml/qqmlapplicationengine.qml b/sources/pyside6/tests/QtQml/qqmlapplicationengine.qml
new file mode 100644
index 000000000..77149ecdc
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/qqmlapplicationengine.qml
@@ -0,0 +1,23 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Window
+
+Window {
+ width: 300
+ height: 200
+ visible: true
+
+ Item {
+ width: 200
+ height: 60
+ Text {
+ anchors {
+ verticalCenter: parent.verticalCenter;
+ horizontalCenter: parent.horizontalCenter;
+ }
+ text: "Text"
+ }
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/qqmlapplicationengine_test.py b/sources/pyside6/tests/QtQml/qqmlapplicationengine_test.py
new file mode 100644
index 000000000..ea54e9e25
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/qqmlapplicationengine_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
+
+'''Test case for QQmlApplicationEngine'''
+
+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.timedqguiapplication import TimedQGuiApplication
+
+from PySide6.QtCore import QUrl, QObject, QTimer, Qt
+from PySide6.QtQml import QQmlApplicationEngine
+
+
+class TestQQmlApplicationEngine(TimedQGuiApplication):
+
+ def testQQmlApplicationEngine(self):
+ engine = QQmlApplicationEngine()
+
+ qml_file_path = Path(__file__).resolve().parent / "qqmlapplicationengine.qml"
+
+ # PYSIDE-1736: load from a string.
+ engine.load(os.fspath(qml_file_path))
+ rootObjects = engine.rootObjects()
+ self.assertTrue(rootObjects)
+ window = rootObjects[0]
+ window.setTitle("TestQQmlApplicationEngine")
+ QTimer.singleShot(100, window.close)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/qqmlcomponent_test.py b/sources/pyside6/tests/QtQml/qqmlcomponent_test.py
new file mode 100644
index 000000000..5521c64fa
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/qqmlcomponent_test.py
@@ -0,0 +1,36 @@
+# 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 PySide6.QtCore import Property, QObject
+from PySide6.QtQml import QQmlComponent
+
+
+class WithComponent(QObject):
+ def get_component(self):
+ return None
+
+ component = Property(QQmlComponent, fget=get_component)
+
+
+class TestQmlSupport(unittest.TestCase):
+
+ def testMetatypeValid(self):
+ m = WithComponent.staticMetaObject
+ c = m.property(m.indexOfProperty("component"))
+
+ self.assertTrue(c.typeId() > 0)
+ self.assertTrue(c.typeName() == "QQmlComponent*")
+ self.assertTrue(c.metaType().isValid())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/qqmlincubator_incubateWhile.py b/sources/pyside6/tests/QtQml/qqmlincubator_incubateWhile.py
new file mode 100644
index 000000000..12a73e398
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/qqmlincubator_incubateWhile.py
@@ -0,0 +1,84 @@
+#!/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(False)
+
+from helper.helper import quickview_errorstring
+
+from PySide6.QtCore import QObject, QUrl, Slot, QTimer
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import QQmlIncubationController, VolatileBool
+from PySide6.QtQuick import QQuickView
+
+
+class CustomIncubationController(QObject, QQmlIncubationController):
+ def __init__(self, test):
+ QObject.__init__(self)
+ QQmlIncubationController.__init__(self)
+ self.test = test
+ self.interrupted = False
+
+ # Incubate every 50 milliseconds
+ self.startTimer(50)
+ self.incubationShouldContinue = VolatileBool(True)
+ self.test.assertEqual(self.incubationShouldContinue.get(), True)
+
+ @Slot()
+ def interrupter(self):
+ if not self.interrupted:
+ self.interrupted = True
+ self.incubationShouldContinue.set(False)
+ self.test.assertEqual(self.incubationShouldContinue.get(), False)
+ QTimer.singleShot(0, QGuiApplication.instance().quit)
+
+ def timerEvent(self, ev):
+ # Incubate items for 2000 milliseconds, or until the volatile bool is set to false.
+ self.incubateWhile(self.incubationShouldContinue, 2000)
+
+
+class TestBug(unittest.TestCase):
+ def testIncubateWhileCall(self):
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+ controller = CustomIncubationController(self)
+ view.engine().setIncubationController(controller)
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ file = Path(__file__).resolve().parent / 'qqmlincubator_incubateWhile.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+ view.show()
+
+ root = view.rootObject()
+ # The QML code will issue an interrupt signal after half of its items are loaded.
+ root.shouldInterrupt.connect(controller.interrupter)
+ res = app.exec()
+
+ itemsToCreate = root.property("itemsToCreate")
+ loadedItems = root.property("loadedItems")
+ self.assertEqual(loadedItems, itemsToCreate / 2)
+
+ # Finish incubating the remaining items.
+ controller.incubateFor(1000)
+ loadedItems = root.property("loadedItems")
+ self.assertEqual(loadedItems, itemsToCreate)
+
+ # Deleting the view before it goes out of scope is required to make sure all child QML
+ # instances are destroyed in the correct order.
+ del view
+ del app
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/qqmlincubator_incubateWhile.qml b/sources/pyside6/tests/QtQml/qqmlincubator_incubateWhile.qml
new file mode 100644
index 000000000..803dec128
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/qqmlincubator_incubateWhile.qml
@@ -0,0 +1,42 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+import QtQuick 2.0
+
+
+Rectangle {
+ id: root
+ objectName: "theNicestRoot"
+ width: 400; height: 400
+
+ signal shouldInterrupt()
+ property int loadedItems: 0
+ property int itemsToCreate: 10
+
+ Row {
+ anchors.centerIn: parent
+ spacing: 20
+
+ Rectangle {
+ id: initialRectangle
+ width: 10; height: 10
+ color: "red"
+ }
+
+ Repeater {
+ model: itemsToCreate
+ Loader {
+ id: loader
+ asynchronous: true
+ source: "qqmlincubator_incubateWhile_component.qml"
+ onLoaded: {
+ root.loadedItems += 1
+
+ // Interrupt incubation after half of the items are loaded.
+ if (root.loadedItems >= (itemsToCreate / 2)) {
+ root.shouldInterrupt()
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/qqmlincubator_incubateWhile_component.qml b/sources/pyside6/tests/QtQml/qqmlincubator_incubateWhile_component.qml
new file mode 100644
index 000000000..0f6693952
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/qqmlincubator_incubateWhile_component.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+
+Rectangle {
+ id: root
+ width: 10; height: 10
+ color: "yellow"
+}
diff --git a/sources/pyside6/tests/QtQml/qqmlnetwork_test.py b/sources/pyside6/tests/QtQml/qqmlnetwork_test.py
new file mode 100644
index 000000000..abdb4529e
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/qqmlnetwork_test.py
@@ -0,0 +1,76 @@
+# 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 cases for QQmlNetwork'''
+
+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 QUrl, QTimer
+from PySide6.QtGui import QGuiApplication, QWindow
+from PySide6.QtQuick import QQuickView
+from PySide6.QtQml import QQmlNetworkAccessManagerFactory
+from PySide6.QtNetwork import QNetworkAccessManager
+
+from helper.helper import quickview_errorstring
+from helper.timedqguiapplication import TimedQGuiApplication
+
+
+request_created = False
+
+
+def check_done():
+ global request_created
+ if request_created:
+ windows = QGuiApplication.topLevelWindows()
+ if windows:
+ windows[0].close()
+
+
+class CustomManager(QNetworkAccessManager):
+ """CustomManager (running in a different thread)"""
+ def createRequest(self, op, req, data=None):
+ global request_created
+ print(">> createRequest ", self, op, req.url(), data)
+ request_created = True
+ return QNetworkAccessManager.createRequest(self, op, req, data)
+
+
+class CustomFactory(QQmlNetworkAccessManagerFactory):
+ def create(self, parent=None):
+ return CustomManager()
+
+
+class TestQQmlNetworkFactory(TimedQGuiApplication):
+ def setUp(self):
+ super().setUp(timeout=2000)
+
+ def testQQuickNetworkFactory(self):
+ view = QQuickView()
+ self.factory = CustomFactory()
+ view.engine().setNetworkAccessManagerFactory(self.factory)
+
+ file = Path(__file__).resolve().parent / 'hw.qml'
+ self.assertTrue(file.is_file())
+ url = QUrl.fromLocalFile(file)
+
+ view.setSource(url)
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+ view.show()
+
+ self.assertEqual(view.status(), QQuickView.Ready)
+
+ timer = QTimer()
+ timer.timeout.connect(check_done)
+ timer.start(50)
+ self.app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/qquickitem_grabToImage.py b/sources/pyside6/tests/QtQml/qquickitem_grabToImage.py
new file mode 100644
index 000000000..25341b0b2
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/qquickitem_grabToImage.py
@@ -0,0 +1,69 @@
+# 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.helper import quickview_errorstring
+from helper.timedqguiapplication import TimedQGuiApplication
+from PySide6.QtCore import QTimer, QUrl
+from PySide6.QtGui import QColor
+from PySide6.QtQuick import QQuickItem, QQuickView
+
+
+class TestGrabToSharedPointerImage(TimedQGuiApplication):
+ def setUp(self):
+ super().setUp(1000)
+
+ def testQQuickItemGrabToImageSharedPointer(self):
+ view = QQuickView()
+ file = Path(__file__).resolve().parent / 'qquickitem_grabToImage.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+ view.show()
+
+ # Get the QQuickItem objects for the blue Rectangle and the Image item.
+ root = view.rootObject()
+ blueRectangle = root.findChild(QQuickItem, "blueRectangle")
+ imageContainer = root.findChild(QQuickItem, "imageContainer")
+
+ # Start the image grabbing.
+ grabResultSharedPtr = blueRectangle.grabToImage()
+
+ # Implicit call of operator bool() of the smart pointer, to check that it holds
+ # a valid pointer.
+ self.assertTrue(grabResultSharedPtr)
+
+ self.grabbedColor = None
+
+ def onGrabReady():
+ # Signal early exit.
+ QTimer.singleShot(50, self.app.quit)
+
+ # Show the grabbed image in the QML Image item.
+ imageContainer.setProperty("source", grabResultSharedPtr.url())
+
+ # Wait for signal when grabbing is complete.
+ grabResultSharedPtr.ready.connect(onGrabReady)
+ self.app.exec()
+
+ # Get the first pixel color of the grabbed image.
+ self.image = grabResultSharedPtr.image()
+ self.assertTrue(self.image)
+ self.grabbedColor = self.image.pixelColor(0, 0)
+ self.assertTrue(self.grabbedColor.isValid())
+
+ # Compare the grabbed color with the one we set in the rectangle.
+ blueColor = QColor("blue")
+ self.assertEqual(self.grabbedColor, blueColor)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/qquickitem_grabToImage.qml b/sources/pyside6/tests/QtQml/qquickitem_grabToImage.qml
new file mode 100644
index 000000000..90235f078
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/qquickitem_grabToImage.qml
@@ -0,0 +1,44 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+
+Item {
+ id: root
+ width: 600
+ height: 600
+
+ Rectangle {
+ id: blue
+ objectName: "blueRectangle"
+ width: 200
+ height: 200
+ anchors.top: root.top
+ anchors.horizontalCenter: root.horizontalCenter
+ color: "blue"
+ }
+
+ Text {
+ text: qsTr("Original blue rectangle")
+ anchors.left: blue.right
+ anchors.verticalCenter: blue.verticalCenter
+ }
+
+ Image {
+ id: imageContainer
+ objectName: "imageContainer"
+ width: 200
+ height: 200
+ anchors.bottom: root.bottom
+ anchors.horizontalCenter: root.horizontalCenter
+ }
+
+ Text {
+ text: qsTr("Image with the source URL set to the result of calling QQuickItem::grabToImage on the rectangle. If you see a second blue rectangle, that means it works.")
+ anchors.left: imageContainer.right
+ anchors.verticalCenter: imageContainer.verticalCenter
+ wrapMode: Text.WrapAtWordBoundaryOrAnywhere
+ width: 200
+ }
+
+}
diff --git a/sources/pyside6/tests/QtQml/qquickview_test.py b/sources/pyside6/tests/QtQml/qquickview_test.py
new file mode 100644
index 000000000..226509669
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/qquickview_test.py
@@ -0,0 +1,87 @@
+# 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 cases for QQuickView'''
+
+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.helper import quickview_errorstring
+from helper.timedqguiapplication import TimedQGuiApplication
+
+from PySide6.QtCore import QUrl, QObject, Property, Slot, Signal
+from PySide6.QtQml import QQmlEngine, QQmlContext
+from PySide6.QtQuick import QQuickView
+
+
+class MyObject(QObject):
+ titleChanged = Signal()
+
+ def __init__(self, text, parent=None):
+ QObject.__init__(self, parent)
+ self._text = text
+
+ def getText(self):
+ return self._text
+
+ @Slot(str)
+ def qmlText(self, text):
+ self._qmlText = text
+
+ title = Property(str, getText, notify=titleChanged)
+
+
+class TestQQuickView(TimedQGuiApplication):
+
+ def testQQuickViewList(self):
+ view = QQuickView()
+
+ dataList = ["Item 1", "Item 2", "Item 3", "Item 4"]
+
+ view.setInitialProperties({"model": dataList})
+
+ file = Path(__file__).resolve().parent / 'view.qml'
+ self.assertTrue(file.is_file())
+ url = QUrl.fromLocalFile(file)
+ view.setSource(url)
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+ view.show()
+
+ self.assertEqual(view.status(), QQuickView.Ready)
+ rootObject = view.rootObject()
+ self.assertTrue(rootObject)
+ context = QQmlEngine.contextForObject(rootObject)
+ self.assertTrue(context)
+ self.assertTrue(context.engine())
+
+ test_context = QQmlContext(context) # Context properties, PYSIDE-1921
+ prop_pair = QQmlContext.PropertyPair()
+ prop_pair.name = "testProperty"
+ prop_pair.value = 42
+ test_context.setContextProperties([prop_pair])
+ self.assertTrue(test_context.contextProperty("testProperty"), 42)
+
+ def testModelExport(self):
+ view = QQuickView()
+ dataList = [MyObject("Item 1"), MyObject("Item 2"), MyObject("Item 3"), MyObject("Item 4")]
+
+ view.setInitialProperties({"model": dataList})
+
+ file = Path(__file__).resolve().parent / 'viewmodel.qml'
+ self.assertTrue(file.is_file())
+ url = QUrl.fromLocalFile(file)
+ view.setSource(url)
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+ view.show()
+
+ self.assertEqual(view.status(), QQuickView.Ready)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/registerattached.py b/sources/pyside6/tests/QtQml/registerattached.py
new file mode 100644
index 000000000..dd300dc89
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registerattached.py
@@ -0,0 +1,101 @@
+# 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 (QCoreApplication, QUrl, QObject, Property)
+from PySide6.QtQml import (QQmlComponent, QQmlEngine, QmlAnonymous,
+ QmlAttached, QmlElement, ListProperty,
+ qmlAttachedPropertiesObject)
+
+
+QML_IMPORT_NAME = "TestLayouts"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+EXPECTED_MARGINS = [10, 20]
+
+
+def component_error(component):
+ result = ""
+ for e in component.errors():
+ if result:
+ result += "\n"
+ result += str(e)
+ return result
+
+
+@QmlAnonymous
+class TestLayoutAttached(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._leftMargin = 0
+
+ @Property(int)
+ def leftMargin(self):
+ return self._leftMargin
+
+ @leftMargin.setter
+ def leftMargin(self, m):
+ self._leftMargin = m
+
+
+@QmlElement
+class TestWidget(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+@QmlElement
+@QmlAttached(TestLayoutAttached)
+class TestLayout(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._widgets = []
+
+ def widget(self, n):
+ return self._widgets[n]
+
+ def widgetCount(self):
+ return len(self._widgets)
+
+ def addWidget(self, w):
+ self._widgets.append(w)
+
+ @staticmethod
+ def qmlAttachedProperties(self, o):
+ return TestLayoutAttached(o)
+
+ widgets = ListProperty(TestWidget, addWidget)
+
+
+class TestQmlAttached(unittest.TestCase):
+ def testIt(self):
+ app = QCoreApplication(sys.argv)
+ file = Path(__file__).resolve().parent / 'registerattached.qml'
+ url = QUrl.fromLocalFile(file)
+ engine = QQmlEngine()
+ component = QQmlComponent(engine, url)
+ layout = component.create()
+ self.assertTrue(layout, component_error(component))
+
+ actual_margins = []
+ for i in range(layout.widgetCount()):
+ w = layout.widget(i)
+ a = qmlAttachedPropertiesObject(TestLayout, w, False)
+ actual_margins.append(a.leftMargin)
+ self.assertEqual(EXPECTED_MARGINS, actual_margins)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/registerattached.qml b/sources/pyside6/tests/QtQml/registerattached.qml
new file mode 100644
index 000000000..7ae8730bd
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registerattached.qml
@@ -0,0 +1,20 @@
+// 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 TestLayouts
+
+TestLayout {
+ id: layout
+
+ widgets: [
+ TestWidget {
+ id: widget1
+ TestLayout.leftMargin: 10
+ },
+
+ TestWidget {
+ id: widget2
+ TestLayout.leftMargin: 20
+ }
+ ]
+}
diff --git a/sources/pyside6/tests/QtQml/registerextended.py b/sources/pyside6/tests/QtQml/registerextended.py
new file mode 100644
index 000000000..b87b5aaaf
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registerextended.py
@@ -0,0 +1,74 @@
+# 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 (QCoreApplication, QUrl, QObject,
+ Property)
+from PySide6.QtQml import (QQmlComponent, QQmlEngine, QmlExtended,
+ QmlElement)
+
+
+"""Test for the QmlExtended decorator. Extends a class TestWidget
+ by a property leftMargin through a TestExtension and verifies the setting."""
+
+
+QML_IMPORT_NAME = "TestExtension"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+def component_error(component):
+ result = ""
+ for e in component.errors():
+ if result:
+ result += "\n"
+ result += str(e)
+ return result
+
+
+class TestExtension(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._leftMargin = 0
+
+ @Property(int)
+ def leftMargin(self):
+ return self._leftMargin
+
+ @leftMargin.setter
+ def leftMargin(self, m):
+ self._leftMargin = m
+
+
+@QmlElement
+@QmlExtended(TestExtension)
+class TestWidget(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+class TestQmlExtended(unittest.TestCase):
+ def testIt(self):
+ app = QCoreApplication(sys.argv)
+ file = Path(__file__).resolve().parent / 'registerextended.qml'
+ url = QUrl.fromLocalFile(file)
+ engine = QQmlEngine()
+ component = QQmlComponent(engine, url)
+ widget = component.create()
+ self.assertTrue(widget, component_error(component))
+ extension = widget.findChild(TestExtension)
+ self.assertTrue(extension)
+ self.assertEqual(extension.leftMargin, 10)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/registerextended.qml b/sources/pyside6/tests/QtQml/registerextended.qml
new file mode 100644
index 000000000..74095f83f
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registerextended.qml
@@ -0,0 +1,9 @@
+// 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 TestExtension
+
+TestWidget {
+ id: widget1
+ leftMargin: 10
+}
diff --git a/sources/pyside6/tests/QtQml/registerforeign.py b/sources/pyside6/tests/QtQml/registerforeign.py
new file mode 100644
index 000000000..d9a982d95
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registerforeign.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(False)
+
+from helper.helper import qmlcomponent_errorstring
+from helper.timedqguiapplication import TimedQGuiApplication
+
+from PySide6.QtCore import Property, QObject, QUrl, qVersion
+from PySide6.QtGui import QGuiApplication, QRasterWindow
+from PySide6.QtQml import (QmlNamedElement, QmlForeign, QQmlEngine,
+ QQmlComponent)
+
+
+"""Test the QmlForeign decorator, letting the QQmlEngine create a QRasterWindow."""
+
+
+QML_IMPORT_NAME = "Foreign"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlNamedElement("QRasterWindow")
+@QmlForeign(QRasterWindow)
+class RasterWindowForeign(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+class TestQmlForeign(TimedQGuiApplication):
+
+ def testIt(self):
+ engine = QQmlEngine()
+ file = Path(__file__).resolve().parent / 'registerforeign.qml'
+ self.assertTrue(file.is_file())
+ component = QQmlComponent(engine, QUrl.fromLocalFile(file))
+ window = component.create()
+ self.assertTrue(window, qmlcomponent_errorstring(component))
+ self.assertEqual(type(window), QRasterWindow)
+ window.setTitle(f"Qt {qVersion()}")
+ window.show()
+ self.app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/registerforeign.qml b/sources/pyside6/tests/QtQml/registerforeign.qml
new file mode 100644
index 000000000..0537abb7c
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registerforeign.qml
@@ -0,0 +1,8 @@
+// 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 Foreign
+
+QRasterWindow {
+ id: rasterWindow
+}
diff --git a/sources/pyside6/tests/QtQml/registerparserstatus.py b/sources/pyside6/tests/QtQml/registerparserstatus.py
new file mode 100644
index 000000000..bbcc14635
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registerparserstatus.py
@@ -0,0 +1,60 @@
+# 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 (QCoreApplication, QUrl)
+from PySide6.QtQml import (QQmlComponent, QQmlEngine,
+ QmlElement, QPyQmlParserStatus)
+
+
+QML_IMPORT_NAME = "ParserStatus"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+def component_error(component):
+ result = ""
+ for e in component.errors():
+ if result:
+ result += "\n"
+ result += str(e)
+ return result
+
+
+@QmlElement
+class TestItem(QPyQmlParserStatus):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.component_complete_called = False
+ self.class_begin_called = False
+
+ def componentComplete(self):
+ self.component_complete_called = True
+
+ def classBegin(self):
+ self.class_begin_called = True
+
+
+class TestQmlAttached(unittest.TestCase):
+ def testIt(self):
+ app = QCoreApplication(sys.argv)
+ file = Path(__file__).resolve().parent / 'registerparserstatus.qml'
+ url = QUrl.fromLocalFile(file)
+ engine = QQmlEngine()
+ component = QQmlComponent(engine, url)
+ item = component.create()
+ self.assertTrue(item, component_error(component))
+ self.assertTrue(item.component_complete_called)
+ self.assertTrue(item.class_begin_called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/registerparserstatus.qml b/sources/pyside6/tests/QtQml/registerparserstatus.qml
new file mode 100644
index 000000000..a39f03227
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registerparserstatus.qml
@@ -0,0 +1,8 @@
+// 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 ParserStatus
+
+TestItem {
+ id: item
+}
diff --git a/sources/pyside6/tests/QtQml/registerqmlfile.py b/sources/pyside6/tests/QtQml/registerqmlfile.py
new file mode 100644
index 000000000..335652e5d
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registerqmlfile.py
@@ -0,0 +1,30 @@
+# 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 QDir, QUrl
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import qmlRegisterType
+
+
+class TestQmlSupport(unittest.TestCase):
+
+ def testIt(self):
+ app = QGuiApplication([])
+
+ file = os.fspath(Path(__file__).resolve().parent / 'ModuleType.qml')
+ url = QUrl.fromLocalFile(QDir.fromNativeSeparators(file))
+ result = qmlRegisterType(url, "CustomModule", 1, 0, "ModuleType")
+ self.assertTrue(result != -1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/registersingletontype.py b/sources/pyside6/tests/QtQml/registersingletontype.py
new file mode 100644
index 000000000..6beca1131
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registersingletontype.py
@@ -0,0 +1,152 @@
+# 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.helper import quickview_errorstring
+
+from PySide6.QtCore import Property, Signal, QTimer, QUrl, QObject, Slot
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import (qmlRegisterSingletonType, qmlRegisterSingletonInstance,
+ QmlElement, QmlSingleton, QJSValue)
+from PySide6.QtQuick import QQuickView
+
+
+URI = "Singletons"
+
+
+finalResult = 0
+qObjectQmlTypeId = 0
+
+
+class SingletonQObject(QObject):
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+ self._data = 100
+
+ def getData(self):
+ return self._data
+
+ def setData(self, data):
+ global finalResult
+ finalResult = self._data = data
+
+ data = Property(int, getData, setData)
+
+
+def singletonQObjectCallback(engine):
+ obj = SingletonQObject()
+ obj.setData(50)
+ return obj
+
+
+def singletonQJSValueCallback(engine):
+ return engine.evaluate("new Object({data: 50})")
+
+
+QML_IMPORT_NAME = URI
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+@QmlSingleton
+class DecoratedSingletonQObject(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._data = 200
+
+ def getData(self):
+ return self._data
+
+ def setData(self, data):
+ self._data = data
+
+ data = Property(int, getData, setData)
+
+
+@QmlElement
+@QmlSingleton
+class DecoratedSingletonWithCreate(QObject):
+ def __init__(self, data, parent=None):
+ super().__init__(parent)
+ self._data = data
+
+ @staticmethod
+ def create(engine):
+ return DecoratedSingletonWithCreate(400)
+
+ def getData(self):
+ return self._data
+
+ def setData(self, data):
+ self._data = data
+
+ data = Property(int, getData, setData)
+
+
+class TestQuickView(QQuickView):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._singleton_instance_qobject_int = False
+ self._singleton_instance_qobject_str = False
+ self._singleton_instance_jsvalue_int = False
+
+ @Slot()
+ def testSlot(self):
+ engine = self.engine()
+ instance = engine.singletonInstance(qObjectQmlTypeId)
+ if instance is not None and isinstance(instance, QObject):
+ self._singleton_instance_qobject_int = True
+ instance = engine.singletonInstance(URI, 'SingletonQObjectNoCallback')
+ if instance is not None and isinstance(instance, QObject):
+ self._singleton_instance_qobject_str = True
+ instance = engine.singletonInstance(URI, 'SingletonQJSValue')
+ if instance is not None and isinstance(instance, QJSValue):
+ self._singleton_instance_jsvalue_int = True
+ self.close()
+
+
+class TestQmlSupport(unittest.TestCase):
+ def testIt(self):
+ app = QGuiApplication([])
+
+ qObjectQmlTypeId = qmlRegisterSingletonType(SingletonQObject, URI, 1, 0,
+ 'SingletonQObjectNoCallback')
+ qmlRegisterSingletonType(SingletonQObject, URI, 1, 0, 'SingletonQObjectCallback',
+ singletonQObjectCallback)
+
+ qmlRegisterSingletonType(URI, 1, 0, 'SingletonQJSValue', singletonQJSValueCallback)
+
+ # Accepts only QObject derived types
+ l = [1, 2]
+ with self.assertRaises(TypeError):
+ qmlRegisterSingletonInstance(SingletonQObject, URI, 1, 0, 'SingletonInstance', l)
+
+ # Modify value on the instance
+ s = SingletonQObject()
+ s.setData(99)
+ qmlRegisterSingletonInstance(SingletonQObject, URI, 1, 0, 'SingletonInstance', s)
+
+ view = TestQuickView()
+ file = Path(__file__).resolve().parent / 'registersingletontype.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ self.assertTrue(view.rootObject(), quickview_errorstring(view))
+ view.resize(200, 200)
+ view.show()
+ QTimer.singleShot(250, view.testSlot)
+ app.exec()
+ self.assertEqual(finalResult, 899)
+ self.assertTrue(view._singleton_instance_qobject_int)
+ self.assertTrue(view._singleton_instance_qobject_str)
+ self.assertTrue(view._singleton_instance_jsvalue_int)
+
+
+if __name__ == '__main__': unittest.main()
diff --git a/sources/pyside6/tests/QtQml/registersingletontype.qml b/sources/pyside6/tests/QtQml/registersingletontype.qml
new file mode 100644
index 000000000..31ca7fe4d
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registersingletontype.qml
@@ -0,0 +1,14 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import Singletons 1.0
+
+Item {
+ Component.onCompleted: {
+ SingletonQObjectCallback.data += SingletonQObjectNoCallback.data
+ + SingletonQJSValue.data
+ + SingletonInstance.data
+ + DecoratedSingletonQObject.data + DecoratedSingletonWithCreate.data;
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/registertype.py b/sources/pyside6/tests/QtQml/registertype.py
new file mode 100644
index 000000000..6c9874f32
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registertype.py
@@ -0,0 +1,116 @@
+# 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.helper import quickview_errorstring
+
+from PySide6.QtCore import Property, QObject, QTimer, QUrl
+from PySide6.QtGui import QGuiApplication, QPen, QColor, QPainter
+from PySide6.QtQml import (qjsEngine, qmlContext, qmlEngine, qmlRegisterType,
+ ListProperty, QmlElement, QmlNamedElement)
+from PySide6.QtQuick import QQuickView, QQuickItem, QQuickPaintedItem
+
+
+QML_IMPORT_NAME = "Charts"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class PieSlice (QQuickPaintedItem):
+ def __init__(self, parent=None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._color = QColor()
+ self._fromAngle = 0
+ self._angleSpan = 0
+
+ def getColor(self):
+ return self._color
+
+ def setColor(self, value):
+ self._color = value
+
+ def getFromAngle(self):
+ return self._angle
+
+ def setFromAngle(self, value):
+ self._fromAngle = value
+
+ def getAngleSpan(self):
+ return self._angleSpan
+
+ def setAngleSpan(self, value):
+ self._angleSpan = value
+
+ color = Property(QColor, getColor, setColor)
+ fromAngle = Property(int, getFromAngle, setFromAngle)
+ angleSpan = Property(int, getAngleSpan, setAngleSpan)
+
+ def paint(self, painter):
+ global paintCalled
+ pen = QPen(self._color, 2)
+ painter.setPen(pen)
+ painter.setRenderHints(QPainter.Antialiasing, True)
+ painter.drawPie(self.boundingRect(), self._fromAngle * 16, self._angleSpan * 16)
+ paintCalled = True
+
+
+@QmlNamedElement("PieChart")
+class PieChartOriginalName(QQuickItem):
+ def __init__(self, parent=None):
+ QQuickItem.__init__(self, parent)
+ self._name = ''
+ self._slices = []
+
+ def getName(self):
+ return self._name
+
+ def setName(self, value):
+ self._name = value
+
+ name = Property(str, getName, setName)
+
+ def appendSlice(self, _slice):
+ global appendCalled
+ _slice.setParentItem(self)
+ self._slices.append(_slice)
+ appendCalled = True
+
+ slices = ListProperty(PieSlice, append=appendSlice)
+
+
+appendCalled = False
+paintCalled = False
+
+
+class TestQmlSupport(unittest.TestCase):
+
+ def testIt(self):
+ app = QGuiApplication([])
+
+ view = QQuickView()
+ file = Path(__file__).resolve().parent / 'registertype.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ root_object = view.rootObject()
+ self.assertTrue(root_object, quickview_errorstring(view))
+ self.assertTrue(qjsEngine(root_object))
+ self.assertEqual(qmlEngine(root_object), view.engine())
+ self.assertTrue(qmlContext(root_object))
+
+ view.show()
+ QTimer.singleShot(250, view.close)
+ app.exec()
+ self.assertTrue(appendCalled)
+ self.assertTrue(paintCalled)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/registertype.qml b/sources/pyside6/tests/QtQml/registertype.qml
new file mode 100644
index 000000000..3be2f9f04
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registertype.qml
@@ -0,0 +1,32 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import Charts 1.0
+
+Item {
+ width: 300; height: 200
+
+ PieChart {
+ anchors.centerIn: parent
+ width: 100; height: 100
+
+ slices: [
+ PieSlice {
+ anchors.fill: parent
+ color: "red"
+ fromAngle: 0; angleSpan: 110
+ },
+ PieSlice {
+ anchors.fill: parent
+ color: "black"
+ fromAngle: 110; angleSpan: 50
+ },
+ PieSlice {
+ anchors.fill: parent
+ color: "blue"
+ fromAngle: 160; angleSpan: 100
+ }
+ ]
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/registeruncreatable.qml b/sources/pyside6/tests/QtQml/registeruncreatable.qml
new file mode 100644
index 000000000..b121c014d
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registeruncreatable.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import Charts 1.0
+
+Item {
+ width: 300; height: 200
+
+ Uncreatable {
+ name : 'uncreatable'
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/registeruncreatabletype.py b/sources/pyside6/tests/QtQml/registeruncreatabletype.py
new file mode 100644
index 000000000..3a4df69f6
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/registeruncreatabletype.py
@@ -0,0 +1,62 @@
+# 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.helper import qmlcomponent_errorstring
+
+from PySide6.QtCore import Property, QObject, QUrl
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import QmlElement, QmlUncreatable, QQmlEngine, QQmlComponent
+
+noCreationReason = 'Cannot create an item of type: Uncreatable (expected)'
+
+QML_IMPORT_NAME = "Charts"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+@QmlUncreatable(noCreationReason)
+class Uncreatable(QObject):
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+ self._name = 'uncreatable'
+
+ def getName(self):
+ return self._name
+
+ def setName(self, value):
+ self._name = value
+
+ name = Property(str, getName, setName)
+
+
+class TestQmlSupport(unittest.TestCase):
+
+ def testIt(self):
+ app = QGuiApplication([])
+
+ engine = QQmlEngine()
+ file = Path(__file__).resolve().parent / 'registeruncreatable.qml'
+ self.assertTrue(file.is_file())
+ component = QQmlComponent(engine, QUrl.fromLocalFile(file))
+
+ # Check that the uncreatable item produces the correct error
+ self.assertEqual(component.status(), QQmlComponent.Error)
+ errorFound = False
+ for e in component.errors():
+ if noCreationReason in e.toString():
+ errorFound = True
+ break
+ self.assertTrue(errorFound)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/signal_arguments.py b/sources/pyside6/tests/QtQml/signal_arguments.py
new file mode 100644
index 000000000..f5b0f8bd3
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/signal_arguments.py
@@ -0,0 +1,61 @@
+# 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.helper import quickview_errorstring
+from helper.timedqguiapplication import TimedQGuiApplication
+
+from PySide6.QtQuick import QQuickView
+from PySide6.QtCore import QObject, Signal, Slot, QUrl, QTimer, Property
+from PySide6.QtQml import QmlElement
+
+QML_IMPORT_NAME = "test.Obj"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class Obj(QObject):
+ def __init__(self):
+ super().__init__()
+ self.value = 0
+
+ sumResult = Signal(int, name="sumResult", arguments=['sum'])
+
+ @Slot(int, int)
+ def sum(self, arg1, arg2):
+ self.sumResult.emit(arg1 + arg2)
+
+ @Slot(str)
+ def sendValue(self, s):
+ self.value = int(s)
+
+
+class TestConnectionWithQml(TimedQGuiApplication):
+
+ def testSignalArguments(self):
+ view = QQuickView()
+ obj = Obj()
+
+ view.setInitialProperties({"o": obj})
+ file = Path(__file__).resolve().parent / 'signal_arguments.qml'
+ self.assertTrue(file.is_file())
+ view.setSource(QUrl.fromLocalFile(file))
+ root = view.rootObject()
+ self.assertTrue(root, quickview_errorstring(view))
+ button = root.findChild(QObject, "button")
+ self.assertTrue(button)
+ view.show()
+ button.clicked.emit()
+ self.assertEqual(obj.value, 42)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/signal_arguments.qml b/sources/pyside6/tests/QtQml/signal_arguments.qml
new file mode 100644
index 000000000..dbc991c77
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/signal_arguments.qml
@@ -0,0 +1,36 @@
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+
+import QtQuick 2.5
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.2
+import test.Obj 1.0
+
+Rectangle {
+ visible: true
+ required property Obj o
+ GridLayout {
+ Button {
+ id: button
+ objectName: "button"
+ text: "sum!"
+ onClicked: {
+ o.sum(40, 2)
+ }
+ }
+ Text {
+ id: sumResultText
+ }
+ }
+ Connections {
+ target: o
+ function onSumResult(sum) {
+ // set the value on the Qml side
+ sumResultText.text = sum
+ // set internal Python value from the already
+ // modified value
+ o.sendValue(sumResultText.text)
+ }
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/signal_types.py b/sources/pyside6/tests/QtQml/signal_types.py
new file mode 100644
index 000000000..240c0fd6e
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/signal_types.py
@@ -0,0 +1,124 @@
+# 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 json
+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.helper import quickview_errorstring
+from helper.timedqguiapplication import TimedQGuiApplication
+
+from PySide6.QtQuick import QQuickView
+from PySide6.QtCore import QObject, Signal, Slot, QUrl
+from PySide6.QtQml import QmlElement
+
+"""PYSIDE-2098: Roundtrip test for signals using QVariantList/QVariantMap.
+
+@QmlElement Obj has signals of list/dict type which are connected to an
+instance of Connections in QML. The QML instance sends them back to Obj's
+slots and additionally sends them back as stringified JSON. This verifies that
+a conversion is done instead of falling back to the default PyObject
+passthrough converter, resulting in a QVariant<PyObject> and reference leaks
+on the PyObject.
+"""
+
+QML_IMPORT_NAME = "test.Obj"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class Obj(QObject):
+ listSignal = Signal(list)
+ dictSignal = Signal(dict)
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._last_data = None
+ self._last_json_data = None
+
+ def clear(self):
+ self._last_data = None
+ self._last_json_data = None
+
+ def last_data(self):
+ """Last data received."""
+ return self._last_data
+
+ def last_json_data(self):
+ """Last data converted from JSON."""
+ return self._last_json_data
+
+ def emit_list(self, test_list):
+ self.listSignal.emit(test_list)
+
+ def emit_dict(self, test_dict):
+ self.dictSignal.emit(test_dict)
+
+ @Slot(list)
+ def list_slot(self, l):
+ self._last_data = l
+ print("list_slot", l)
+
+ @Slot(dict)
+ def dict_slot(self, d):
+ self._last_data = d
+ print("dict_slot", d)
+
+ @Slot(str)
+ def json_slot(self, s):
+ self._last_json_data = json.loads(s)
+ print(f'json_slot "{s}"->', self._last_json_data)
+
+
+class TestConnectionWithQml(TimedQGuiApplication):
+
+ def setUp(self):
+ super().setUp()
+ self._view = QQuickView()
+ self._obj = Obj()
+
+ self._view.setInitialProperties({"o": self._obj})
+ file = Path(__file__).resolve().parent / "signal_types.qml"
+ self.assertTrue(file.is_file())
+ self._view.setSource(QUrl.fromLocalFile(file))
+ root = self._view.rootObject()
+ self.assertTrue(root, quickview_errorstring(self._view))
+
+ def tearDown(self):
+ super().tearDown()
+ del self._view
+ self._view = None
+
+ def testVariantList(self):
+ self._obj.clear()
+ test_list = [1, 2]
+ before_refcount = sys.getrefcount(test_list)
+ self._obj.emit_list(test_list)
+ received = self._obj.last_data()
+ self.assertTrue(isinstance(received, list))
+ self.assertEqual(test_list, received)
+ self.assertEqual(test_list, self._obj.last_json_data())
+ refcount = sys.getrefcount(test_list)
+ self.assertEqual(before_refcount, refcount)
+
+ def testVariantDict(self):
+ self._obj.clear()
+ test_dict = {"1": 1, "2": 2}
+ before_refcount = sys.getrefcount(test_dict)
+ self._obj.emit_dict(test_dict)
+ received = self._obj.last_data()
+ self.assertTrue(isinstance(received, dict))
+ self.assertEqual(test_dict, received)
+ self.assertEqual(test_dict, self._obj.last_json_data())
+ refcount = sys.getrefcount(test_dict)
+ self.assertEqual(before_refcount, refcount)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtQml/signal_types.qml b/sources/pyside6/tests/QtQml/signal_types.qml
new file mode 100644
index 000000000..6b03b3abd
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/signal_types.qml
@@ -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 QtQuick
+import test.Obj
+
+Rectangle {
+ visible: true
+ required property Obj o
+
+ Connections {
+ target: o
+ function onListSignal(list) {
+ var json_data = JSON.stringify(list)
+ console.log("Connections.onListSignal: " + typeof(list) + " " + json_data)
+ o.list_slot(list)
+ o.json_slot(json_data)
+ }
+ function onDictSignal(dict) {
+ var json_data = JSON.stringify(dict)
+ console.log("Connections.onDictSignal: " + typeof(dict) + " " + json_data)
+ o.dict_slot(dict)
+ o.json_slot(json_data)
+ }
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/view.qml b/sources/pyside6/tests/QtQml/view.qml
new file mode 100644
index 000000000..8557271c2
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/view.qml
@@ -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
+
+import QtQuick 2.0
+
+ListView {
+ width: 100
+ height: 100
+ anchors.fill: parent
+ model: myModel
+ delegate: Component {
+ Rectangle {
+ required property string modelData
+ height: 25
+ width: 100
+ Text { text: modelData }
+ }
+ }
+}
diff --git a/sources/pyside6/tests/QtQml/viewmodel.qml b/sources/pyside6/tests/QtQml/viewmodel.qml
new file mode 100644
index 000000000..33db6072e
--- /dev/null
+++ b/sources/pyside6/tests/QtQml/viewmodel.qml
@@ -0,0 +1,16 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+
+ListView {
+ width: 100; height: 100
+ anchors.fill: parent
+
+ delegate: Rectangle {
+ height: 25
+ width: 100
+ Text { text: model.modelData.title }
+ }
+}
+
diff --git a/sources/pyside6/tests/QtQuick/CMakeLists.txt b/sources/pyside6/tests/QtQuick/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtQuick/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtQuick3D/CMakeLists.txt b/sources/pyside6/tests/QtQuick3D/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtQuick3D/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtQuickControls2/CMakeLists.txt b/sources/pyside6/tests/QtQuickControls2/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickControls2/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtQuickTest/CMakeLists.txt b/sources/pyside6/tests/QtQuickTest/CMakeLists.txt
new file mode 100644
index 000000000..49f15e447
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickTest/CMakeLists.txt
@@ -0,0 +1,3 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+PYSIDE_TEST(quicktestmainwithsetup/tst_quicktestmainwithsetup.py)
diff --git a/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/data/tst_setup.qml b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/data/tst_setup.qml
new file mode 100644
index 000000000..2cfe936a6
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/data/tst_setup.qml
@@ -0,0 +1,20 @@
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import QtTest 1.2
+
+import QmlRegisterTypeCppModule 1.0
+import ImportPathQmlModule 1.0
+
+TestCase {
+ name: "setup"
+
+ QmlRegisterTypeCppType {}
+ ImportPathQmlType {}
+
+ function initTestCase()
+ {
+ verify(qmlEngineAvailableCalled)
+ }
+}
diff --git a/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml
new file mode 100644
index 000000000..617bdaaf6
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml
@@ -0,0 +1,3 @@
+import QtQuick 2.0
+
+Item {}
diff --git a/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir
new file mode 100644
index 000000000..dea7c9a8a
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir
@@ -0,0 +1,2 @@
+module ImportPathQmlModule
+ImportPathQmlType 1.0 ImportPathQmlType.qml
diff --git a/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/quicktestmainwithsetup.pyproject b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/quicktestmainwithsetup.pyproject
new file mode 100644
index 000000000..61e89f4af
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/quicktestmainwithsetup.pyproject
@@ -0,0 +1,4 @@
+{
+ "files": ["tst_quicktestmainwithsetup.py", "data/tst_setup.qml",
+ "imports/ImportPathQmlModule/ImportPathQmlType.qml"]
+}
diff --git a/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/tst_quicktestmainwithsetup.py b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/tst_quicktestmainwithsetup.py
new file mode 100644
index 000000000..33b2db08f
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/tst_quicktestmainwithsetup.py
@@ -0,0 +1,46 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[2]))
+from init_paths import init_test_paths
+init_test_paths(False)
+
+from pathlib import Path
+from PySide6.QtCore import QObject, Slot
+from PySide6.QtQml import QQmlEngine, qmlRegisterType
+from PySide6.QtQuickTest import QUICK_TEST_MAIN_WITH_SETUP
+
+
+"""Copy of the equivalent test in qtdeclarative."""
+
+
+class QmlRegisterTypeCppType(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+class CustomTestSetup(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ @Slot(QQmlEngine)
+ def qmlEngineAvailable(self, qmlEngine):
+ # Test that modules are successfully imported by the TestCaseCollector
+ # that parses the QML files (but doesn't run them). For that to happen,
+ # qmlEngineAvailable() must be called before TestCaseCollector does its
+ # thing.
+ qmlRegisterType(QmlRegisterTypeCppType, "QmlRegisterTypeCppModule", 1, 0,
+ "QmlRegisterTypeCppType")
+ import_dir = Path(__file__).parent / "imports"
+ qmlEngine.addImportPath(os.fspath(import_dir))
+ qmlEngine.rootContext().setContextProperty("qmlEngineAvailableCalled", True)
+
+
+data_dir = Path(__file__).parent / "data"
+exitCode = QUICK_TEST_MAIN_WITH_SETUP("qquicktestsetup", CustomTestSetup, sys.argv,
+ os.fspath(data_dir))
+sys.exit(exitCode)
diff --git a/sources/pyside6/tests/QtQuickWidgets/CMakeLists.txt b/sources/pyside6/tests/QtQuickWidgets/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickWidgets/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtRemoteObjects/CMakeLists.txt b/sources/pyside6/tests/QtRemoteObjects/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtRemoteObjects/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtScxml/CMakeLists.txt b/sources/pyside6/tests/QtScxml/CMakeLists.txt
new file mode 100644
index 000000000..dde186697
--- /dev/null
+++ b/sources/pyside6/tests/QtScxml/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(test_dynamic.py)
diff --git a/sources/pyside6/tests/QtScxml/QtScxml.pyproject b/sources/pyside6/tests/QtScxml/QtScxml.pyproject
new file mode 100644
index 000000000..21ee7c9ab
--- /dev/null
+++ b/sources/pyside6/tests/QtScxml/QtScxml.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["test_dynamic.py"]
+}
diff --git a/sources/pyside6/tests/QtScxml/test_dynamic.py b/sources/pyside6/tests/QtScxml/test_dynamic.py
new file mode 100644
index 000000000..212d6f7c1
--- /dev/null
+++ b/sources/pyside6/tests/QtScxml/test_dynamic.py
@@ -0,0 +1,53 @@
+# 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.timedqapplication import TimedQApplication
+from PySide6.QtCore import QCoreApplication, QObject, Slot, SIGNAL, SLOT
+from PySide6.QtScxml import QScxmlStateMachine, QScxmlEvent
+
+
+class Receiver(QObject):
+ def __init__(self):
+ super().__init__()
+ self.eventReceived = False
+ self.reachedStable = False
+
+ @Slot(QScxmlEvent)
+ def handleEvent(self, event):
+ self.eventReceived = True
+
+ @Slot()
+ def slotReachedStable(self):
+ self.reachedStable = True
+
+
+class testDynamicStateMachine(TimedQApplication):
+ def setUp(self):
+ super().setUp()
+ filePath = Path(__file__).parent / "trafficlight.scxml"
+ self.assertTrue(filePath.is_file())
+ self._machine = QScxmlStateMachine.fromFile(os.fspath(filePath))
+ self._receiver = Receiver()
+ self._machine.connectToEvent("*", self._receiver,
+ SLOT("handleEvent(QScxmlEvent)"))
+ self._machine.reachedStableState.connect(self._receiver.slotReachedStable)
+ self.assertTrue(not self._machine.parseErrors())
+ self.assertTrue(self._machine)
+
+ def test(self):
+ self._machine.start()
+ while not self._receiver.reachedStable and not self._receiver.eventReceived:
+ QCoreApplication.processEvents()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtScxml/trafficlight.scxml b/sources/pyside6/tests/QtScxml/trafficlight.scxml
new file mode 100644
index 000000000..699409e68
--- /dev/null
+++ b/sources/pyside6/tests/QtScxml/trafficlight.scxml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+-->
+<scxml
+ xmlns="http://www.w3.org/2005/07/scxml"
+ xmlns:qt="http://theqtcompany.com/scxml/2015/06/"
+ version="1.0"
+ name="TrafficLightStateMachine"
+ initial="working"
+>
+ <state id="working" initial="yellow">
+ <state id="red">
+ <onentry>
+ <send event="startGoingGreen" delay="3s"/>
+ </onentry>
+ <transition event="startGoingGreen" target="redGoingGreen"/>
+ </state>
+
+ <state id="yellow" initial="greenGoingRed">
+ <state id="redGoingGreen">
+ <onentry>
+ <send event="goGreen" delay="1s"/>
+ </onentry>
+ <transition event="goGreen" target="green"/>
+ </state>
+
+ <state id="greenGoingRed">
+ <onentry>
+ <send event="goRed" delay="1s"/>
+ </onentry>
+ <transition event="goRed" target="red"/>
+ </state>
+ </state>
+
+ <state id="green">
+ <onentry>
+ <send event="startGoingRed" delay="3s"/>
+ </onentry>
+ <transition event="startGoingRed" target="greenGoingRed"/>
+ </state>
+
+ <transition event="smash" target="broken"/>
+ </state>
+
+ <state id="broken" initial="blinking">
+ <state id="blinking">
+ <onentry>
+ <send event="unblink" delay="1s"/>
+ </onentry>
+ <transition event="unblink" target="unblinking"/>
+ </state>
+
+ <state id="unblinking">
+ <onentry>
+ <send event="blink" delay="1s"/>
+ </onentry>
+ <transition event="blink" target="blinking"/>
+ </state>
+
+ <transition event="repair" target="working"/>
+ </state>
+</scxml>
diff --git a/sources/pyside6/tests/QtSensors/CMakeLists.txt b/sources/pyside6/tests/QtSensors/CMakeLists.txt
new file mode 100644
index 000000000..87e548f87
--- /dev/null
+++ b/sources/pyside6/tests/QtSensors/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(sensors.py)
diff --git a/sources/pyside6/tests/QtSensors/QtSensors.pyproject b/sources/pyside6/tests/QtSensors/QtSensors.pyproject
new file mode 100644
index 000000000..2090754d9
--- /dev/null
+++ b/sources/pyside6/tests/QtSensors/QtSensors.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["sensors.py"]
+}
diff --git a/sources/pyside6/tests/QtSensors/sensors.py b/sources/pyside6/tests/QtSensors/sensors.py
new file mode 100644
index 000000000..84bd1a92f
--- /dev/null
+++ b/sources/pyside6/tests/QtSensors/sensors.py
@@ -0,0 +1,46 @@
+#!/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
+
+'''Test cases for QSensor'''
+
+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.QtSensors import QSensor, QSensorReading
+
+
+class QSensorTest(unittest.TestCase):
+ def test(self):
+ for sensorType in QSensor.sensorTypes():
+ identifiers = QSensor.sensorsForType(sensorType)
+ values = []
+ error = ''
+ for identifier in identifiers:
+ sensor = QSensor(sensorType, None)
+ sensor.setIdentifier(identifier)
+ if sensor.connectToBackend():
+ usedIdentifier = identifier
+ reading = sensor.reading()
+ if reading:
+ for i in range(0, reading.valueCount()):
+ values.append(reading.value(i))
+ break
+ else:
+ error = "Unable to obtain reading"
+ else:
+ error = "Unable to connect to backend"
+ if values:
+ print('Sensor ', sensorType, usedIdentifier, values)
+ else:
+ print(f"{sensorType}: {error}", file=sys.stderr)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtSerialBus/CMakeLists.txt b/sources/pyside6/tests/QtSerialBus/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtSerialBus/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtSerialPort/CMakeLists.txt b/sources/pyside6/tests/QtSerialPort/CMakeLists.txt
new file mode 100644
index 000000000..554373445
--- /dev/null
+++ b/sources/pyside6/tests/QtSerialPort/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(serial.py)
diff --git a/sources/pyside6/tests/QtSerialPort/QtSerialPort.pyproject b/sources/pyside6/tests/QtSerialPort/QtSerialPort.pyproject
new file mode 100644
index 000000000..1b7c0f694
--- /dev/null
+++ b/sources/pyside6/tests/QtSerialPort/QtSerialPort.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["serial.py"]
+}
diff --git a/sources/pyside6/tests/QtSerialPort/serial.py b/sources/pyside6/tests/QtSerialPort/serial.py
new file mode 100644
index 000000000..f1e54f2ac
--- /dev/null
+++ b/sources/pyside6/tests/QtSerialPort/serial.py
@@ -0,0 +1,72 @@
+#!/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
+
+'''Test cases for QSerialPort'''
+
+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.QtSerialPort import QSerialPort, QSerialPortInfo
+from PySide6.QtCore import QIODevice
+
+
+class QSerialPortTest(unittest.TestCase):
+ def testDefaultConstructedPort(self):
+ serialPort = QSerialPort()
+
+ self.assertEqual(serialPort.error(), QSerialPort.NoError)
+ self.assertTrue(not serialPort.errorString() == "")
+
+ # properties
+ defaultBaudRate = QSerialPort.Baud9600
+ self.assertEqual(serialPort.baudRate(), defaultBaudRate)
+ self.assertEqual(serialPort.baudRate(QSerialPort.Input), defaultBaudRate)
+ self.assertEqual(serialPort.baudRate(QSerialPort.Output), defaultBaudRate)
+ self.assertEqual(serialPort.dataBits(), QSerialPort.Data8)
+ self.assertEqual(serialPort.parity(), QSerialPort.NoParity)
+ self.assertEqual(serialPort.stopBits(), QSerialPort.OneStop)
+ self.assertEqual(serialPort.flowControl(), QSerialPort.NoFlowControl)
+
+ self.assertEqual(serialPort.pinoutSignals(), QSerialPort.NoSignal)
+ self.assertEqual(serialPort.isRequestToSend(), False)
+ self.assertEqual(serialPort.isDataTerminalReady(), False)
+
+ # QIODevice
+ self.assertEqual(serialPort.openMode(), QIODevice.NotOpen)
+ self.assertTrue(not serialPort.isOpen())
+ self.assertTrue(not serialPort.isReadable())
+ self.assertTrue(not serialPort.isWritable())
+ self.assertTrue(serialPort.isSequential())
+ self.assertEqual(serialPort.canReadLine(), False)
+ self.assertEqual(serialPort.pos(), 0)
+ self.assertEqual(serialPort.size(), 0)
+ self.assertTrue(serialPort.atEnd())
+ self.assertEqual(serialPort.bytesAvailable(), 0)
+ self.assertEqual(serialPort.bytesToWrite(), 0)
+
+ def testOpenExisting(self):
+ allportinfos = QSerialPortInfo.availablePorts()
+ for portinfo in allportinfos:
+ serialPort = QSerialPort(portinfo)
+ self.assertEqual(serialPort.portName(), portinfo.portName())
+
+
+class QSerialPortInfoTest(unittest.TestCase):
+ def test_available_ports(self):
+ allportinfos = QSerialPortInfo.availablePorts()
+ for portinfo in allportinfos:
+ portinfo.description()
+ portinfo.hasProductIdentifier()
+ portinfo.hasVendorIdentifier()
+ portinfo.isNull()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtSpatialAudio/CMakeLists.txt b/sources/pyside6/tests/QtSpatialAudio/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtSpatialAudio/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtSql/CMakeLists.txt b/sources/pyside6/tests/QtSql/CMakeLists.txt
new file mode 100644
index 000000000..eedb31e98
--- /dev/null
+++ b/sources/pyside6/tests/QtSql/CMakeLists.txt
@@ -0,0 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+PYSIDE_TEST(bug_1013.py)
+PYSIDE_TEST(qsqldatabaseandqueries_test.py)
+PYSIDE_TEST(qvarianttype_test.py)
diff --git a/sources/pyside6/tests/QtSql/QtSql.pyproject b/sources/pyside6/tests/QtSql/QtSql.pyproject
new file mode 100644
index 000000000..8282cb404
--- /dev/null
+++ b/sources/pyside6/tests/QtSql/QtSql.pyproject
@@ -0,0 +1,5 @@
+{
+ "files": ["bug_1013.py",
+ "qsqldatabaseandqueries_test.py",
+ "qvarianttype_test.py"]
+}
diff --git a/sources/pyside6/tests/QtSql/bug_1013.py b/sources/pyside6/tests/QtSql/bug_1013.py
new file mode 100644
index 000000000..b47aecb77
--- /dev/null
+++ b/sources/pyside6/tests/QtSql/bug_1013.py
@@ -0,0 +1,43 @@
+# 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 QCoreApplication, QTimer
+from PySide6.QtSql import QSqlDatabase, QSqlQuery, QSqlTableModel
+
+
+class TestBug1013 (unittest.TestCase):
+
+ def someSlot(self, row, record):
+ record.setValue(0, 2)
+ self._wasCalled = True
+
+ def testIt(self):
+ app = QCoreApplication([])
+ db = QSqlDatabase.addDatabase('QSQLITE')
+ db.setDatabaseName(':memory:')
+ db.open()
+ query = QSqlQuery()
+ query.exec('CREATE TABLE "foo" (id INT);')
+ model = QSqlTableModel()
+ model.setTable('foo')
+
+ self._wasCalled = False
+ model.primeInsert.connect(self.someSlot)
+ model.select()
+ QTimer.singleShot(0, lambda: model.insertRow(0) and app.quit())
+ app.exec()
+ self.assertTrue(self._wasCalled)
+ self.assertEqual(model.data(model.index(0, 0)), 2)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtSql/qsqldatabaseandqueries_test.py b/sources/pyside6/tests/QtSql/qsqldatabaseandqueries_test.py
new file mode 100644
index 000000000..a3e70a3a7
--- /dev/null
+++ b/sources/pyside6/tests/QtSql/qsqldatabaseandqueries_test.py
@@ -0,0 +1,86 @@
+#!/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
+
+'''Test cases for QtSql database creation, destruction and queries'''
+
+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.QtSql import QSqlDatabase, QSqlQuery, QSqlTableModel
+from PySide6.QtWidgets import QApplication, QWidget
+from helper.usesqapplication import UsesQApplication
+
+
+class Foo(QWidget):
+ def __init__(self):
+ super().__init__()
+ self.model = QSqlTableModel()
+
+
+class SqlDatabaseCreationDestructionAndQueries(UsesQApplication):
+ '''Test cases for QtSql database creation, destruction and queries'''
+
+ def setUp(self):
+ # Acquire resources
+ super().setUp()
+ self.assertFalse(not QSqlDatabase.drivers(), "installed Qt has no DB drivers")
+ self.assertTrue("QSQLITE" in QSqlDatabase.drivers(), "\"QSQLITE\" driver not available in this Qt version")
+ self.db = QSqlDatabase.addDatabase("QSQLITE")
+ self.db.setDatabaseName(":memory:")
+ self.assertTrue(self.db.open())
+
+ def tearDown(self):
+ # Release resources
+ self.db.close()
+ QSqlDatabase.removeDatabase(":memory:")
+ del self.db
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super().tearDown()
+
+ def testTableCreationAndDestruction(self):
+ # Test table creation and destruction
+ query = QSqlQuery()
+ query.exec("CREATE TABLE dummy(id int primary key, dummyfield varchar(20))")
+ query.exec("DROP TABLE dummy")
+ query.clear()
+
+ def testTableInsertionAndRetrieval(self):
+ # Test table creation, insertion and retrieval
+ query = QSqlQuery()
+ query.exec("CREATE TABLE person(id int primary key, "
+ "firstname varchar(20), lastname varchar(20))")
+ query.exec("INSERT INTO person VALUES(101, 'George', 'Harrison')")
+ query.prepare("INSERT INTO person (id, firstname, lastname) "
+ "VALUES (:id, :firstname, :lastname)")
+ query.bindValue(":id", 102)
+ query.bindValue(":firstname", "John")
+ query.bindValue(":lastname", "Lennon")
+ query.exec()
+
+ lastname = ''
+ query.exec("SELECT lastname FROM person where id=101")
+ self.assertTrue(query.isActive())
+ query.next()
+ lastname = query.value(0)
+ self.assertEqual(lastname, 'Harrison')
+
+ def testTableModelDeletion(self):
+ bar = Foo()
+ model = bar.model
+ del bar
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtSql/qvarianttype_test.py b/sources/pyside6/tests/QtSql/qvarianttype_test.py
new file mode 100644
index 000000000..3999be20e
--- /dev/null
+++ b/sources/pyside6/tests/QtSql/qvarianttype_test.py
@@ -0,0 +1,39 @@
+# 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 cases for QVariant::Type converter'''
+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 QMetaType
+from PySide6.QtSql import QSqlField
+
+
+class QVariantTypeTest(unittest.TestCase):
+ def testQVariantType(self):
+ cmp_id = QMetaType.QString.value
+
+ f = QSqlField("name", QMetaType(QMetaType.QString))
+ self.assertEqual(f.metaType().id(), cmp_id)
+
+ f = QSqlField("name", QMetaType.fromName(b"QString"))
+ self.assertEqual(f.metaType().id(), cmp_id)
+
+ f = QSqlField("name", QMetaType.fromName(b"double"))
+ self.assertEqual(f.metaType(), float)
+
+ f = QSqlField("name", float)
+ self.assertEqual(f.metaType(), float)
+
+ f = QSqlField("name", int)
+ self.assertEqual(f.metaType(), int)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtStateMachine/CMakeLists.txt b/sources/pyside6/tests/QtStateMachine/CMakeLists.txt
new file mode 100644
index 000000000..e42f8cc8b
--- /dev/null
+++ b/sources/pyside6/tests/QtStateMachine/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+PYSIDE_TEST(bug_1031.py)
+PYSIDE_TEST(qabstracttransition_test.py)
+PYSIDE_TEST(qstatemachine_test.py)
+PYSIDE_TEST(qstate_test.py)
+PYSIDE_TEST(setprop_on_ctor_test.py)
diff --git a/sources/pyside6/tests/QtStateMachine/QtStateMachine.pyproject b/sources/pyside6/tests/QtStateMachine/QtStateMachine.pyproject
new file mode 100644
index 000000000..46c1b8b12
--- /dev/null
+++ b/sources/pyside6/tests/QtStateMachine/QtStateMachine.pyproject
@@ -0,0 +1,7 @@
+{
+ "files": ["bug_1031.py",
+ "qabstracttransition_test.py",
+ "qstate_test.py",
+ "qstatemachine_test.py",
+ "setprop_on_ctor_test.py"]
+}
diff --git a/sources/pyside6/tests/QtStateMachine/bug_1031.py b/sources/pyside6/tests/QtStateMachine/bug_1031.py
new file mode 100644
index 000000000..7fe5fc1e6
--- /dev/null
+++ b/sources/pyside6/tests/QtStateMachine/bug_1031.py
@@ -0,0 +1,18 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtStateMachine import QStateMachine, QState
+
+
+mach = QStateMachine()
+state = QState(mach)
+print(state.machine())
diff --git a/sources/pyside6/tests/QtStateMachine/qabstracttransition_test.py b/sources/pyside6/tests/QtStateMachine/qabstracttransition_test.py
new file mode 100644
index 000000000..9c52bfd59
--- /dev/null
+++ b/sources/pyside6/tests/QtStateMachine/qabstracttransition_test.py
@@ -0,0 +1,175 @@
+#!/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.QtCore import (QCoreApplication, QObject, QParallelAnimationGroup,
+ QTimer, SIGNAL)
+from PySide6.QtStateMachine import (QEventTransition, QFinalState, QState,
+ QStateMachine, QSignalTransition)
+
+
+def addStates(transition):
+ sx = QState()
+ sy = QState()
+ transition.setTargetStates([sx, sy])
+
+
+def addAnimation(transition):
+ animation = QParallelAnimationGroup()
+ transition.addAnimation(animation)
+
+
+class QAbstractTransitionTest(unittest.TestCase):
+
+ def testBasic(self):
+ app = QCoreApplication([])
+
+ o = QObject()
+ o.setProperty("text", "INdT")
+
+ machine = QStateMachine()
+ s1 = QState()
+ s1.assignProperty(o, "text", "Rocks")
+
+ s2 = QFinalState()
+ t = s1.addTransition(o, SIGNAL("change()"), s2)
+
+ self.assertEqual(t.targetStates(), [s2])
+
+ addStates(t)
+ self.assertEqual(len(t.targetStates()), 2)
+
+ animation = QParallelAnimationGroup()
+ t.addAnimation(animation)
+
+ self.assertEqual(t.animations(), [animation])
+
+ addAnimation(t)
+ self.assertEqual(t.animations()[0].parent(), None)
+
+ machine.addState(s1)
+ machine.addState(s2)
+ machine.setInitialState(s1)
+ machine.start()
+
+ QTimer.singleShot(100, app.quit)
+ app.exec()
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefCountOfTargetState(self):
+ transition = QEventTransition()
+ state1 = QState()
+ refcount1 = sys.getrefcount(state1)
+
+ transition.setTargetState(state1)
+
+ self.assertEqual(transition.targetState(), state1)
+ self.assertEqual(sys.getrefcount(transition.targetState()), refcount1 + 1)
+
+ state2 = QState()
+ refcount2 = sys.getrefcount(state2)
+
+ transition.setTargetState(state2)
+
+ self.assertEqual(transition.targetState(), state2)
+ self.assertEqual(sys.getrefcount(transition.targetState()), refcount2 + 1)
+ self.assertEqual(sys.getrefcount(state1), refcount1)
+
+ del transition
+
+ self.assertEqual(sys.getrefcount(state2), refcount2)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefCountOfTargetStates(self):
+ transition = QEventTransition()
+ state1 = QState()
+ state2 = QState()
+ states = [state1, state2]
+ refcount1 = sys.getrefcount(state1)
+ refcount2 = sys.getrefcount(state2)
+
+ transition.setTargetStates(states)
+
+ self.assertEqual(transition.targetStates(), states)
+ self.assertEqual(transition.targetState(), state1)
+ self.assertEqual(sys.getrefcount(transition.targetStates()[0]), refcount1 + 1)
+ self.assertEqual(sys.getrefcount(transition.targetStates()[1]), refcount2 + 1)
+
+ del states
+ del transition
+
+ self.assertEqual(sys.getrefcount(state1), refcount1 - 1)
+ self.assertEqual(sys.getrefcount(state2), refcount2 - 1)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefCountOfTargetStatesAfterSingleTargetState(self):
+ transition = QEventTransition()
+ state0 = QState()
+ refcount0 = sys.getrefcount(state0)
+
+ transition.setTargetState(state0)
+
+ self.assertEqual(transition.targetState(), state0)
+ self.assertEqual(sys.getrefcount(transition.targetState()), refcount0 + 1)
+
+ state1 = QState()
+ state2 = QState()
+ states = [state1, state2]
+ refcount1 = sys.getrefcount(state1)
+ refcount2 = sys.getrefcount(state2)
+
+ transition.setTargetStates(states)
+
+ self.assertEqual(sys.getrefcount(state0), refcount0)
+ self.assertEqual(transition.targetStates(), states)
+ self.assertEqual(transition.targetState(), state1)
+ self.assertEqual(sys.getrefcount(transition.targetStates()[0]), refcount1 + 1)
+ self.assertEqual(sys.getrefcount(transition.targetStates()[1]), refcount2 + 1)
+
+ del states
+ del transition
+
+ self.assertEqual(sys.getrefcount(state1), refcount1 - 1)
+ self.assertEqual(sys.getrefcount(state2), refcount2 - 1)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefCountOfTargetStatesBeforeSingleTargetState(self):
+ transition = QEventTransition()
+ state1 = QState()
+ state2 = QState()
+ states = [state1, state2]
+ refcount1 = sys.getrefcount(state1)
+ refcount2 = sys.getrefcount(state2)
+
+ transition.setTargetStates(states)
+
+ self.assertEqual(transition.targetStates(), states)
+ self.assertEqual(transition.targetState(), state1)
+ self.assertEqual(sys.getrefcount(transition.targetStates()[0]), refcount1 + 1)
+ self.assertEqual(sys.getrefcount(transition.targetStates()[1]), refcount2 + 1)
+
+ state3 = QState()
+ refcount3 = sys.getrefcount(state3)
+
+ transition.setTargetState(state3)
+
+ self.assertEqual(transition.targetState(), state3)
+ self.assertEqual(sys.getrefcount(transition.targetState()), refcount3 + 1)
+
+ del states
+
+ self.assertEqual(sys.getrefcount(state1), refcount1 - 1)
+ self.assertEqual(sys.getrefcount(state2), refcount2 - 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtStateMachine/qstate_test.py b/sources/pyside6/tests/QtStateMachine/qstate_test.py
new file mode 100644
index 000000000..4a33141c8
--- /dev/null
+++ b/sources/pyside6/tests/QtStateMachine/qstate_test.py
@@ -0,0 +1,49 @@
+#!/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.QtCore import QCoreApplication, QObject, SIGNAL, QTimer
+from PySide6.QtStateMachine import (QEventTransition, QFinalState, QState,
+ QStateMachine, QSignalTransition)
+
+
+class QStateTest(unittest.TestCase):
+ def testBasic(self):
+ app = QCoreApplication([])
+
+ o = QObject()
+ o.setProperty("text", "INdT")
+
+ machine = QStateMachine()
+ s1 = QState()
+ s1.assignProperty(o, "text", "Rocks")
+
+ s2 = QFinalState()
+ t = s1.addTransition(o, SIGNAL("change()"), s2)
+ self.assertTrue(isinstance(t, QSignalTransition))
+
+ machine.addState(s1)
+ machine.addState(s2)
+ machine.setInitialState(s1)
+ machine.start()
+
+ o.emit(SIGNAL("change()"))
+
+ QTimer.singleShot(100, app.quit)
+ app.exec()
+
+ txt = o.property("text")
+ self.assertTrue(txt, "Rocks")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtStateMachine/qstatemachine_test.py b/sources/pyside6/tests/QtStateMachine/qstatemachine_test.py
new file mode 100644
index 000000000..5e17b3a1f
--- /dev/null
+++ b/sources/pyside6/tests/QtStateMachine/qstatemachine_test.py
@@ -0,0 +1,68 @@
+#!/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.QtCore import (QObject, QParallelAnimationGroup,
+ QPropertyAnimation, QTimer, SIGNAL)
+from PySide6.QtStateMachine import (QFinalState, QState, QStateMachine)
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QStateMachineTest(UsesQApplication):
+
+ def cb(self, *args):
+ self.assertEqual(self.machine.defaultAnimations(), [self.anim])
+
+ def testBasic(self):
+ self.machine = QStateMachine()
+ s1 = QState()
+ s2 = QState()
+ s3 = QFinalState()
+
+ self.machine.started.connect(self.cb)
+
+ self.anim = QParallelAnimationGroup()
+
+ self.machine.addState(s1)
+ self.machine.addState(s2)
+ self.machine.addState(s3)
+ self.machine.setInitialState(s1)
+ self.machine.addDefaultAnimation(self.anim)
+ self.machine.start()
+
+ QTimer.singleShot(100, self.app.quit)
+ self.app.exec()
+
+
+class QSetConverterTest(UsesQApplication):
+ '''Test converter of QSet toPython using QStateAnimation.configuration'''
+
+ def testBasic(self):
+ '''QStateMachine.configuration converting QSet to python set'''
+ machine = QStateMachine()
+ s1 = QState()
+ machine.addState(s1)
+ machine.setInitialState(s1)
+ machine.start()
+
+ QTimer.singleShot(100, self.app.quit)
+ self.app.exec()
+
+ configuration = machine.configuration()
+
+ self.assertTrue(isinstance(configuration, set))
+ self.assertTrue(s1 in configuration)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtStateMachine/setprop_on_ctor_test.py b/sources/pyside6/tests/QtStateMachine/setprop_on_ctor_test.py
new file mode 100644
index 000000000..48f397282
--- /dev/null
+++ b/sources/pyside6/tests/QtStateMachine/setprop_on_ctor_test.py
@@ -0,0 +1,24 @@
+#!/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.QtStateMachine import QEventTransition, QState
+
+
+class SetPropOnCtorTest(unittest.TestCase):
+ def testIt(self):
+ obj = QEventTransition(targetStates=[QState()])
+ self.assertEqual(len(obj.targetStates()), 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtSvg/CMakeLists.txt b/sources/pyside6/tests/QtSvg/CMakeLists.txt
new file mode 100644
index 000000000..53d15e857
--- /dev/null
+++ b/sources/pyside6/tests/QtSvg/CMakeLists.txt
@@ -0,0 +1,2 @@
+PYSIDE_TEST(qsvggenerator_test.py)
+PYSIDE_TEST(qsvgrenderer_test.py)
diff --git a/sources/pyside6/tests/QtSvg/QtSvg.pyproject b/sources/pyside6/tests/QtSvg/QtSvg.pyproject
new file mode 100644
index 000000000..9bc41d710
--- /dev/null
+++ b/sources/pyside6/tests/QtSvg/QtSvg.pyproject
@@ -0,0 +1,4 @@
+{
+ "files": ["qsvggenerator_test.py",
+ "qsvgrenderer_test.py"]
+}
diff --git a/sources/pyside6/tests/QtSvg/qsvggenerator_test.py b/sources/pyside6/tests/QtSvg/qsvggenerator_test.py
new file mode 100644
index 000000000..a06cefb37
--- /dev/null
+++ b/sources/pyside6/tests/QtSvg/qsvggenerator_test.py
@@ -0,0 +1,47 @@
+#!/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.QtCore import QBuffer
+from PySide6.QtSvg import QSvgGenerator
+
+
+class QSvgGeneratorTest(unittest.TestCase):
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefCountOfTOutputDevice(self):
+ generator = QSvgGenerator()
+ iodevice1 = QBuffer()
+ refcount1 = sys.getrefcount(iodevice1)
+
+ generator.setOutputDevice(iodevice1)
+
+ self.assertEqual(generator.outputDevice(), iodevice1)
+ self.assertEqual(sys.getrefcount(generator.outputDevice()), refcount1 + 1)
+
+ iodevice2 = QBuffer()
+ refcount2 = sys.getrefcount(iodevice2)
+
+ generator.setOutputDevice(iodevice2)
+
+ self.assertEqual(generator.outputDevice(), iodevice2)
+ self.assertEqual(sys.getrefcount(generator.outputDevice()), refcount2 + 1)
+ self.assertEqual(sys.getrefcount(iodevice1), refcount1)
+
+ del generator
+
+ self.assertEqual(sys.getrefcount(iodevice2), refcount2)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtSvg/qsvgrenderer_test.py b/sources/pyside6/tests/QtSvg/qsvgrenderer_test.py
new file mode 100644
index 000000000..b4422001f
--- /dev/null
+++ b/sources/pyside6/tests/QtSvg/qsvgrenderer_test.py
@@ -0,0 +1,37 @@
+#!/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.QtCore import QFile
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtSvg import QSvgRenderer
+
+
+class QSvgRendererTest(unittest.TestCase):
+
+ def testLoad(self):
+ tigerPath = os.path.join(os.path.dirname(__file__), 'tiger.svg')
+ app = QGuiApplication([])
+
+ fromFile = QSvgRenderer(tigerPath)
+ self.assertTrue(fromFile.isValid())
+
+ tigerFile = QFile(tigerPath)
+ tigerFile.open(QFile.ReadOnly)
+ tigerData = tigerFile.readAll()
+ fromContents = QSvgRenderer(tigerData)
+ self.assertTrue(fromContents.isValid())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtSvg/tiger.svg b/sources/pyside6/tests/QtSvg/tiger.svg
new file mode 100644
index 000000000..681fbd209
--- /dev/null
+++ b/sources/pyside6/tests/QtSvg/tiger.svg
@@ -0,0 +1,730 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ height="800">
+ <g transform="translate(200,200)" style="fill-opacity:1; fill:none;">
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-122.304 84.285C-122.304 84.285 -122.203 86.179 -123.027 86.16C-123.851 86.141 -140.305 38.066 -160.833 40.309C-160.833 40.309 -143.05 32.956 -122.304 84.285z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-118.774 81.262C-118.774 81.262 -119.323 83.078 -120.092 82.779C-120.86 82.481 -119.977 31.675 -140.043 26.801C-140.043 26.801 -120.82 25.937 -118.774 81.262z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-91.284 123.59C-91.284 123.59 -89.648 124.55 -90.118 125.227C-90.589 125.904 -139.763 113.102 -149.218 131.459C-149.218 131.459 -145.539 112.572 -91.284 123.59z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-94.093 133.801C-94.093 133.801 -92.237 134.197 -92.471 134.988C-92.704 135.779 -143.407 139.121 -146.597 159.522C-146.597 159.522 -149.055 140.437 -94.093 133.801z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-98.304 128.276C-98.304 128.276 -96.526 128.939 -96.872 129.687C-97.218 130.435 -147.866 126.346 -153.998 146.064C-153.998 146.064 -153.646 126.825 -98.304 128.276z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-109.009 110.072C-109.009 110.072 -107.701 111.446 -108.34 111.967C-108.979 112.488 -152.722 86.634 -166.869 101.676C-166.869 101.676 -158.128 84.533 -109.009 110.072z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-116.554 114.263C-116.554 114.263 -115.098 115.48 -115.674 116.071C-116.25 116.661 -162.638 95.922 -174.992 112.469C-174.992 112.469 -168.247 94.447 -116.554 114.263z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-119.154 118.335C-119.154 118.335 -117.546 119.343 -118.036 120.006C-118.526 120.669 -167.308 106.446 -177.291 124.522C-177.291 124.522 -173.066 105.749 -119.154 118.335z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-108.42 118.949C-108.42 118.949 -107.298 120.48 -107.999 120.915C-108.7 121.35 -148.769 90.102 -164.727 103.207C-164.727 103.207 -153.862 87.326 -108.42 118.949z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-128.2 90C-128.2 90 -127.6 91.8 -128.4 92C-129.2 92.2 -157.8 50.2 -177.001 57.8C-177.001 57.8 -161.8 46 -128.2 90z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-127.505 96.979C-127.505 96.979 -126.53 98.608 -127.269 98.975C-128.007 99.343 -164.992 64.499 -182.101 76.061C-182.101 76.061 -169.804 61.261 -127.505 96.979z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
+ <path d="M-127.62 101.349C-127.62 101.349 -126.498 102.88 -127.199 103.315C-127.9 103.749 -167.969 72.502 -183.927 85.607C-183.927 85.607 -173.062 69.726 -127.62 101.349z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000">
+ <path d="M-129.83 103.065C-129.327 109.113 -128.339 115.682 -126.6 118.801C-126.6 118.801 -130.2 131.201 -121.4 144.401C-121.4 144.401 -121.8 151.601 -120.2 154.801C-120.2 154.801 -116.2 163.201 -111.4 164.001C-107.516 164.648 -98.793 167.717 -88.932 169.121C-88.932 169.121 -71.8 183.201 -75 196.001C-75 196.001 -75.4 212.401 -79 214.001C-79 214.001 -67.4 202.801 -77 219.601L-81.4 238.401C-81.4 238.401 -55.8 216.801 -71.4 235.201L-81.4 261.201C-81.4 261.201 -61.8 242.801 -69 251.201L-72.2 260.001C-72.2 260.001 -29 232.801 -59.8 262.401C-59.8 262.401 -51.8 258.801 -47.4 261.601C-47.4 261.601 -40.6 260.401 -41.4 262.001C-41.4 262.001 -62.2 272.401 -65.8 290.801C-65.8 290.801 -57.4 280.801 -60.6 291.601L-60.2 303.201C-60.2 303.201 -56.2 281.601 -56.6 319.201C-56.6 319.201 -37.4 301.201 -49 322.001L-49 338.801C-49 338.801 -33.8 322.401 -40.2 335.201C-40.2 335.201 -30.2 326.401 -34.2 341.601C-34.2 341.601 -35 352.001 -30.6 340.801C-30.6 340.801 -14.6 310.201 -20.6 336.401C-20.6 336.401 -21.4 355.601 -16.6 340.801C-16.6 340.801 -16.2 351.201 -7 358.401C-7 358.401 -8.2 307.601 4.6 343.601L8.6 360.001C8.6 360.001 11.4 350.801 11 345.601C11 345.601 25.8 329.201 19 353.601C19 353.601 34.2 330.801 31 344.001C31 344.001 23.4 360.001 25 364.801C25 364.801 41.8 330.001 43 328.401C43 328.401 41 370.802 51.8 334.801C51.8 334.801 57.4 346.801 54.6 351.201C54.6 351.201 62.6 343.201 61.8 340.001C61.8 340.001 66.4 331.801 69.2 345.401C69.2 345.401 71 354.801 72.6 351.601C72.6 351.601 76.6 375.602 77.8 352.801C77.8 352.801 79.4 339.201 72.2 327.601C72.2 327.601 73 324.401 70.2 320.401C70.2 320.401 83.8 342.001 76.6 313.201C76.6 313.201 87.801 321.201 89.001 321.201C89.001 321.201 75.4 298.001 84.2 302.801C84.2 302.801 79 292.401 97.001 304.401C97.001 304.401 81 288.401 98.601 298.001C98.601 298.001 106.601 304.401 99.001 294.401C99.001 294.401 84.6 278.401 106.601 296.401C106.601 296.401 118.201 312.801 119.001 315.601C119.001 315.601 109.001 286.401 104.601 283.601C104.601 283.601 113.001 247.201 154.201 262.801C154.201 262.801 161.001 280.001 165.401 261.601C165.401 261.601 178.201 255.201 189.401 282.801C189.401 282.801 193.401 269.201 192.601 266.401C192.601 266.401 199.401 267.601 198.601 266.401C198.601 266.401 211.801 270.801 213.001 270.001C213.001 270.001 219.801 276.801 220.201 273.201C220.201 273.201 229.401 276.001 227.401 272.401C227.401 272.401 236.201 288.001 236.601 291.601L239.001 277.601L241.001 280.401C241.001 280.401 242.601 272.801 241.801 271.601C241.001 270.401 261.801 278.401 266.601 299.201L268.601 307.601C268.601 307.601 274.601 292.801 273.001 288.801C273.001 288.801 278.201 289.601 278.601 294.001C278.601 294.001 282.601 270.801 277.801 264.801C277.801 264.801 282.201 264.001 283.401 267.601L283.401 260.401C283.401 260.401 290.601 261.201 290.601 258.801C290.601 258.801 295.001 254.801 297.001 259.601C297.001 259.601 284.601 224.401 303.001 243.601C303.001 243.601 310.201 254.401 306.601 235.601C303.001 216.801 299.001 215.201 303.801 214.801C303.801 214.801 304.601 211.201 302.601 209.601C300.601 208.001 303.801 209.601 303.801 209.601C303.801 209.601 308.601 213.601 303.401 191.601C303.401 191.601 309.801 193.201 297.801 164.001C297.801 164.001 300.601 161.601 296.601 153.201C296.601 153.201 304.601 157.601 307.401 156.001C307.401 156.001 307.001 154.401 303.801 150.401C303.801 150.401 282.201 95.6 302.601 117.601C302.601 117.601 314.451 131.151 308.051 108.351C308.051 108.351 298.94 84.341 299.717 80.045L-129.83 103.065z"/>
+ </g>
+ <g style="fill: #cc7226; stroke:#000000">
+ <path d="M299.717 80.245C300.345 80.426 302.551 81.55 303.801 83.2C303.801 83.2 310.601 94 305.401 75.6C305.401 75.6 296.201 46.8 305.001 58C305.001 58 311.001 65.2 307.801 51.6C303.936 35.173 301.401 28.8 301.401 28.8C301.401 28.8 313.001 33.6 286.201 -6L295.001 -2.4C295.001 -2.4 275.401 -42 253.801 -47.2L245.801 -53.2C245.801 -53.2 284.201 -91.2 271.401 -128C271.401 -128 264.601 -133.2 255.001 -124C255.001 -124 248.601 -119.2 242.601 -120.8C242.601 -120.8 211.801 -119.6 209.801 -119.6C207.801 -119.6 173.001 -156.8 107.401 -139.2C107.401 -139.2 102.201 -137.2 97.801 -138.4C97.801 -138.4 79.4 -154.4 30.6 -131.6C30.6 -131.6 20.6 -129.6 19 -129.6C17.4 -129.6 14.6 -129.6 6.6 -123.2C-1.4 -116.8 -1.8 -116 -3.8 -114.4C-3.8 -114.4 -20.2 -103.2 -25 -102.4C-25 -102.4 -36.6 -96 -41 -86L-44.6 -84.8C-44.6 -84.8 -46.2 -77.6 -46.6 -76.4C-46.6 -76.4 -51.4 -72.8 -52.2 -67.2C-52.2 -67.2 -61 -61.2 -60.6 -56.8C-60.6 -56.8 -62.2 -51.6 -63 -46.8C-63 -46.8 -70.2 -42 -69.4 -39.2C-69.4 -39.2 -77 -25.2 -75.8 -18.4C-75.8 -18.4 -82.2 -18.8 -85 -16.4C-85 -16.4 -85.8 -11.6 -87.4 -11.2C-87.4 -11.2 -90.2 -10 -87.8 -6C-87.8 -6 -89.4 -3.2 -89.8 -1.6C-89.8 -1.6 -89 1.2 -93.4 6.8C-93.4 6.8 -99.8 25.6 -97.8 30.8C-97.8 30.8 -97.4 35.6 -100.2 37.2C-100.2 37.2 -103.8 36.8 -95.4 48.8C-95.4 48.8 -94.6 50 -97.8 52.4C-97.8 52.4 -115 56 -117.4 72.4C-117.4 72.4 -131 87.2 -131 92.4C-131 94.705 -130.729 97.852 -130.03 102.465C-130.03 102.465 -130.6 110.801 -103 111.601C-75.4 112.401 299.717 80.245 299.717 80.245z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M-115.6 102.6C-140.6 63.2 -126.2 119.601 -126.2 119.601C-117.4 154.001 12.2 116.401 12.2 116.401C12.2 116.401 181.001 86 192.201 82C203.401 78 298.601 84.4 298.601 84.4L293.001 67.6C228.201 21.2 209.001 44.4 195.401 40.4C181.801 36.4 184.201 46 181.001 46.8C177.801 47.6 138.601 22.8 132.201 23.6C125.801 24.4 100.459 0.649 115.401 32.4C131.401 66.4 57 71.6 40.2 60.4C23.4 49.2 47.4 78.8 47.4 78.8C65.8 98.8 31.4 82 31.4 82C-3 69.2 -27 94.8 -30.2 95.6C-33.4 96.4 -38.2 99.6 -39 93.2C-39.8 86.8 -47.31 70.099 -79 96.4C-99 113.001 -112.8 91 -112.8 91L-115.6 102.6z"/>
+ </g>
+ <g style="fill: #e87f3a">
+ <path d="M133.51 25.346C127.11 26.146 101.743 2.407 116.71 34.146C133.31 69.346 58.31 73.346 41.51 62.146C24.709 50.946 48.71 80.546 48.71 80.546C67.11 100.546 32.709 83.746 32.709 83.746C-1.691 70.946 -25.691 96.546 -28.891 97.346C-32.091 98.146 -36.891 101.346 -37.691 94.946C-38.491 88.546 -45.87 72.012 -77.691 98.146C-98.927 115.492 -112.418 94.037 -112.418 94.037L-115.618 104.146C-140.618 64.346 -125.546 122.655 -125.546 122.655C-116.745 157.056 13.509 118.146 13.509 118.146C13.509 118.146 182.31 87.746 193.51 83.746C204.71 79.746 299.038 86.073 299.038 86.073L293.51 68.764C228.71 22.364 210.31 46.146 196.71 42.146C183.11 38.146 185.51 47.746 182.31 48.546C179.11 49.346 139.91 24.546 133.51 25.346z"/>
+ </g>
+ <g style="fill: #ea8c4d">
+ <path d="M134.819 27.091C128.419 27.891 103.685 3.862 118.019 35.891C134.219 72.092 59.619 75.092 42.819 63.892C26.019 52.692 50.019 82.292 50.019 82.292C68.419 102.292 34.019 85.492 34.019 85.492C-0.381 72.692 -24.382 98.292 -27.582 99.092C-30.782 99.892 -35.582 103.092 -36.382 96.692C-37.182 90.292 -44.43 73.925 -76.382 99.892C-98.855 117.983 -112.036 97.074 -112.036 97.074L-115.636 105.692C-139.436 66.692 -124.891 125.71 -124.891 125.71C-116.091 160.11 14.819 119.892 14.819 119.892C14.819 119.892 183.619 89.492 194.819 85.492C206.019 81.492 299.474 87.746 299.474 87.746L294.02 69.928C229.219 23.528 211.619 47.891 198.019 43.891C184.419 39.891 186.819 49.491 183.619 50.292C180.419 51.092 141.219 26.291 134.819 27.091z"/>
+ </g>
+ <g style="fill: #ec9961">
+ <path d="M136.128 28.837C129.728 29.637 104.999 5.605 119.328 37.637C136.128 75.193 60.394 76.482 44.128 65.637C27.328 54.437 51.328 84.037 51.328 84.037C69.728 104.037 35.328 87.237 35.328 87.237C0.928 74.437 -23.072 100.037 -26.272 100.837C-29.472 101.637 -34.272 104.837 -35.072 98.437C-35.872 92.037 -42.989 75.839 -75.073 101.637C-98.782 120.474 -111.655 100.11 -111.655 100.11L-115.655 107.237C-137.455 70.437 -124.236 128.765 -124.236 128.765C-115.436 163.165 16.128 121.637 16.128 121.637C16.128 121.637 184.928 91.237 196.129 87.237C207.329 83.237 299.911 89.419 299.911 89.419L294.529 71.092C229.729 24.691 212.929 49.637 199.329 45.637C185.728 41.637 188.128 51.237 184.928 52.037C181.728 52.837 142.528 28.037 136.128 28.837z"/>
+ </g>
+ <g style="fill: #eea575">
+ <path d="M137.438 30.583C131.037 31.383 106.814 7.129 120.637 39.383C137.438 78.583 62.237 78.583 45.437 67.383C28.637 56.183 52.637 85.783 52.637 85.783C71.037 105.783 36.637 88.983 36.637 88.983C2.237 76.183 -21.763 101.783 -24.963 102.583C-28.163 103.383 -32.963 106.583 -33.763 100.183C-34.563 93.783 -41.548 77.752 -73.763 103.383C-98.709 122.965 -111.273 103.146 -111.273 103.146L-115.673 108.783C-135.473 73.982 -123.582 131.819 -123.582 131.819C-114.782 166.22 17.437 123.383 17.437 123.383C17.437 123.383 186.238 92.983 197.438 88.983C208.638 84.983 300.347 91.092 300.347 91.092L295.038 72.255C230.238 25.855 214.238 51.383 200.638 47.383C187.038 43.383 189.438 52.983 186.238 53.783C183.038 54.583 143.838 29.783 137.438 30.583z"/>
+ </g>
+ <g style="fill: #f1b288">
+ <path d="M138.747 32.328C132.347 33.128 106.383 9.677 121.947 41.128C141.147 79.928 63.546 80.328 46.746 69.128C29.946 57.928 53.946 87.528 53.946 87.528C72.346 107.528 37.946 90.728 37.946 90.728C3.546 77.928 -20.454 103.528 -23.654 104.328C-26.854 105.128 -31.654 108.328 -32.454 101.928C-33.254 95.528 -40.108 79.665 -72.454 105.128C-98.636 125.456 -110.891 106.183 -110.891 106.183L-115.691 110.328C-133.691 77.128 -122.927 134.874 -122.927 134.874C-114.127 169.274 18.746 125.128 18.746 125.128C18.746 125.128 187.547 94.728 198.747 90.728C209.947 86.728 300.783 92.764 300.783 92.764L295.547 73.419C230.747 27.019 215.547 53.128 201.947 49.128C188.347 45.128 190.747 54.728 187.547 55.528C184.347 56.328 145.147 31.528 138.747 32.328z"/>
+ </g>
+ <g style="fill: #f3bf9c">
+ <path d="M140.056 34.073C133.655 34.873 107.313 11.613 123.255 42.873C143.656 82.874 64.855 82.074 48.055 70.874C31.255 59.674 55.255 89.274 55.255 89.274C73.655 109.274 39.255 92.474 39.255 92.474C4.855 79.674 -19.145 105.274 -22.345 106.074C-25.545 106.874 -30.345 110.074 -31.145 103.674C-31.945 97.274 -38.668 81.578 -71.145 106.874C-98.564 127.947 -110.509 109.219 -110.509 109.219L-115.709 111.874C-131.709 81.674 -122.273 137.929 -122.273 137.929C-113.473 172.329 20.055 126.874 20.055 126.874C20.055 126.874 188.856 96.474 200.056 92.474C211.256 88.474 301.22 94.437 301.22 94.437L296.056 74.583C231.256 28.183 216.856 54.874 203.256 50.874C189.656 46.873 192.056 56.474 188.856 57.274C185.656 58.074 146.456 33.273 140.056 34.073z"/>
+ </g>
+ <g style="fill: #f5ccb0">
+ <path d="M141.365 35.819C134.965 36.619 107.523 13.944 124.565 44.619C146.565 84.219 66.164 83.819 49.364 72.619C32.564 61.419 56.564 91.019 56.564 91.019C74.964 111.019 40.564 94.219 40.564 94.219C6.164 81.419 -17.836 107.019 -21.036 107.819C-24.236 108.619 -29.036 111.819 -29.836 105.419C-30.636 99.019 -37.227 83.492 -69.836 108.619C-98.491 130.438 -110.127 112.256 -110.127 112.256L-115.727 113.419C-130.128 85.019 -121.618 140.983 -121.618 140.983C-112.818 175.384 21.364 128.619 21.364 128.619C21.364 128.619 190.165 98.219 201.365 94.219C212.565 90.219 301.656 96.11 301.656 96.11L296.565 75.746C231.765 29.346 218.165 56.619 204.565 52.619C190.965 48.619 193.365 58.219 190.165 59.019C186.965 59.819 147.765 35.019 141.365 35.819z"/>
+ </g>
+ <g style="fill: #f8d8c4">
+ <path d="M142.674 37.565C136.274 38.365 108.832 15.689 125.874 46.365C147.874 85.965 67.474 85.565 50.674 74.365C33.874 63.165 57.874 92.765 57.874 92.765C76.274 112.765 41.874 95.965 41.874 95.965C7.473 83.165 -16.527 108.765 -19.727 109.565C-22.927 110.365 -27.727 113.565 -28.527 107.165C-29.327 100.765 -35.786 85.405 -68.527 110.365C-98.418 132.929 -109.745 115.293 -109.745 115.293L-115.745 114.965C-129.346 88.564 -120.963 144.038 -120.963 144.038C-112.163 178.438 22.673 130.365 22.673 130.365C22.673 130.365 191.474 99.965 202.674 95.965C213.874 91.965 302.093 97.783 302.093 97.783L297.075 76.91C232.274 30.51 219.474 58.365 205.874 54.365C192.274 50.365 194.674 59.965 191.474 60.765C188.274 61.565 149.074 36.765 142.674 37.565z"/>
+ </g>
+ <g style="fill: #fae5d7">
+ <path d="M143.983 39.31C137.583 40.11 110.529 17.223 127.183 48.11C149.183 88.91 68.783 87.31 51.983 76.11C35.183 64.91 59.183 94.51 59.183 94.51C77.583 114.51 43.183 97.71 43.183 97.71C8.783 84.91 -15.217 110.51 -18.417 111.31C-21.618 112.11 -26.418 115.31 -27.218 108.91C-28.018 102.51 -34.346 87.318 -67.218 112.11C-98.345 135.42 -109.363 118.329 -109.363 118.329L-115.764 116.51C-128.764 92.51 -120.309 147.093 -120.309 147.093C-111.509 181.493 23.983 132.11 23.983 132.11C23.983 132.11 192.783 101.71 203.983 97.71C215.183 93.71 302.529 99.456 302.529 99.456L297.583 78.074C232.783 31.673 220.783 60.11 207.183 56.11C193.583 52.11 195.983 61.71 192.783 62.51C189.583 63.31 150.383 38.51 143.983 39.31z"/>
+ </g>
+ <g style="fill: #fcf2eb">
+ <path d="M145.292 41.055C138.892 41.855 112.917 18.411 128.492 49.855C149.692 92.656 70.092 89.056 53.292 77.856C36.492 66.656 60.492 96.256 60.492 96.256C78.892 116.256 44.492 99.456 44.492 99.456C10.092 86.656 -13.908 112.256 -17.108 113.056C-20.308 113.856 -25.108 117.056 -25.908 110.656C-26.708 104.256 -32.905 89.232 -65.908 113.856C-98.273 137.911 -108.982 121.365 -108.982 121.365L-115.782 118.056C-128.582 94.856 -119.654 150.147 -119.654 150.147C-110.854 184.547 25.292 133.856 25.292 133.856C25.292 133.856 194.093 103.456 205.293 99.456C216.493 95.456 302.965 101.128 302.965 101.128L298.093 79.237C233.292 32.837 222.093 61.856 208.493 57.856C194.893 53.855 197.293 63.456 194.093 64.256C190.892 65.056 151.692 40.255 145.292 41.055z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M-115.8 119.601C-128.6 97.6 -119 153.201 -119 153.201C-110.2 187.601 26.6 135.601 26.6 135.601C26.6 135.601 195.401 105.2 206.601 101.2C217.801 97.2 303.401 102.8 303.401 102.8L298.601 80.4C233.801 34 223.401 63.6 209.801 59.6C196.201 55.6 198.601 65.2 195.401 66C192.201 66.8 153.001 42 146.601 42.8C140.201 43.6 114.981 19.793 129.801 51.6C152.028 99.307 69.041 89.227 54.6 79.6C37.8 68.4 61.8 98 61.8 98C80.2 118.001 45.8 101.2 45.8 101.2C11.4 88.4 -12.6 114.001 -15.8 114.801C-19 115.601 -23.8 118.801 -24.6 112.401C-25.4 106 -31.465 91.144 -64.6 115.601C-98.2 140.401 -108.6 124.401 -108.6 124.401L-115.8 119.601z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-74.2 149.601C-74.2 149.601 -81.4 161.201 -60.6 174.401C-60.6 174.401 -59.2 175.801 -77.2 171.601C-77.2 171.601 -83.4 169.601 -85 159.201C-85 159.201 -89.8 154.801 -94.6 149.201C-99.4 143.601 -74.2 149.601 -74.2 149.601z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M65.8 102C65.8 102 83.498 128.821 82.9 133.601C81.6 144.001 81.4 153.601 84.6 157.601C87.801 161.601 96.601 194.801 96.601 194.801C96.601 194.801 96.201 196.001 108.601 158.001C108.601 158.001 120.201 142.001 100.201 123.601C100.201 123.601 65 94.8 65.8 102z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-54.2 176.401C-54.2 176.401 -43 183.601 -57.4 214.801L-51 212.401C-51 212.401 -51.8 223.601 -55 226.001L-47.8 222.801C-47.8 222.801 -43 230.801 -47 235.601C-47 235.601 -30.2 243.601 -31 250.001C-31 250.001 -24.6 242.001 -28.6 235.601C-32.6 229.201 -39.8 233.201 -39 214.801L-47.8 218.001C-47.8 218.001 -42.2 209.201 -42.2 202.801L-50.2 205.201C-50.2 205.201 -34.731 178.623 -45.4 177.201C-51.4 176.401 -54.2 176.401 -54.2 176.401z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-21.8 193.201C-21.8 193.201 -19 188.801 -21.8 189.601C-24.6 190.401 -55.8 205.201 -61.8 214.801C-61.8 214.801 -27.4 190.401 -21.8 193.201z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-11.4 201.201C-11.4 201.201 -8.6 196.801 -11.4 197.601C-14.2 198.401 -45.4 213.201 -51.4 222.801C-51.4 222.801 -17 198.401 -11.4 201.201z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M1.8 186.001C1.8 186.001 4.6 181.601 1.8 182.401C-1 183.201 -32.2 198.001 -38.2 207.601C-38.2 207.601 -3.8 183.201 1.8 186.001z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-21.4 229.601C-21.4 229.601 -21.4 223.601 -24.2 224.401C-27 225.201 -63 242.801 -69 252.401C-69 252.401 -27 226.801 -21.4 229.601z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-20.2 218.801C-20.2 218.801 -19 214.001 -21.8 214.801C-23.8 214.801 -50.2 226.401 -56.2 236.001C-56.2 236.001 -26.6 214.401 -20.2 218.801z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-34.6 266.401L-44.6 274.001C-44.6 274.001 -34.2 266.401 -30.6 267.601C-30.6 267.601 -37.4 278.801 -38.2 284.001C-38.2 284.001 -27.8 271.201 -22.2 271.601C-22.2 271.601 -14.6 272.001 -14.6 282.801C-14.6 282.801 -9 272.401 -5.8 272.801C-5.8 272.801 -4.6 279.201 -5.8 286.001C-5.8 286.001 -1.8 278.401 2.2 280.001C2.2 280.001 8.6 278.001 7.8 289.601C7.8 289.601 7.8 300.001 7 302.801C7 302.801 12.6 276.401 15 276.001C15 276.001 23 274.801 27.8 283.601C27.8 283.601 23.8 276.001 28.6 278.001C28.6 278.001 39.4 279.601 42.6 286.401C42.6 286.401 35.8 274.401 41.4 277.601C41.4 277.601 48.2 277.601 49.4 284.001C49.4 284.001 57.8 305.201 59.8 306.801C59.8 306.801 52.2 285.201 53.8 285.201C53.8 285.201 51.8 273.201 57 288.001C57 288.001 53.8 274.001 59.4 274.801C65 275.601 69.4 285.601 77.8 283.201C77.8 283.201 87.401 288.801 89.401 219.601L-34.6 266.401z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-29.8 173.601C-29.8 173.601 -15 167.601 25 173.601C25 173.601 32.2 174.001 39 165.201C45.8 156.401 72.6 149.201 79 151.201L88.601 157.601L89.401 158.801C89.401 158.801 101.801 169.201 102.201 176.801C102.601 184.401 87.801 232.401 78.2 248.401C68.6 264.401 59 276.801 39.8 274.401C39.8 274.401 19 270.401 -6.6 274.401C-6.6 274.401 -35.8 272.801 -38.6 264.801C-41.4 256.801 -27.4 241.601 -27.4 241.601C-27.4 241.601 -23 233.201 -24.2 218.801C-25.4 204.401 -25 176.401 -29.8 173.601z"/>
+ </g>
+ <g style="fill: #e5668c">
+ <path d="M-7.8 175.601C0.6 194.001 -29 259.201 -29 259.201C-31 260.801 -16.34 266.846 -6.2 264.401C4.746 261.763 45 266.001 45 266.001C68.6 250.401 81.4 206.001 81.4 206.001C81.4 206.001 91.801 182.001 74.2 178.801C56.6 175.601 -7.8 175.601 -7.8 175.601z"/>
+ </g>
+ <g style="fill: #b23259">
+ <path d="M-9.831 206.497C-6.505 193.707 -4.921 181.906 -7.8 175.601C-7.8 175.601 54.6 182.001 65.8 161.201C70.041 153.326 84.801 184.001 84.4 193.601C84.4 193.601 21.4 208.001 6.6 196.801L-9.831 206.497z"/>
+ </g>
+ <g style="fill: #a5264c">
+ <path d="M-5.4 222.801C-5.4 222.801 -3.4 230.001 -5.8 234.001C-5.8 234.001 -7.4 234.801 -8.6 235.201C-8.6 235.201 -7.4 238.801 -1.4 240.401C-1.4 240.401 0.6 244.801 3 245.201C5.4 245.601 10.2 251.201 14.2 250.001C18.2 248.801 29.4 244.801 29.4 244.801C29.4 244.801 35 241.601 43.8 245.201C43.8 245.201 46.175 244.399 46.6 240.401C47.1 235.701 50.2 232.001 52.2 230.001C54.2 228.001 63.8 215.201 62.6 214.801C61.4 214.401 -5.4 222.801 -5.4 222.801z"/>
+ </g>
+ <g style="fill: #ff727f; stroke:#000000">
+ <path d="M-9.8 174.401C-9.8 174.401 -12.6 196.801 -9.4 205.201C-6.2 213.601 -7 215.601 -7.8 219.601C-8.6 223.601 -4.2 233.601 1.4 239.601L13.4 241.201C13.4 241.201 28.6 237.601 37.8 240.401C37.8 240.401 46.794 241.744 50.2 226.801C50.2 226.801 55 220.401 62.2 217.601C69.4 214.801 76.6 173.201 72.6 165.201C68.6 157.201 54.2 152.801 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-8.2 249.201C-8.2 249.201 -9 247.201 -13.4 246.801C-13.4 246.801 -35.8 243.201 -44.2 230.801C-44.2 230.801 -51 225.201 -46.6 236.801C-46.6 236.801 -36.2 257.201 -29.4 260.001C-29.4 260.001 -13 264.001 -8.2 249.201z"/>
+ </g>
+ <g style="fill: #cc3f4c">
+ <path d="M71.742 185.229C72.401 177.323 74.354 168.709 72.6 165.201C66.154 152.307 49.181 157.695 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401C-9.8 174.401 -11.545 188.364 -10.705 198.376C-10.705 198.376 26.6 186.801 27.4 192.401C27.4 192.401 29 189.201 38.2 189.201C47.4 189.201 70.142 188.029 71.742 185.229z"/>
+ </g>
+ <g style="stroke:#a51926; stroke-width:2">
+ <path d="M28.6 175.201C28.6 175.201 33.4 180.001 29.8 189.601C29.8 189.601 15.4 205.601 17.4 219.601"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-19.4 260.001C-19.4 260.001 -23.8 247.201 -15 254.001C-15 254.001 -10.2 256.001 -11.4 257.601C-12.6 259.201 -18.2 263.201 -19.4 260.001z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-14.36 261.201C-14.36 261.201 -17.88 250.961 -10.84 256.401C-10.84 256.401 -6.419 258.849 -7.96 259.281C-12.52 260.561 -7.96 263.121 -14.36 261.201z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-9.56 261.201C-9.56 261.201 -13.08 250.961 -6.04 256.401C-6.04 256.401 -1.665 258.711 -3.16 259.281C-6.52 260.561 -3.16 263.121 -9.56 261.201z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-2.96 261.401C-2.96 261.401 -6.48 251.161 0.56 256.601C0.56 256.601 4.943 258.933 3.441 259.481C0.48 260.561 3.441 263.321 -2.96 261.401z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M3.52 261.321C3.52 261.321 0 251.081 7.041 256.521C7.041 256.521 10.881 258.121 9.921 259.401C8.961 260.681 9.921 263.241 3.52 261.321z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M10.2 262.001C10.2 262.001 5.4 249.601 14.6 256.001C14.6 256.001 19.4 258.001 18.2 259.601C17 261.201 18.2 264.401 10.2 262.001z"/>
+ </g>
+ <g style="stroke:#a5264c; stroke-width:2">
+ <path d="M-18.2 244.801C-18.2 244.801 -5 242.001 1 245.201C1 245.201 7 246.401 8.2 246.001C9.4 245.601 12.6 245.201 12.6 245.201"/>
+ </g>
+ <g style="stroke:#a5264c; stroke-width:2">
+ <path d="M15.8 253.601C15.8 253.601 27.8 240.001 39.8 244.401C46.816 246.974 45.8 243.601 46.6 240.801C47.4 238.001 47.6 233.801 52.6 230.801"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M33 237.601C33 237.601 29 226.801 26.2 239.601C23.4 252.401 20.2 256.001 18.6 258.801C18.6 258.801 18.6 264.001 27 263.601C27 263.601 37.8 263.201 38.2 260.401C38.6 257.601 37 246.001 33 237.601z"/>
+ </g>
+ <g style="stroke:#a5264c; stroke-width:2">
+ <path d="M47 244.801C47 244.801 50.6 242.401 53 243.601"/>
+ </g>
+ <g style="stroke:#a5264c; stroke-width:2">
+ <path d="M53.5 228.401C53.5 228.401 56.4 223.501 61.2 222.701"/>
+ </g>
+ <g style="fill: #b2b2b2">
+ <path d="M-25.8 265.201C-25.8 265.201 -7.8 268.401 -3.4 266.801C-3.4 266.801 5.4 266.801 -3 268.801C-3 268.801 -15.8 268.801 -23.8 267.601C-23.8 267.601 -35.4 262.001 -25.8 265.201z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-11.8 172.001C-11.8 172.001 5.8 172.001 7.8 172.801C7.8 172.801 15 203.601 11.4 211.201C11.4 211.201 10.2 214.001 7.4 208.401C7.4 208.401 -11 175.601 -14.2 173.601C-17.4 171.601 -13 172.001 -11.8 172.001z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-88.9 169.301C-88.9 169.301 -80 171.001 -67.4 173.601C-67.4 173.601 -62.6 196.001 -59.4 200.801C-56.2 205.601 -59.8 205.601 -63.4 202.801C-67 200.001 -81.8 186.001 -83.8 181.601C-85.8 177.201 -88.9 169.301 -88.9 169.301z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-67.039 173.818C-67.039 173.818 -61.239 175.366 -60.23 177.581C-59.222 179.795 -61.432 183.092 -61.432 183.092C-61.432 183.092 -62.432 186.397 -63.634 184.235C-64.836 182.072 -67.708 174.412 -67.039 173.818z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-67 173.601C-67 173.601 -63.4 178.801 -59.8 178.801C-56.2 178.801 -55.818 178.388 -53 179.001C-48.4 180.001 -48.8 178.001 -42.2 179.201C-39.56 179.681 -37 178.801 -34.2 180.001C-31.4 181.201 -28.2 180.401 -27 178.401C-25.8 176.401 -21 172.201 -21 172.201C-21 172.201 -33.8 174.001 -36.6 174.801C-36.6 174.801 -59 176.001 -67 173.601z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-22.4 173.801C-22.4 173.801 -28.85 177.301 -29.25 179.701C-29.65 182.101 -24 185.801 -24 185.801C-24 185.801 -21.25 190.401 -20.65 188.001C-20.05 185.601 -21.6 174.201 -22.4 173.801z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-59.885 179.265C-59.885 179.265 -52.878 190.453 -52.661 179.242C-52.661 179.242 -52.104 177.984 -53.864 177.962C-59.939 177.886 -58.418 173.784 -59.885 179.265z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-52.707 179.514C-52.707 179.514 -44.786 190.701 -45.422 179.421C-45.422 179.421 -45.415 179.089 -47.168 178.936C-51.915 178.522 -51.57 174.004 -52.707 179.514z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-45.494 179.522C-45.494 179.522 -37.534 190.15 -38.203 180.484C-38.203 180.484 -38.084 179.251 -39.738 178.95C-43.63 178.244 -43.841 174.995 -45.494 179.522z"/>
+ </g>
+ <g style="fill: #ffffcc; stroke:#000000; stroke-width:0.5">
+ <path d="M-38.618 179.602C-38.618 179.602 -30.718 191.163 -30.37 181.382C-30.37 181.382 -28.726 180.004 -30.472 179.782C-36.29 179.042 -35.492 174.588 -38.618 179.602z"/>
+ </g>
+ <g style="fill: #e5e5b2">
+ <path d="M-74.792 183.132L-82.45 181.601C-85.05 176.601 -87.15 170.451 -87.15 170.451C-87.15 170.451 -80.8 171.451 -68.3 174.251C-68.3 174.251 -67.424 177.569 -65.952 183.364L-74.792 183.132z"/>
+ </g>
+ <g style="fill: #e5e5b2">
+ <path d="M-9.724 178.47C-11.39 175.964 -12.707 174.206 -13.357 173.8C-16.37 171.917 -12.227 172.294 -11.098 172.294C-11.098 172.294 5.473 172.294 7.356 173.047C7.356 173.047 7.88 175.289 8.564 178.68C8.564 178.68 -1.524 176.67 -9.724 178.47z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M43.88 40.321C71.601 44.281 97.121 8.641 98.881 -1.04C100.641 -10.72 90.521 -22.6 90.521 -22.6C91.841 -25.68 87.001 -39.76 81.721 -49C76.441 -58.24 60.54 -57.266 43 -58.24C27.16 -59.12 8.68 -35.8 7.36 -34.04C6.04 -32.28 12.2 6.001 13.52 11.721C14.84 17.441 12.2 43.841 12.2 43.841C46.44 34.741 16.16 36.361 43.88 40.321z"/>
+ </g>
+ <g style="fill: #ea8e51">
+ <path d="M8.088 -33.392C6.792 -31.664 12.84 5.921 14.136 11.537C15.432 17.153 12.84 43.073 12.84 43.073C45.512 34.193 16.728 35.729 43.944 39.617C71.161 43.505 96.217 8.513 97.945 -0.992C99.673 -10.496 89.737 -22.16 89.737 -22.16C91.033 -25.184 86.281 -39.008 81.097 -48.08C75.913 -57.152 60.302 -56.195 43.08 -57.152C27.528 -58.016 9.384 -35.12 8.088 -33.392z"/>
+ </g>
+ <g style="fill: #efaa7c">
+ <path d="M8.816 -32.744C7.544 -31.048 13.48 5.841 14.752 11.353C16.024 16.865 13.48 42.305 13.48 42.305C44.884 33.145 17.296 35.097 44.008 38.913C70.721 42.729 95.313 8.385 97.009 -0.944C98.705 -10.272 88.953 -21.72 88.953 -21.72C90.225 -24.688 85.561 -38.256 80.473 -47.16C75.385 -56.064 60.063 -55.125 43.16 -56.064C27.896 -56.912 10.088 -34.44 8.816 -32.744z"/>
+ </g>
+ <g style="fill: #f4c6a8">
+ <path d="M9.544 -32.096C8.296 -30.432 14.12 5.761 15.368 11.169C16.616 16.577 14.12 41.537 14.12 41.537C43.556 32.497 17.864 34.465 44.072 38.209C70.281 41.953 94.409 8.257 96.073 -0.895C97.737 -10.048 88.169 -21.28 88.169 -21.28C89.417 -24.192 84.841 -37.504 79.849 -46.24C74.857 -54.976 59.824 -54.055 43.24 -54.976C28.264 -55.808 10.792 -33.76 9.544 -32.096z"/>
+ </g>
+ <g style="fill: #f9e2d3">
+ <path d="M10.272 -31.448C9.048 -29.816 14.76 5.681 15.984 10.985C17.208 16.289 14.76 40.769 14.76 40.769C42.628 31.849 18.432 33.833 44.136 37.505C69.841 41.177 93.505 8.129 95.137 -0.848C96.769 -9.824 87.385 -20.84 87.385 -20.84C88.609 -23.696 84.121 -36.752 79.225 -45.32C74.329 -53.888 59.585 -52.985 43.32 -53.888C28.632 -54.704 11.496 -33.08 10.272 -31.448z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M44.2 36.8C69.4 40.4 92.601 8 94.201 -0.8C95.801 -9.6 86.601 -20.4 86.601 -20.4C87.801 -23.2 83.4 -36 78.6 -44.4C73.8 -52.8 59.346 -51.914 43.4 -52.8C29 -53.6 12.2 -32.4 11 -30.8C9.8 -29.2 15.4 5.6 16.6 10.8C17.8 16 15.4 40 15.4 40C40.9 31.4 19 33.2 44.2 36.8z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M90.601 2.8C90.601 2.8 62.8 10.4 51.2 8.8C51.2 8.8 35.4 2.2 26.6 24C26.6 24 23 31.2 21 33.2C19 35.2 90.601 2.8 90.601 2.8z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M94.401 0.6C94.401 0.6 65.4 12.8 55.4 12.4C55.4 12.4 39 7.8 30.6 22.4C30.6 22.4 22.2 31.6 19 33.2C19 33.2 18.6 34.8 25 30.8L35.4 36C35.4 36 50.2 45.6 59.8 29.6C59.8 29.6 63.8 18.4 63.8 16.4C63.8 14.4 85 8.8 86.601 8.4C88.201 8 94.801 3.8 94.401 0.6z"/>
+ </g>
+ <g style="fill: #99cc32">
+ <path d="M47 36.514C40.128 36.514 31.755 32.649 31.755 26.4C31.755 20.152 40.128 13.887 47 13.887C53.874 13.887 59.446 18.952 59.446 25.2C59.446 31.449 53.874 36.514 47 36.514z"/>
+ </g>
+ <g style="fill: #659900">
+ <path d="M43.377 19.83C38.531 20.552 33.442 22.055 33.514 21.839C35.054 17.22 41.415 13.887 47 13.887C51.296 13.887 55.084 15.865 57.32 18.875C57.32 18.875 52.004 18.545 43.377 19.83z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M55.4 19.6C55.4 19.6 51 16.4 51 18.6C51 18.6 54.6 23 55.4 19.6z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M45.4 27.726C42.901 27.726 40.875 25.7 40.875 23.2C40.875 20.701 42.901 18.675 45.4 18.675C47.9 18.675 49.926 20.701 49.926 23.2C49.926 25.7 47.9 27.726 45.4 27.726z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M-58.6 14.4C-58.6 14.4 -61.8 -6.8 -59.4 -11.2C-59.4 -11.2 -48.6 -21.2 -49 -24.8C-49 -24.8 -49.4 -42.8 -50.6 -43.6C-51.8 -44.4 -59.4 -50.4 -65.4 -44C-65.4 -44 -75.8 -26 -75 -19.6L-75 -17.6C-75 -17.6 -82.6 -18 -84.2 -16C-84.2 -16 -85.4 -10.8 -86.6 -10.4C-86.6 -10.4 -89.4 -8 -87.4 -5.2C-87.4 -5.2 -89.4 -2.8 -89 1.2L-81.4 5.2C-81.4 5.2 -79.4 19.6 -68.6 24.8C-63.764 27.129 -60.6 20.4 -58.6 14.4z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M-59.6 12.56C-59.6 12.56 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.48 -40.36 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.96 -59.6 12.56z"/>
+ </g>
+ <g style="fill: #eb955c">
+ <path d="M-51.05 -42.61C-52.14 -43.47 -59.63 -49.24 -65.48 -43C-65.48 -43 -75.62 -25.45 -74.84 -19.21L-74.84 -17.26C-74.84 -17.26 -82.25 -17.65 -83.81 -15.7C-83.81 -15.7 -84.98 -10.63 -86.15 -10.24C-86.15 -10.24 -88.88 -7.9 -86.93 -5.17C-86.93 -5.17 -88.88 -2.83 -88.49 1.07L-81.08 4.97C-81.08 4.97 -79.13 19.01 -68.6 24.08C-63.886 26.35 -60.8 19.79 -58.85 13.94C-58.85 13.94 -61.97 -6.73 -59.63 -11.02C-59.63 -11.02 -49.1 -20.77 -49.49 -24.28C-49.49 -24.28 -49.88 -41.83 -51.05 -42.61z"/>
+ </g>
+ <g style="fill: #f2b892">
+ <path d="M-51.5 -41.62C-52.48 -42.54 -59.86 -48.08 -65.56 -42C-65.56 -42 -75.44 -24.9 -74.68 -18.82L-74.68 -16.92C-74.68 -16.92 -81.9 -17.3 -83.42 -15.4C-83.42 -15.4 -84.56 -10.46 -85.7 -10.08C-85.7 -10.08 -88.36 -7.8 -86.46 -5.14C-86.46 -5.14 -88.36 -2.86 -87.98 0.94L-80.76 4.74C-80.76 4.74 -78.86 18.42 -68.6 23.36C-64.006 25.572 -61 19.18 -59.1 13.48C-59.1 13.48 -62.14 -6.66 -59.86 -10.84C-59.86 -10.84 -49.6 -20.34 -49.98 -23.76C-49.98 -23.76 -50.36 -40.86 -51.5 -41.62z"/>
+ </g>
+ <g style="fill: #f8dcc8">
+ <path d="M-51.95 -40.63C-52.82 -41.61 -60.09 -46.92 -65.64 -41C-65.64 -41 -75.26 -24.35 -74.52 -18.43L-74.52 -16.58C-74.52 -16.58 -81.55 -16.95 -83.03 -15.1C-83.03 -15.1 -84.14 -10.29 -85.25 -9.92C-85.25 -9.92 -87.84 -7.7 -85.99 -5.11C-85.99 -5.11 -87.84 -2.89 -87.47 0.81L-80.44 4.51C-80.44 4.51 -78.59 17.83 -68.6 22.64C-64.127 24.794 -61.2 18.57 -59.35 13.02C-59.35 13.02 -62.31 -6.59 -60.09 -10.66C-60.09 -10.66 -50.1 -19.91 -50.47 -23.24C-50.47 -23.24 -50.84 -39.89 -51.95 -40.63z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M-59.6 12.46C-59.6 12.46 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.16 -40.68 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.86 -59.6 12.46z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-62.7 6.2C-62.7 6.2 -84.3 -4 -85.2 -4.8C-85.2 -4.8 -76.1 3.4 -75.3 3.4C-74.5 3.4 -62.7 6.2 -62.7 6.2z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-79.8 0C-79.8 0 -61.4 3.6 -61.4 8C-61.4 10.912 -61.643 24.331 -67 22.8C-75.4 20.4 -71.8 6 -79.8 0z"/>
+ </g>
+ <g style="fill: #99cc32">
+ <path d="M-71.4 3.8C-71.4 3.8 -62.422 5.274 -61.4 8C-60.8 9.6 -60.137 17.908 -65.6 19C-70.152 19.911 -72.382 9.69 -71.4 3.8z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M14.595 46.349C14.098 44.607 15.409 44.738 17.2 44.2C19.2 43.6 31.4 39.8 32.2 37.2C33 34.6 46.2 39 46.2 39C48 39.8 52.4 42.4 52.4 42.4C57.2 43.6 63.8 44 63.8 44C66.2 45 69.6 47.8 69.6 47.8C84.2 58 96.601 50.8 96.601 50.8C116.601 44.2 110.601 27 110.601 27C107.601 18 110.801 14.6 110.801 14.6C111.001 10.8 118.201 17.2 118.201 17.2C120.801 21.4 121.601 26.4 121.601 26.4C129.601 37.6 126.201 19.8 126.201 19.8C126.401 18.8 123.601 15.2 123.601 14C123.601 12.8 121.801 9.4 121.801 9.4C118.801 6 121.201 -1 121.201 -1C123.001 -14.8 120.801 -13 120.801 -13C119.601 -14.8 110.401 -4.8 110.401 -4.8C108.201 -1.4 102.201 0.2 102.201 0.2C99.401 2 96.001 0.6 96.001 0.6C93.401 0.2 87.801 7.2 87.801 7.2C90.601 7 93.001 11.4 95.401 11.6C97.801 11.8 99.601 9.2 101.201 8.6C102.801 8 105.601 13.8 105.601 13.8C106.001 16.4 100.401 21.2 100.401 21.2C100.001 25.8 98.401 24.2 98.401 24.2C95.401 23.6 94.201 27.4 93.201 32C92.201 36.6 88.001 37 88.001 37C86.401 44.4 85.2 41.4 85.2 41.4C85 35.8 79 41.6 79 41.6C77.8 43.6 73.2 41.4 73.2 41.4C66.4 39.4 68.8 37.4 68.8 37.4C70.6 35.2 81.8 37.4 81.8 37.4C84 35.8 76 31.8 76 31.8C75.4 30 76.4 25.6 76.4 25.6C77.6 22.4 84.4 16.8 84.4 16.8C93.801 15.6 91.001 14 91.001 14C84.801 8.8 79 16.4 79 16.4C76.8 22.6 59.4 37.6 59.4 37.6C54.6 41 57.2 34.2 53.2 37.6C49.2 41 28.6 32 28.6 32C17.038 30.807 14.306 46.549 10.777 43.429C10.777 43.429 16.195 51.949 14.595 46.349z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M209.401 -120C209.401 -120 183.801 -112 181.001 -93.2C181.001 -93.2 178.601 -70.4 199.001 -52.8C199.001 -52.8 199.401 -46.4 201.401 -43.2C201.401 -43.2 199.801 -38.4 218.601 -46L245.801 -54.4C245.801 -54.4 252.201 -56.8 257.401 -65.6C262.601 -74.4 277.801 -93.2 274.201 -118.4C274.201 -118.4 275.401 -129.6 269.401 -130C269.401 -130 261.001 -131.6 253.801 -124C253.801 -124 247.001 -120.8 244.601 -121.2L209.401 -120z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M264.022 -120.99C264.022 -120.99 266.122 -129.92 261.282 -125.08C261.282 -125.08 254.242 -119.36 246.761 -119.36C246.761 -119.36 232.241 -117.16 227.841 -103.96C227.841 -103.96 223.881 -77.12 231.801 -71.4C231.801 -71.4 236.641 -63.92 243.681 -70.52C250.722 -77.12 266.222 -107.35 264.022 -120.99z"/>
+ </g>
+ <g style="fill: #323232">
+ <path d="M263.648 -120.632C263.648 -120.632 265.738 -129.376 260.986 -124.624C260.986 -124.624 254.074 -119.008 246.729 -119.008C246.729 -119.008 232.473 -116.848 228.153 -103.888C228.153 -103.888 224.265 -77.536 232.041 -71.92C232.041 -71.92 236.793 -64.576 243.705 -71.056C250.618 -77.536 265.808 -107.24 263.648 -120.632z"/>
+ </g>
+ <g style="fill: #666666">
+ <path d="M263.274 -120.274C263.274 -120.274 265.354 -128.832 260.69 -124.168C260.69 -124.168 253.906 -118.656 246.697 -118.656C246.697 -118.656 232.705 -116.536 228.465 -103.816C228.465 -103.816 224.649 -77.952 232.281 -72.44C232.281 -72.44 236.945 -65.232 243.729 -71.592C250.514 -77.952 265.394 -107.13 263.274 -120.274z"/>
+ </g>
+ <g style="fill: #999999">
+ <path d="M262.9 -119.916C262.9 -119.916 264.97 -128.288 260.394 -123.712C260.394 -123.712 253.738 -118.304 246.665 -118.304C246.665 -118.304 232.937 -116.224 228.777 -103.744C228.777 -103.744 225.033 -78.368 232.521 -72.96C232.521 -72.96 237.097 -65.888 243.753 -72.128C250.41 -78.368 264.98 -107.02 262.9 -119.916z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M262.526 -119.558C262.526 -119.558 264.586 -127.744 260.098 -123.256C260.098 -123.256 253.569 -117.952 246.633 -117.952C246.633 -117.952 233.169 -115.912 229.089 -103.672C229.089 -103.672 225.417 -78.784 232.761 -73.48C232.761 -73.48 237.249 -66.544 243.777 -72.664C250.305 -78.784 264.566 -106.91 262.526 -119.558z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M262.151 -119.2C262.151 -119.2 264.201 -127.2 259.801 -122.8C259.801 -122.8 253.401 -117.6 246.601 -117.6C246.601 -117.6 233.401 -115.6 229.401 -103.6C229.401 -103.6 225.801 -79.2 233.001 -74C233.001 -74 237.401 -67.2 243.801 -73.2C250.201 -79.2 264.151 -106.8 262.151 -119.2z"/>
+ </g>
+ <g style="fill: #992600">
+ <path d="M50.6 84C50.6 84 30.2 64.8 22.2 64C22.2 64 -12.2 60 -27 78C-27 78 -9.4 57.6 18.2 63.2C18.2 63.2 -3.4 58.8 -15.8 62C-15.8 62 -32.6 62 -42.2 76L-45 80.8C-45 80.8 -41 66 -22.6 60C-22.6 60 0.2 55.2 11 60C11 60 -10.6 53.2 -20.6 55.2C-20.6 55.2 -51 52.8 -63.8 79.2C-63.8 79.2 -59.8 64.8 -45 57.6C-45 57.6 -31.4 48.8 -11 51.6C-11 51.6 3.4 54.8 8.6 57.2C13.8 59.6 12.6 56.8 4.2 52C4.2 52 -1.4 42 -15.4 42.4C-15.4 42.4 -58.2 46 -68.6 58C-68.6 58 -55 46.8 -44.6 44C-44.6 44 -22.2 36 -13.8 36.8C-13.8 36.8 11 37.8 18.6 33.8C18.6 33.8 7.4 38.8 10.6 42C13.8 45.2 20.6 52.8 20.6 54C20.6 55.2 44.8 77.3 48.4 81.7L50.6 84z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M189 278C189 278 173.5 241.5 161 232C161 232 187 248 190.5 266C190.5 266 190.5 276 189 278z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M236 285.5C236 285.5 209.5 230.5 191 206.5C191 206.5 234.5 244 239.5 270.5L240 276L237 273.5C237 273.5 236.5 282.5 236 285.5z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M292.5 237C292.5 237 230 177.5 228.5 175C228.5 175 289 241 292 248.5C292 248.5 290 239.5 292.5 237z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M104 280.5C104 280.5 123.5 228.5 142.5 251C142.5 251 157.5 261 157 264C157 264 153 257.5 135 258C135 258 116 255 104 280.5z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M294.5 153C294.5 153 249.5 124.5 242 123C230.193 120.639 291.5 152 296.5 162.5C296.5 162.5 298.5 160 294.5 153z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M143.801 259.601C143.801 259.601 164.201 257.601 171.001 250.801L175.401 254.401L193.001 216.001L196.601 221.201C196.601 221.201 211.001 206.401 210.201 198.401C209.401 190.401 223.001 204.401 223.001 204.401C223.001 204.401 222.201 192.801 229.401 199.601C229.401 199.601 227.001 184.001 235.401 192.001C235.401 192.001 224.864 161.844 247.401 187.601C253.001 194.001 248.601 187.201 248.601 187.201C248.601 187.201 222.601 139.201 244.201 153.601C244.201 153.601 246.201 130.801 245.001 126.401C243.801 122.001 241.801 99.6 237.001 94.4C232.201 89.2 237.401 87.6 243.001 92.8C243.001 92.8 231.801 68.8 245.001 80.8C245.001 80.8 241.401 65.6 237.001 62.8C237.001 62.8 231.401 45.6 246.601 56.4C246.601 56.4 242.201 44 239.001 40.8C239.001 40.8 227.401 13.2 234.601 18L239.001 21.6C239.001 21.6 232.201 7.6 238.601 12C245.001 16.4 245.001 16 245.001 16C245.001 16 223.801 -17.2 244.201 0.4C244.201 0.4 236.042 -13.518 232.601 -20.4C232.601 -20.4 213.801 -40.8 228.201 -34.4L233.001 -32.8C233.001 -32.8 224.201 -42.8 216.201 -44.4C208.201 -46 218.601 -52.4 225.001 -50.4C231.401 -48.4 247.001 -40.8 247.001 -40.8C247.001 -40.8 259.801 -22 263.801 -21.6C263.801 -21.6 243.801 -29.2 249.801 -21.2C249.801 -21.2 264.201 -7.2 257.001 -7.6C257.001 -7.6 251.001 -0.4 255.801 8.4C255.801 8.4 237.342 -9.991 252.201 15.6L259.001 32C259.001 32 234.601 7.2 245.801 29.2C245.801 29.2 263.001 52.8 265.001 53.2C267.001 53.6 271.401 62.4 271.401 62.4L267.001 60.4L272.201 69.2C272.201 69.2 261.001 57.2 267.001 70.4L272.601 84.8C272.601 84.8 252.201 62.8 265.801 92.4C265.801 92.4 249.401 87.2 258.201 104.4C258.201 104.4 256.601 120.401 257.001 125.601C257.401 130.801 258.601 159.201 254.201 167.201C249.801 175.201 260.201 194.401 262.201 198.401C264.201 202.401 267.801 213.201 259.001 204.001C250.201 194.801 254.601 200.401 256.601 209.201C258.601 218.001 264.601 233.601 263.801 239.201C263.801 239.201 262.601 240.401 259.401 236.801C259.401 236.801 244.601 214.001 246.201 228.401C246.201 228.401 245.001 236.401 241.801 245.201C241.801 245.201 238.601 256.001 238.601 247.201C238.601 247.201 235.401 230.401 232.601 238.001C229.801 245.601 226.201 251.601 223.401 254.001C220.601 256.401 215.401 233.601 214.201 244.001C214.201 244.001 202.201 231.601 197.401 248.001L185.801 264.401C185.801 264.401 185.401 252.001 184.201 258.001C184.201 258.001 154.201 264.001 143.801 259.601z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M109.401 -97.2C109.401 -97.2 97.801 -105.2 93.801 -104.8C89.801 -104.4 121.401 -113.6 162.601 -86C162.601 -86 167.401 -83.2 171.001 -83.6C171.001 -83.6 174.201 -81.2 171.401 -77.6C171.401 -77.6 162.601 -68 173.801 -56.8C173.801 -56.8 192.201 -50 186.601 -58.8C186.601 -58.8 197.401 -54.8 199.801 -50.8C202.201 -46.8 201.001 -50.8 201.001 -50.8C201.001 -50.8 194.601 -58 188.601 -63.2C188.601 -63.2 183.401 -65.2 180.601 -73.6C177.801 -82 175.401 -92 179.801 -95.2C179.801 -95.2 175.801 -90.8 176.601 -94.8C177.401 -98.8 181.001 -102.4 182.601 -102.8C184.201 -103.2 200.601 -119 207.401 -119.4C207.401 -119.4 198.201 -118 195.201 -119C192.201 -120 165.601 -131.4 159.601 -132.6C159.601 -132.6 142.801 -139.2 154.801 -137.2C154.801 -137.2 190.601 -133.4 208.801 -120.2C208.801 -120.2 201.601 -128.6 183.201 -135.6C183.201 -135.6 161.001 -148.2 125.801 -143.2C125.801 -143.2 108.001 -140 100.201 -138.2C100.201 -138.2 97.601 -138.8 97.001 -139.2C96.401 -139.6 84.6 -148.6 57 -141.6C57 -141.6 40 -137 31.4 -132.2C31.4 -132.2 16.2 -131 12.6 -127.8C12.6 -127.8 -6 -113.2 -8 -112.4C-10 -111.6 -21.4 -104 -22.2 -103.6C-22.2 -103.6 2.4 -110.2 4.8 -112.6C7.2 -115 24.6 -117.6 27 -116.2C29.4 -114.8 37.8 -115.4 28.2 -114.8C28.2 -114.8 103.801 -100 104.601 -98C105.401 -96 109.401 -97.2 109.401 -97.2z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M180.801 -106.4C180.801 -106.4 170.601 -113.8 168.601 -113.8C166.601 -113.8 154.201 -124 150.001 -123.6C145.801 -123.2 133.601 -133.2 106.201 -125C106.201 -125 105.601 -127 109.201 -127.8C109.201 -127.8 115.601 -130 116.001 -130.6C116.001 -130.6 136.201 -134.8 143.401 -131.2C143.401 -131.2 152.601 -128.6 158.801 -122.4C158.801 -122.4 170.001 -119.2 173.201 -120.2C173.201 -120.2 182.001 -118 182.401 -116.2C182.401 -116.2 188.201 -113.2 186.401 -110.6C186.401 -110.6 186.801 -109 180.801 -106.4z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M168.33 -108.509C169.137 -107.877 170.156 -107.779 170.761 -106.97C170.995 -106.656 170.706 -106.33 170.391 -106.233C169.348 -105.916 168.292 -106.486 167.15 -105.898C166.748 -105.691 166.106 -105.873 165.553 -106.022C163.921 -106.463 162.092 -106.488 160.401 -105.8C158.416 -106.929 156.056 -106.345 153.975 -107.346C153.917 -107.373 153.695 -107.027 153.621 -107.054C150.575 -108.199 146.832 -107.916 144.401 -110.2C141.973 -110.612 139.616 -111.074 137.188 -111.754C135.37 -112.263 133.961 -113.252 132.341 -114.084C130.964 -114.792 129.507 -115.314 127.973 -115.686C126.11 -116.138 124.279 -116.026 122.386 -116.546C122.293 -116.571 122.101 -116.227 122.019 -116.254C121.695 -116.362 121.405 -116.945 121.234 -116.892C119.553 -116.37 118.065 -117.342 116.401 -117C115.223 -118.224 113.495 -117.979 111.949 -118.421C108.985 -119.269 105.831 -117.999 102.801 -119C106.914 -120.842 111.601 -119.61 115.663 -121.679C117.991 -122.865 120.653 -121.763 123.223 -122.523C123.71 -122.667 124.401 -122.869 124.801 -122.2C124.935 -122.335 125.117 -122.574 125.175 -122.546C127.625 -121.389 129.94 -120.115 132.422 -119.049C132.763 -118.903 133.295 -119.135 133.547 -118.933C135.067 -117.717 137.01 -117.82 138.401 -116.6C140.099 -117.102 141.892 -116.722 143.621 -117.346C143.698 -117.373 143.932 -117.032 143.965 -117.054C145.095 -117.802 146.25 -117.531 147.142 -117.227C147.48 -117.112 148.143 -116.865 148.448 -116.791C149.574 -116.515 150.43 -116.035 151.609 -115.852C151.723 -115.834 151.908 -116.174 151.98 -116.146C153.103 -115.708 154.145 -115.764 154.801 -114.6C154.936 -114.735 155.101 -114.973 155.183 -114.946C156.21 -114.608 156.859 -113.853 157.96 -113.612C158.445 -113.506 159.057 -112.88 159.633 -112.704C162.025 -111.973 163.868 -110.444 166.062 -109.549C166.821 -109.239 167.697 -109.005 168.33 -108.509z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M91.696 -122.739C89.178 -124.464 86.81 -125.57 84.368 -127.356C84.187 -127.489 83.827 -127.319 83.625 -127.441C82.618 -128.05 81.73 -128.631 80.748 -129.327C80.209 -129.709 79.388 -129.698 78.88 -129.956C76.336 -131.248 73.707 -131.806 71.2 -133C71.882 -133.638 73.004 -133.394 73.6 -134.2C73.795 -133.92 74.033 -133.636 74.386 -133.827C76.064 -134.731 77.914 -134.884 79.59 -134.794C81.294 -134.702 83.014 -134.397 84.789 -134.125C85.096 -134.078 85.295 -133.555 85.618 -133.458C87.846 -132.795 90.235 -133.32 92.354 -132.482C93.945 -131.853 95.515 -131.03 96.754 -129.755C97.006 -129.495 96.681 -129.194 96.401 -129C96.789 -129.109 97.062 -128.903 97.173 -128.59C97.257 -128.351 97.257 -128.049 97.173 -127.81C97.061 -127.498 96.782 -127.397 96.408 -127.346C95.001 -127.156 96.773 -128.536 96.073 -128.088C94.8 -127.274 95.546 -125.868 94.801 -124.6C94.521 -124.794 94.291 -125.012 94.401 -125.4C94.635 -124.878 94.033 -124.588 93.865 -124.272C93.48 -123.547 92.581 -122.132 91.696 -122.739z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M59.198 -115.391C56.044 -116.185 52.994 -116.07 49.978 -117.346C49.911 -117.374 49.688 -117.027 49.624 -117.054C48.258 -117.648 47.34 -118.614 46.264 -119.66C45.351 -120.548 43.693 -120.161 42.419 -120.648C42.095 -120.772 41.892 -121.284 41.591 -121.323C40.372 -121.48 39.445 -122.429 38.4 -123C40.736 -123.795 43.147 -123.764 45.609 -124.148C45.722 -124.166 45.867 -123.845 46 -123.845C46.136 -123.845 46.266 -124.066 46.4 -124.2C46.595 -123.92 46.897 -123.594 47.154 -123.848C47.702 -124.388 48.258 -124.198 48.798 -124.158C48.942 -124.148 49.067 -123.845 49.2 -123.845C49.336 -123.845 49.467 -124.156 49.6 -124.156C49.736 -124.155 49.867 -123.845 50 -123.845C50.136 -123.845 50.266 -124.066 50.4 -124.2C51.092 -123.418 51.977 -123.972 52.799 -123.793C53.837 -123.566 54.104 -122.418 55.178 -122.12C59.893 -120.816 64.03 -118.671 68.393 -116.584C68.7 -116.437 68.91 -116.189 68.8 -115.8C69.067 -115.8 69.38 -115.888 69.57 -115.756C70.628 -115.024 71.669 -114.476 72.366 -113.378C72.582 -113.039 72.253 -112.632 72.02 -112.684C67.591 -113.679 63.585 -114.287 59.198 -115.391z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M45.338 -71.179C43.746 -72.398 43.162 -74.429 42.034 -76.221C41.82 -76.561 42.094 -76.875 42.411 -76.964C42.971 -77.123 43.514 -76.645 43.923 -76.443C45.668 -75.581 47.203 -74.339 49.2 -74.2C51.19 -71.966 55.45 -71.581 55.457 -68.2C55.458 -67.341 54.03 -68.259 53.6 -67.4C51.149 -68.403 48.76 -68.3 46.38 -69.767C45.763 -70.148 46.093 -70.601 45.338 -71.179z"/>
+ </g>
+ <g style="fill: #cc7226">
+ <path d="M17.8 -123.756C17.935 -123.755 24.966 -123.522 24.949 -123.408C24.904 -123.099 17.174 -122.05 16.81 -122.22C16.646 -122.296 9.134 -119.866 9 -120C9.268 -120.135 17.534 -123.756 17.8 -123.756z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M33.2 -114C33.2 -114 18.4 -112.2 14 -111C9.6 -109.8 -9 -102.2 -12 -100.2C-12 -100.2 -25.4 -94.8 -42.4 -74.8C-42.4 -74.8 -34.8 -78.2 -32.6 -81C-32.6 -81 -19 -93.6 -19.2 -91C-19.2 -91 -7 -99.6 -7.6 -97.4C-7.6 -97.4 16.8 -108.6 14.8 -105.4C14.8 -105.4 36.4 -110 35.4 -108C35.4 -108 54.2 -103.6 51.4 -103.4C51.4 -103.4 45.6 -102.2 52 -98.6C52 -98.6 48.6 -94.2 43.2 -98.2C37.8 -102.2 40.8 -100 35.8 -99C35.8 -99 33.2 -98.2 28.6 -102.2C28.6 -102.2 23 -106.8 14.2 -103.2C14.2 -103.2 -16.4 -90.6 -18.4 -90C-18.4 -90 -22 -87.2 -24.4 -83.6C-24.4 -83.6 -30.2 -79.2 -33.2 -77.8C-33.2 -77.8 -46 -66.2 -47.2 -64.8C-47.2 -64.8 -50.6 -59.6 -51.4 -59.2C-51.4 -59.2 -45 -63 -43 -65C-43 -65 -29 -75 -23.6 -75.8C-23.6 -75.8 -19.2 -78.8 -18.4 -80.2C-18.4 -80.2 -4 -89.4 0.2 -89.4C0.2 -89.4 9.4 -84.2 11.8 -91.2C11.8 -91.2 17.6 -93 23.2 -91.8C23.2 -91.8 26.4 -94.4 25.6 -96.6C25.6 -96.6 27.2 -98.4 28.2 -94.6C28.2 -94.6 31.6 -91 36.4 -93C36.4 -93 40.4 -93.2 38.4 -90.8C38.4 -90.8 34 -87 22.2 -86.8C22.2 -86.8 9.8 -86.2 -6.6 -78.6C-6.6 -78.6 -36.4 -68.2 -45.6 -57.8C-45.6 -57.8 -52 -49 -57.4 -47.8C-57.4 -47.8 -63.2 -47 -69.2 -39.6C-69.2 -39.6 -59.4 -45.4 -50.4 -45.4C-50.4 -45.4 -46.4 -47.8 -50.2 -44.2C-50.2 -44.2 -53.8 -36.6 -52.2 -31.2C-52.2 -31.2 -52.8 -26 -53.6 -24.4C-53.6 -24.4 -61.4 -11.6 -61.4 -9.2C-61.4 -6.8 -60.2 3 -59.8 3.6C-59.4 4.2 -60.8 2 -57 4.4C-53.2 6.8 -50.4 8.4 -49.6 11.2C-48.8 14 -51.6 5.8 -51.8 4C-52 2.2 -56.2 -5 -55.4 -7.4C-55.4 -7.4 -54.4 -6.4 -53.6 -5C-53.6 -5 -54.2 -5.6 -53.6 -9.2C-53.6 -9.2 -52.8 -14.4 -51.4 -17.6C-50 -20.8 -48 -24.6 -47.6 -25.4C-47.2 -26.2 -47.2 -32 -45.8 -29.4L-42.4 -26.8C-42.4 -26.8 -45.2 -29.4 -43 -31.6C-43 -31.6 -44 -37.2 -42.2 -39.8C-42.2 -39.8 -35.2 -48.2 -33.6 -49.2C-32 -50.2 -33.4 -49.8 -33.4 -49.8C-33.4 -49.8 -27.4 -54 -33.2 -52.4C-33.2 -52.4 -37.2 -50.8 -40.2 -50.8C-40.2 -50.8 -47.8 -48.8 -43.8 -53C-39.8 -57.2 -29.8 -62.6 -26 -62.4L-25.2 -60.8L-14 -63.2L-15.2 -62.4C-15.2 -62.4 -15.4 -62.6 -11.2 -63C-7 -63.4 -1.2 -62 0.2 -63.8C1.6 -65.6 5 -66.6 4.6 -65.2C4.2 -63.8 4 -61.8 4 -61.8C4 -61.8 9 -67.6 8.4 -65.4C7.8 -63.2 -0.4 -58 -1.8 -51.8L8.6 -60L12.2 -63C12.2 -63 15.8 -60.8 16 -62.4C16.2 -64 20.8 -69.8 22 -69.6C23.2 -69.4 25.2 -72.2 25 -69.6C24.8 -67 32.4 -61.6 32.4 -61.6C32.4 -61.6 35.6 -63.4 37 -62C38.4 -60.6 42.6 -81.8 42.6 -81.8L67.6 -92.4L111.201 -95.8L94.201 -102.6L33.2 -114z"/>
+ </g>
+ <g style="stroke:#4c0000; stroke-width:2">
+ <path d="M51.4 85C51.4 85 36.4 68.2 28 65.6C28 65.6 14.6 58.8 -10 66.6"/>
+ </g>
+ <g style="stroke:#4c0000; stroke-width:2">
+ <path d="M24.8 64.2C24.8 64.2 -0.4 56.2 -15.8 60.4C-15.8 60.4 -34.2 62.4 -42.6 76.2"/>
+ </g>
+ <g style="stroke:#4c0000; stroke-width:2">
+ <path d="M21.2 63C21.2 63 4.2 55.8 -10.6 53.6C-10.6 53.6 -27.2 51 -43.8 58.2C-43.8 58.2 -56 64.2 -61.4 74.4"/>
+ </g>
+ <g style="stroke:#4c0000; stroke-width:2">
+ <path d="M22.2 63.4C22.2 63.4 6.8 52.4 5.8 51C5.8 51 -1.2 40 -14.2 39.6C-14.2 39.6 -35.6 40.4 -52.8 48.4"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M20.895 54.407C22.437 55.87 49.4 84.8 49.4 84.8C84.6 121.401 56.6 87.2 56.6 87.2C49 82.4 39.8 63.6 39.8 63.6C38.6 60.8 53.8 70.8 53.8 70.8C57.8 71.6 71.4 90.8 71.4 90.8C64.6 88.4 69.4 95.6 69.4 95.6C72.2 97.6 92.601 113.201 92.601 113.201C96.201 117.201 100.201 118.801 100.201 118.801C114.201 113.601 107.801 126.801 107.801 126.801C110.201 133.601 115.801 122.001 115.801 122.001C127.001 105.2 110.601 107.601 110.601 107.601C80.6 110.401 73.8 94.4 73.8 94.4C71.4 92 80.2 94.4 80.2 94.4C88.601 96.4 73 82 73 82C75.4 82 84.6 88.8 84.6 88.8C95.001 98 97.001 96 97.001 96C115.001 87.2 125.401 94.8 125.401 94.8C127.401 96.4 121.801 103.2 123.401 108.401C125.001 113.601 129.801 126.001 129.801 126.001C127.401 127.601 127.801 138.401 127.801 138.401C144.601 161.601 135.001 159.601 135.001 159.601C119.401 159.201 134.201 166.801 134.201 166.801C137.401 168.801 146.201 176.001 146.201 176.001C143.401 174.801 141.801 180.001 141.801 180.001C146.601 184.001 143.801 188.801 143.801 188.801C137.801 190.001 136.601 194.001 136.601 194.001C143.401 202.001 133.401 202.401 133.401 202.401C137.001 206.801 132.201 218.801 132.201 218.801C127.401 218.801 121.001 224.401 121.001 224.401C123.401 229.201 113.001 234.801 113.001 234.801C104.601 236.401 107.401 243.201 107.401 243.201C99.401 249.201 97.001 265.201 97.001 265.201C96.201 275.601 93.801 278.801 99.001 276.801C104.201 274.801 103.401 262.401 103.401 262.401C98.601 246.801 141.401 230.801 141.401 230.801C145.401 229.201 146.201 224.001 146.201 224.001C148.201 224.401 157.001 232.001 157.001 232.001C164.601 243.201 165.001 234.001 165.001 234.001C166.201 230.401 164.601 224.401 164.601 224.401C170.601 202.801 156.601 196.401 156.601 196.401C146.601 162.801 160.601 171.201 160.601 171.201C163.401 176.801 174.201 182.001 174.201 182.001L177.801 179.601C176.201 174.801 184.601 168.801 184.601 168.801C187.401 175.201 193.401 167.201 193.401 167.201C197.001 142.801 209.401 157.201 209.401 157.201C213.401 158.401 214.601 151.601 214.601 151.601C218.201 141.201 214.601 127.601 214.601 127.601C218.201 127.201 227.801 133.201 227.801 133.201C230.601 129.601 221.401 112.801 225.401 115.201C229.401 117.601 233.801 119.201 233.801 119.201C234.601 117.201 224.601 104.801 224.601 104.801C220.201 102 215.001 81.6 215.001 81.6C222.201 85.2 212.201 70 212.201 70C212.201 66.8 218.201 55.6 218.201 55.6C217.401 48.8 218.201 49.2 218.201 49.2C221.001 50.4 229.001 52 222.201 45.6C215.401 39.2 223.001 34.4 223.001 34.4C227.401 31.6 213.801 32 213.801 32C208.601 27.6 209.001 23.6 209.001 23.6C217.001 25.6 202.601 11.2 200.201 7.6C197.801 4 207.401 -1.2 207.401 -1.2C220.601 -4.8 209.001 -8 209.001 -8C189.401 -7.6 200.201 -18.4 200.201 -18.4C206.201 -18 204.601 -20.4 204.601 -20.4C199.401 -21.6 189.801 -28 189.801 -28C185.801 -31.6 189.401 -30.8 189.401 -30.8C206.201 -29.6 177.401 -40.8 177.401 -40.8C185.401 -40.8 167.401 -51.2 167.401 -51.2C165.401 -52.8 162.201 -60.4 162.201 -60.4C156.201 -65.6 151.401 -72.4 151.401 -72.4C151.001 -76.8 146.201 -81.6 146.201 -81.6C134.601 -95.2 129.001 -94.8 129.001 -94.8C114.201 -98.4 109.001 -97.6 109.001 -97.6L56.2 -93.2C29.8 -80.4 37.6 -59.4 37.6 -59.4C44 -51 53.2 -54.8 53.2 -54.8C57.8 -61 69.4 -58.8 69.4 -58.8C89.801 -55.6 87.201 -59.2 87.201 -59.2C84.801 -63.8 68.6 -70 68.4 -70.6C68.2 -71.2 59.4 -74.6 59.4 -74.6C56.4 -75.8 52 -85 52 -85C48.8 -88.4 64.6 -82.6 64.6 -82.6C63.4 -81.6 70.8 -77.6 70.8 -77.6C88.201 -78.6 98.801 -67.8 98.801 -67.8C109.601 -51.2 109.801 -59.4 109.801 -59.4C112.601 -68.8 100.801 -90 100.801 -90C101.201 -92 109.401 -85.4 109.401 -85.4C110.801 -87.4 111.601 -81.6 111.601 -81.6C111.801 -79.2 115.601 -71.2 115.601 -71.2C118.401 -58.2 122.001 -65.6 122.001 -65.6L126.601 -56.2C128.001 -53.6 122.001 -46 122.001 -46C121.801 -43.2 122.601 -43.4 117.001 -35.8C111.401 -28.2 114.801 -23.8 114.801 -23.8C113.401 -17.2 122.201 -17.6 122.201 -17.6C124.801 -15.4 128.201 -15.4 128.201 -15.4C130.001 -13.4 132.401 -14 132.401 -14C134.001 -17.8 140.201 -15.8 140.201 -15.8C141.601 -18.2 149.801 -18.6 149.801 -18.6C150.801 -21.2 151.201 -22.8 154.601 -23.4C158.001 -24 133.401 -67 133.401 -67C139.801 -67.8 131.601 -80.2 131.601 -80.2C129.401 -86.8 140.801 -72.2 143.001 -70.8C145.201 -69.4 146.201 -67.2 144.601 -67.4C143.001 -67.6 141.201 -65.4 142.601 -65.2C144.001 -65 157.001 -50 160.401 -39.8C163.801 -29.6 169.801 -25.6 176.001 -19.6C182.201 -13.6 181.401 10.6 181.401 10.6C181.001 19.4 187.001 30 187.001 30C189.001 33.8 184.801 52 184.801 52C182.801 54.2 184.201 55 184.201 55C185.201 56.2 192.001 69.4 192.001 69.4C190.201 69.2 193.801 72.8 193.801 72.8C199.001 78.8 192.601 75.8 192.601 75.8C186.601 74.2 193.601 84 193.601 84C194.801 85.8 185.801 81.2 185.801 81.2C176.601 80.6 188.201 87.8 188.201 87.8C196.801 95 185.401 90.6 185.401 90.6C180.801 88.8 184.001 95.6 184.001 95.6C187.201 97.2 204.401 104.2 204.401 104.2C204.801 108.001 201.801 113.001 201.801 113.001C202.201 117.001 200.001 120.401 200.001 120.401C198.801 128.601 198.201 129.401 198.201 129.401C194.001 129.601 186.601 143.401 186.601 143.401C184.801 146.001 174.601 158.001 174.601 158.001C172.601 165.001 154.601 157.801 154.601 157.801C148.001 161.201 150.001 157.801 150.001 157.801C149.601 155.601 154.401 149.601 154.401 149.601C161.401 147.001 158.801 136.201 158.801 136.201C162.801 134.801 151.601 132.001 151.801 130.801C152.001 129.601 157.801 128.201 157.801 128.201C165.801 126.201 161.401 123.801 161.401 123.801C160.801 119.801 163.801 114.201 163.801 114.201C175.401 113.401 163.801 97.2 163.801 97.2C153.001 89.6 152.001 83.8 152.001 83.8C164.601 75.6 156.401 63.2 156.601 59.6C156.801 56 158.001 34.4 158.001 34.4C156.001 28.2 153.001 14.6 153.001 14.6C155.201 9.4 162.601 -3.2 162.601 -3.2C165.401 -7.4 174.201 -12.2 172.001 -15.2C169.801 -18.2 162.001 -16.4 162.001 -16.4C154.201 -17.8 154.801 -12.6 154.801 -12.6C153.201 -11.6 152.401 -6.6 152.401 -6.6C151.68 1.333 142.801 7.6 142.801 7.6C131.601 13.8 140.801 17.8 140.801 17.8C146.801 24.4 137.001 24.6 137.001 24.6C126.001 22.8 134.201 33 134.201 33C145.001 45.8 142.001 48.6 142.001 48.6C131.801 49.6 144.401 58.8 144.401 58.8C144.401 58.8 143.601 56.8 143.801 58.6C144.001 60.4 147.001 64.6 147.801 66.6C148.601 68.6 144.601 68.8 144.601 68.8C145.201 78.4 129.801 74.2 129.801 74.2C129.801 74.2 129.801 74.2 128.201 74.4C126.601 74.6 115.401 73.8 109.601 71.6C103.801 69.4 97.001 69.4 97.001 69.4C97.001 69.4 93.001 71.2 85.4 71C77.8 70.8 69.8 73.6 69.8 73.6C65.4 73.2 74 68.8 74.2 69C74.4 69.2 80 63.6 72 64.2C50.203 65.835 39.4 55.6 39.4 55.6C37.4 54.2 34.8 51.4 34.8 51.4C24.8 49.4 36.2 63.8 36.2 63.8C37.4 65.2 36 66.2 36 66.2C35.2 64.6 27.4 59.2 27.4 59.2C24.589 58.227 23.226 56.893 20.895 54.407z"/>
+ </g>
+ <g style="fill: #4c0000">
+ <path d="M-3 42.8C-3 42.8 8.6 48.4 11.2 51.2C13.8 54 27.8 65.4 27.8 65.4C27.8 65.4 22.4 63.4 19.8 61.6C17.2 59.8 6.4 51.6 6.4 51.6C6.4 51.6 2.6 45.6 -3 42.8z"/>
+ </g>
+ <g style="fill: #99cc32">
+ <path d="M-61.009 11.603C-60.672 11.455 -61.196 8.743 -61.4 8.2C-62.422 5.474 -71.4 4 -71.4 4C-71.627 5.365 -71.682 6.961 -71.576 8.599C-71.576 8.599 -66.708 14.118 -61.009 11.603z"/>
+ </g>
+ <g style="fill: #659900">
+ <path d="M-61.009 11.403C-61.458 11.561 -61.024 8.669 -61.2 8.2C-62.222 5.474 -71.4 3.9 -71.4 3.9C-71.627 5.265 -71.682 6.861 -71.576 8.499C-71.576 8.499 -67.308 13.618 -61.009 11.403z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-65.4 11.546C-66.025 11.546 -66.531 10.406 -66.531 9C-66.531 7.595 -66.025 6.455 -65.4 6.455C-64.775 6.455 -64.268 7.595 -64.268 9C-64.268 10.406 -64.775 11.546 -65.4 11.546z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-65.4 9z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-111 109.601C-111 109.601 -116.6 119.601 -91.8 113.601C-91.8 113.601 -77.8 112.401 -75.4 110.001C-74.2 110.801 -65.834 113.734 -63 114.401C-56.2 116.001 -47.8 106 -47.8 106C-47.8 106 -43.2 95.5 -40.4 95.5C-37.6 95.5 -40.8 97.1 -40.8 97.1C-40.8 97.1 -47.4 107.201 -47 108.801C-47 108.801 -52.2 128.801 -68.2 129.601C-68.2 129.601 -84.35 130.551 -83 136.401C-83 136.401 -74.2 134.001 -71.8 136.401C-71.8 136.401 -61 136.001 -69 142.401L-75.8 154.001C-75.8 154.001 -75.66 157.919 -85.8 154.401C-95.6 151.001 -105.9 138.101 -105.9 138.101C-105.9 138.101 -121.85 123.551 -111 109.601z"/>
+ </g>
+ <g style="fill: #e59999">
+ <path d="M-112.2 113.601C-112.2 113.601 -114.2 123.201 -77.4 112.801C-77.4 112.801 -73 112.801 -70.6 113.601C-68.2 114.401 -56.2 117.201 -54.2 116.001C-54.2 116.001 -61.4 129.601 -73 128.001C-73 128.001 -86.2 129.601 -85.8 134.401C-85.8 134.401 -81.8 141.601 -77 144.001C-77 144.001 -74.2 146.401 -74.6 149.601C-75 152.801 -77.8 154.401 -79.8 155.201C-81.8 156.001 -85 152.801 -86.6 152.801C-88.2 152.801 -96.6 146.401 -101 141.601C-105.4 136.801 -113.8 124.801 -113.4 122.001C-113 119.201 -112.2 113.601 -112.2 113.601z"/>
+ </g>
+ <g style="fill: #b26565">
+ <path d="M-109 131.051C-106.4 135.001 -103.2 139.201 -101 141.601C-96.6 146.401 -88.2 152.801 -86.6 152.801C-85 152.801 -81.8 156.001 -79.8 155.201C-77.8 154.401 -75 152.801 -74.6 149.601C-74.2 146.401 -77 144.001 -77 144.001C-80.066 142.468 -82.806 138.976 -84.385 136.653C-84.385 136.653 -84.2 139.201 -89.4 138.401C-94.6 137.601 -99.8 134.801 -101.4 131.601C-103 128.401 -105.4 126.001 -103.8 129.601C-102.2 133.201 -99.8 136.801 -98.2 137.201C-96.6 137.601 -97 138.801 -99.4 138.401C-101.8 138.001 -104.6 137.601 -109 132.401z"/>
+ </g>
+ <g style="fill: #992600">
+ <path d="M-111.6 110.001C-111.6 110.001 -109.8 96.4 -108.6 92.4C-108.6 92.4 -109.4 85.6 -107 81.4C-104.6 77.2 -102.6 71 -99.6 65.6C-96.6 60.2 -96.4 56.2 -92.4 54.6C-88.4 53 -82.4 44.4 -79.6 43.4C-76.8 42.4 -77 43.2 -77 43.2C-77 43.2 -70.2 28.4 -56.6 32.4C-56.6 32.4 -72.8 29.6 -57 20.2C-57 20.2 -61.8 21.3 -58.5 14.3C-56.299 9.632 -56.8 16.4 -67.8 28.2C-67.8 28.2 -72.8 36.8 -78 39.8C-83.2 42.8 -95.2 49.8 -96.4 53.6C-97.6 57.4 -100.8 63.2 -102.8 64.8C-104.8 66.4 -107.6 70.6 -108 74C-108 74 -109.2 78 -110.6 79.2C-112 80.4 -112.2 83.6 -112.2 85.6C-112.2 87.6 -114.2 90.4 -114 92.8C-114 92.8 -113.2 111.801 -113.6 113.801L-111.6 110.001z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M-120.2 114.601C-120.2 114.601 -122.2 113.201 -126.6 119.201C-126.6 119.201 -119.3 152.201 -119.3 153.601C-119.3 153.601 -118.2 151.501 -119.5 144.301C-120.8 137.101 -121.7 124.401 -121.7 124.401L-120.2 114.601z"/>
+ </g>
+ <g style="fill: #992600">
+ <path d="M-98.6 54C-98.6 54 -116.2 57.2 -115.8 86.4L-116.6 111.201C-116.6 111.201 -117.8 85.6 -119 84C-120.2 82.4 -116.2 71.2 -119.4 77.2C-119.4 77.2 -133.4 91.2 -125.4 112.401C-125.4 112.401 -123.9 115.701 -126.9 111.101C-126.9 111.101 -131.5 98.5 -130.4 92.1C-130.4 92.1 -130.2 89.9 -128.3 87.1C-128.3 87.1 -119.7 75.4 -117 73.1C-117 73.1 -115.2 58.7 -99.8 53.5C-99.8 53.5 -94.1 51.2 -98.6 54z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M40.8 -12.2C41.46 -12.554 41.451 -13.524 42.031 -13.697C43.18 -14.041 43.344 -15.108 43.862 -15.892C44.735 -17.211 44.928 -18.744 45.51 -20.235C45.782 -20.935 45.809 -21.89 45.496 -22.55C44.322 -25.031 43.62 -27.48 42.178 -29.906C41.91 -30.356 41.648 -31.15 41.447 -31.748C40.984 -33.132 39.727 -34.123 38.867 -35.443C38.579 -35.884 39.104 -36.809 38.388 -36.893C37.491 -36.998 36.042 -37.578 35.809 -36.552C35.221 -33.965 36.232 -31.442 37.2 -29C36.418 -28.308 36.752 -27.387 36.904 -26.62C37.614 -23.014 36.416 -19.662 35.655 -16.188C35.632 -16.084 35.974 -15.886 35.946 -15.824C34.724 -13.138 33.272 -10.693 31.453 -8.312C30.695 -7.32 29.823 -6.404 29.326 -5.341C28.958 -4.554 28.55 -3.588 28.8 -2.6C25.365 0.18 23.115 4.025 20.504 7.871C20.042 8.551 20.333 9.76 20.884 10.029C21.697 10.427 22.653 9.403 23.123 8.557C23.512 7.859 23.865 7.209 24.356 6.566C24.489 6.391 24.31 5.972 24.445 5.851C27.078 3.504 28.747 0.568 31.2 -1.8C33.15 -2.129 34.687 -3.127 36.435 -4.14C36.743 -4.319 37.267 -4.07 37.557 -4.265C39.31 -5.442 39.308 -7.478 39.414 -9.388C39.464 -10.272 39.66 -11.589 40.8 -12.2z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M31.959 -16.666C32.083 -16.743 31.928 -17.166 32.037 -17.382C32.199 -17.706 32.602 -17.894 32.764 -18.218C32.873 -18.434 32.71 -18.814 32.846 -18.956C35.179 -21.403 35.436 -24.427 34.4 -27.4C35.424 -28.02 35.485 -29.282 35.06 -30.129C34.207 -31.829 34.014 -33.755 33.039 -35.298C32.237 -36.567 30.659 -37.811 29.288 -36.508C28.867 -36.108 28.546 -35.321 28.824 -34.609C28.888 -34.446 29.173 -34.3 29.146 -34.218C29.039 -33.894 28.493 -33.67 28.487 -33.398C28.457 -31.902 27.503 -30.391 28.133 -29.062C28.905 -27.433 29.724 -25.576 30.4 -23.8C29.166 -21.684 30.199 -19.235 28.446 -17.358C28.31 -17.212 28.319 -16.826 28.441 -16.624C28.733 -16.138 29.139 -15.732 29.625 -15.44C29.827 -15.319 30.175 -15.317 30.375 -15.441C30.953 -15.803 31.351 -16.29 31.959 -16.666z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M94.771 -26.977C96.16 -25.185 96.45 -22.39 94.401 -21C94.951 -17.691 98.302 -19.67 100.401 -20.2C100.292 -20.588 100.519 -20.932 100.802 -20.937C101.859 -20.952 102.539 -21.984 103.601 -21.8C104.035 -23.357 105.673 -24.059 106.317 -25.439C108.043 -29.134 107.452 -33.407 104.868 -36.653C104.666 -36.907 104.883 -37.424 104.759 -37.786C104.003 -39.997 101.935 -40.312 100.001 -41C98.824 -44.875 98.163 -48.906 96.401 -52.6C94.787 -52.85 94.089 -54.589 92.752 -55.309C91.419 -56.028 90.851 -54.449 90.892 -53.403C90.899 -53.198 91.351 -52.974 91.181 -52.609C91.105 -52.445 90.845 -52.334 90.845 -52.2C90.846 -52.065 91.067 -51.934 91.201 -51.8C90.283 -50.98 88.86 -50.503 88.565 -49.358C87.611 -45.648 90.184 -42.523 91.852 -39.322C92.443 -38.187 91.707 -36.916 90.947 -35.708C90.509 -35.013 90.617 -33.886 90.893 -33.03C91.645 -30.699 93.236 -28.96 94.771 -26.977z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M57.611 -8.591C56.124 -6.74 52.712 -4.171 55.629 -2.243C55.823 -2.114 56.193 -2.11 56.366 -2.244C58.387 -3.809 60.39 -4.712 62.826 -5.294C62.95 -5.323 63.224 -4.856 63.593 -5.017C65.206 -5.72 67.216 -5.662 68.4 -7C72.167 -6.776 75.732 -7.892 79.123 -9.2C80.284 -9.648 81.554 -10.207 82.755 -10.709C84.131 -11.285 85.335 -12.213 86.447 -13.354C86.58 -13.49 86.934 -13.4 87.201 -13.4C87.161 -14.263 88.123 -14.39 88.37 -15.012C88.462 -15.244 88.312 -15.64 88.445 -15.742C90.583 -17.372 91.503 -19.39 90.334 -21.767C90.049 -22.345 89.8 -22.963 89.234 -23.439C88.149 -24.35 87.047 -23.496 86 -23.8C85.841 -23.172 85.112 -23.344 84.726 -23.146C83.867 -22.707 82.534 -23.292 81.675 -22.854C80.313 -22.159 79.072 -21.99 77.65 -21.613C77.338 -21.531 76.56 -21.627 76.4 -21C76.266 -21.134 76.118 -21.368 76.012 -21.346C74.104 -20.95 72.844 -20.736 71.543 -19.044C71.44 -18.911 70.998 -19.09 70.839 -18.955C69.882 -18.147 69.477 -16.913 68.376 -16.241C68.175 -16.118 67.823 -16.286 67.629 -16.157C66.983 -15.726 66.616 -15.085 65.974 -14.638C65.645 -14.409 65.245 -14.734 65.277 -14.99C65.522 -16.937 66.175 -18.724 65.6 -20.6C67.677 -23.12 70.194 -25.069 72 -27.8C72.015 -29.966 72.707 -32.112 72.594 -34.189C72.584 -34.382 72.296 -35.115 72.17 -35.462C71.858 -36.316 72.764 -37.382 71.92 -38.106C70.516 -39.309 69.224 -38.433 68.4 -37C66.562 -36.61 64.496 -35.917 62.918 -37.151C61.911 -37.938 61.333 -38.844 60.534 -39.9C59.549 -41.202 59.884 -42.638 59.954 -44.202C59.96 -44.33 59.645 -44.466 59.645 -44.6C59.646 -44.735 59.866 -44.866 60 -45C59.294 -45.626 59.019 -46.684 58 -47C58.305 -48.092 57.629 -48.976 56.758 -49.278C54.763 -49.969 53.086 -48.057 51.194 -47.984C50.68 -47.965 50.213 -49.003 49.564 -49.328C49.132 -49.544 48.428 -49.577 48.066 -49.311C47.378 -48.807 46.789 -48.693 46.031 -48.488C44.414 -48.052 43.136 -46.958 41.656 -46.103C40.171 -45.246 39.216 -43.809 38.136 -42.489C37.195 -41.337 37.059 -38.923 38.479 -38.423C40.322 -37.773 41.626 -40.476 43.592 -40.15C43.904 -40.099 44.11 -39.788 44 -39.4C44.389 -39.291 44.607 -39.52 44.8 -39.8C45.658 -38.781 46.822 -38.444 47.76 -37.571C48.73 -36.667 50.476 -37.085 51.491 -36.088C53.02 -34.586 52.461 -31.905 54.4 -30.6C53.814 -29.287 53.207 -28.01 52.872 -26.583C52.59 -25.377 53.584 -24.18 54.795 -24.271C56.053 -24.365 56.315 -25.124 56.8 -26.2C57.067 -25.933 57.536 -25.636 57.495 -25.42C57.038 -23.033 56.011 -21.04 55.553 -18.609C55.494 -18.292 55.189 -18.09 54.8 -18.2C54.332 -14.051 50.28 -11.657 47.735 -8.492C47.332 -7.99 47.328 -6.741 47.737 -6.338C49.14 -4.951 51.1 -6.497 52.8 -7C53.013 -8.206 53.872 -9.148 55.204 -9.092C55.46 -9.082 55.695 -9.624 56.019 -9.754C56.367 -9.892 56.869 -9.668 57.155 -9.866C58.884 -11.061 60.292 -12.167 62.03 -13.356C62.222 -13.487 62.566 -13.328 62.782 -13.436C63.107 -13.598 63.294 -13.985 63.617 -14.17C63.965 -14.37 64.207 -14.08 64.4 -13.8C63.754 -13.451 63.75 -12.494 63.168 -12.292C62.393 -12.024 61.832 -11.511 61.158 -11.064C60.866 -10.871 60.207 -11.119 60.103 -10.94C59.505 -9.912 58.321 -9.474 57.611 -8.591z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M2.2 -58C2.2 -58 -7.038 -60.872 -18.2 -35.2C-18.2 -35.2 -20.6 -30 -23 -28C-25.4 -26 -36.6 -22.4 -38.6 -18.4L-49 -2.4C-49 -2.4 -34.2 -18.4 -31 -20.8C-31 -20.8 -23 -29.2 -26.2 -22.4C-26.2 -22.4 -40.2 -11.6 -39 -2.4C-39 -2.4 -44.6 12 -45.4 14C-45.4 14 -29.4 -18 -27 -19.2C-24.6 -20.4 -23.4 -20.4 -24.6 -16.8C-25.8 -13.2 -26.2 3.2 -29 5.2C-29 5.2 -21 -15.2 -21.8 -18.4C-21.8 -18.4 -18.6 -22 -16.2 -16.8L-17.4 -0.8L-13 11.2C-13 11.2 -15.4 0 -13.8 -15.6C-13.8 -15.6 -15.8 -26 -11.8 -20.4C-7.8 -14.8 1.8 -8.8 1.8 -4C1.8 -4 -3.4 -21.6 -12.6 -26.4L-16.6 -20.4L-17.8 -22.4C-17.8 -22.4 -21.4 -23.2 -17 -30C-12.6 -36.8 -13 -37.6 -13 -37.6C-13 -37.6 -6.6 -30.4 -5 -30.4C-5 -30.4 8.2 -38 9.4 -13.6C9.4 -13.6 16.2 -28 7 -34.8C7 -34.8 -7.8 -36.8 -6.6 -42L0.6 -54.4C4.2 -59.6 2.6 -56.8 2.6 -56.8z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-17.8 -41.6C-17.8 -41.6 -30.6 -41.6 -33.8 -36.4L-41 -26.8C-41 -26.8 -23.8 -36.8 -19.8 -38C-15.8 -39.2 -17.8 -41.6 -17.8 -41.6z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-57.8 -35.2C-57.8 -35.2 -59.8 -34 -60.2 -31.2C-60.6 -28.4 -63 -28 -62.2 -25.2C-61.4 -22.4 -59.4 -20 -59.4 -24C-59.4 -28 -57.8 -30 -57 -31.2C-56.2 -32.4 -54.6 -36.8 -57.8 -35.2z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-66.6 26C-66.6 26 -75 22 -78.2 18.4C-81.4 14.8 -80.948 19.966 -85.8 19.6C-91.647 19.159 -90.6 3.2 -90.6 3.2L-94.6 10.8C-94.6 10.8 -95.8 25.2 -87.8 22.8C-83.893 21.628 -82.6 23.2 -84.2 24C-85.8 24.8 -78.6 25.2 -81.4 26.8C-84.2 28.4 -69.8 23.2 -72.2 33.6L-66.6 26z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-79.2 40.4C-79.2 40.4 -94.6 44.8 -98.2 35.2C-98.2 35.2 -103 37.6 -100.8 40.6C-98.6 43.6 -97.4 44 -97.4 44C-97.4 44 -92 45.2 -92.6 46C-93.2 46.8 -95.6 50.2 -95.6 50.2C-95.6 50.2 -85.4 44.2 -79.2 40.4z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M149.201 118.601C148.774 120.735 147.103 121.536 145.201 122.201C143.284 121.243 140.686 118.137 138.801 120.201C138.327 119.721 137.548 119.661 137.204 118.999C136.739 118.101 137.011 117.055 136.669 116.257C136.124 114.985 135.415 113.619 135.601 112.201C137.407 111.489 138.002 109.583 137.528 107.82C137.459 107.563 137.03 107.366 137.23 107.017C137.416 106.694 137.734 106.467 138.001 106.2C137.866 106.335 137.721 106.568 137.61 106.548C137 106.442 137.124 105.805 137.254 105.418C137.839 103.672 139.853 103.408 141.201 104.6C141.457 104.035 141.966 104.229 142.401 104.2C142.351 103.621 142.759 103.094 142.957 102.674C143.475 101.576 145.104 102.682 145.901 102.07C146.977 101.245 148.04 100.546 149.118 101.149C150.927 102.162 152.636 103.374 153.835 105.115C154.41 105.949 154.65 107.23 154.592 108.188C154.554 108.835 153.173 108.483 152.83 109.412C152.185 111.16 154.016 111.679 154.772 113.017C154.97 113.366 154.706 113.67 154.391 113.768C153.98 113.896 153.196 113.707 153.334 114.16C154.306 117.353 151.55 118.031 149.201 118.601z"/>
+ </g>
+ <g style="fill: #ffffff">
+ <path d="M139.6 138.201C139.593 136.463 137.992 134.707 139.201 133.001C139.336 133.135 139.467 133.356 139.601 133.356C139.736 133.356 139.867 133.135 140.001 133.001C141.496 135.217 145.148 136.145 145.006 138.991C144.984 139.438 143.897 140.356 144.801 141.001C142.988 142.349 142.933 144.719 142.001 146.601C140.763 146.315 139.551 145.952 138.401 145.401C138.753 143.915 138.636 142.231 139.456 140.911C139.89 140.213 139.603 139.134 139.6 138.201z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-26.6 129.201C-26.6 129.201 -43.458 139.337 -29.4 124.001C-20.6 114.401 -10.6 108.801 -10.6 108.801C-10.6 108.801 -0.2 104.4 3.4 103.2C7 102 22.2 96.8 25.4 96.4C28.6 96 38.2 92 45 96C51.8 100 59.8 104.4 59.8 104.4C59.8 104.4 43.4 96 39.8 98.4C36.2 100.8 29 100.4 23 103.6C23 103.6 8.2 108.001 5 110.001C1.8 112.001 -8.6 123.601 -10.2 122.801C-11.8 122.001 -9.8 121.601 -8.6 118.801C-7.4 116.001 -9.4 114.401 -17.4 120.801C-25.4 127.201 -26.6 129.201 -26.6 129.201z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-19.195 123.234C-19.195 123.234 -17.785 110.194 -9.307 111.859C-9.307 111.859 -1.081 107.689 1.641 105.721C1.641 105.721 9.78 104.019 11.09 103.402C29.569 94.702 44.288 99.221 44.835 98.101C45.381 96.982 65.006 104.099 68.615 108.185C69.006 108.628 58.384 102.588 48.686 100.697C40.413 99.083 18.811 100.944 7.905 106.48C4.932 107.989 -4.013 113.773 -6.544 113.662C-9.075 113.55 -19.195 123.234 -19.195 123.234z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-23 148.801C-23 148.801 -38.2 146.401 -21.4 144.801C-21.4 144.801 -3.4 142.801 0.6 137.601C0.6 137.601 14.2 128.401 17 128.001C19.8 127.601 49.8 120.401 50.2 118.001C50.6 115.601 56.2 115.601 57.8 116.401C59.4 117.201 58.6 118.401 55.8 119.201C53 120.001 21.8 136.401 15.4 137.601C9 138.801 -2.6 146.401 -7.4 147.601C-12.2 148.801 -23 148.801 -23 148.801z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-3.48 141.403C-3.48 141.403 -12.062 140.574 -3.461 139.755C-3.461 139.755 5.355 136.331 7.403 133.668C7.403 133.668 14.367 128.957 15.8 128.753C17.234 128.548 31.194 124.861 31.399 123.633C31.604 122.404 65.67 109.823 70.09 113.013C73.001 115.114 63.1 113.437 53.466 117.847C52.111 118.467 18.258 133.054 14.981 133.668C11.704 134.283 5.765 138.174 3.307 138.788C0.85 139.403 -3.48 141.403 -3.48 141.403z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-11.4 143.601C-11.4 143.601 -6.2 143.201 -7.4 144.801C-8.6 146.401 -11 145.601 -11 145.601L-11.4 143.601z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-18.6 145.201C-18.6 145.201 -13.4 144.801 -14.6 146.401C-15.8 148.001 -18.2 147.201 -18.2 147.201L-18.6 145.201z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-29 146.801C-29 146.801 -23.8 146.401 -25 148.001C-26.2 149.601 -28.6 148.801 -28.6 148.801L-29 146.801z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-36.6 147.601C-36.6 147.601 -31.4 147.201 -32.6 148.801C-33.8 150.401 -36.2 149.601 -36.2 149.601L-36.6 147.601z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M1.8 108.001C1.8 108.001 6.2 108.001 5 109.601C3.8 111.201 0.6 110.801 0.6 110.801L1.8 108.001z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-8.2 113.601C-8.2 113.601 -1.694 111.46 -4.2 114.801C-5.4 116.401 -7.8 115.601 -7.8 115.601L-8.2 113.601z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-19.4 118.401C-19.4 118.401 -14.2 118.001 -15.4 119.601C-16.6 121.201 -19 120.401 -19 120.401L-19.4 118.401z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-27 124.401C-27 124.401 -21.8 124.001 -23 125.601C-24.2 127.201 -26.6 126.401 -26.6 126.401L-27 124.401z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-33.8 129.201C-33.8 129.201 -28.6 128.801 -29.8 130.401C-31 132.001 -33.4 131.201 -33.4 131.201L-33.8 129.201z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M5.282 135.598C5.282 135.598 12.203 135.066 10.606 137.195C9.009 139.325 5.814 138.26 5.814 138.26L5.282 135.598z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M15.682 130.798C15.682 130.798 22.603 130.266 21.006 132.395C19.409 134.525 16.214 133.46 16.214 133.46L15.682 130.798z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M26.482 126.398C26.482 126.398 33.403 125.866 31.806 127.995C30.209 130.125 27.014 129.06 27.014 129.06L26.482 126.398z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M36.882 121.598C36.882 121.598 43.803 121.066 42.206 123.195C40.609 125.325 37.414 124.26 37.414 124.26L36.882 121.598z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M9.282 103.598C9.282 103.598 16.203 103.066 14.606 105.195C13.009 107.325 9.014 107.06 9.014 107.06L9.282 103.598z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M19.282 100.398C19.282 100.398 26.203 99.866 24.606 101.995C23.009 104.125 18.614 103.86 18.614 103.86L19.282 100.398z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-3.4 140.401C-3.4 140.401 1.8 140.001 0.6 141.601C-0.6 143.201 -3 142.401 -3 142.401L-3.4 140.401z"/>
+ </g>
+ <g style="fill: #992600">
+ <path d="M-76.6 41.2C-76.6 41.2 -81 50 -81.4 53.2C-81.4 53.2 -80.6 44.4 -79.4 42.4C-78.2 40.4 -76.6 41.2 -76.6 41.2z"/>
+ </g>
+ <g style="fill: #992600">
+ <path d="M-95 55.2C-95 55.2 -98.2 69.6 -97.8 72.4C-97.8 72.4 -99 60.8 -98.6 59.6C-98.2 58.4 -95 55.2 -95 55.2z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-74.2 -19.4L-74.4 -16.2L-76.6 -16C-76.6 -16 -62.4 -3.4 -61.8 4.2C-61.8 4.2 -61 -4 -74.2 -19.4z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-70.216 -18.135C-70.647 -18.551 -70.428 -19.296 -70.836 -19.556C-71.645 -20.072 -69.538 -20.129 -69.766 -20.845C-70.149 -22.051 -69.962 -22.072 -70.084 -23.348C-70.141 -23.946 -69.553 -25.486 -69.168 -25.926C-67.722 -27.578 -69.046 -30.51 -67.406 -32.061C-67.102 -32.35 -66.726 -32.902 -66.441 -33.32C-65.782 -34.283 -64.598 -34.771 -63.648 -35.599C-63.33 -35.875 -63.531 -36.702 -62.962 -36.61C-62.248 -36.495 -61.007 -36.625 -61.052 -35.784C-61.165 -33.664 -62.494 -31.944 -63.774 -30.276C-63.323 -29.572 -63.781 -28.937 -64.065 -28.38C-65.4 -25.76 -65.211 -22.919 -65.385 -20.079C-65.39 -19.994 -65.697 -19.916 -65.689 -19.863C-65.336 -17.528 -64.752 -15.329 -63.873 -13.1C-63.507 -12.17 -63.036 -11.275 -62.886 -10.348C-62.775 -9.662 -62.672 -8.829 -63.08 -8.124C-61.045 -5.234 -62.354 -2.583 -61.185 0.948C-60.978 1.573 -59.286 3.487 -59.749 3.326C-62.262 2.455 -62.374 2.057 -62.551 1.304C-62.697 0.681 -63.027 -0.696 -63.264 -1.298C-63.328 -1.462 -63.499 -3.346 -63.577 -3.468C-65.09 -5.85 -63.732 -5.674 -65.102 -8.032C-66.53 -8.712 -67.496 -9.816 -68.619 -10.978C-68.817 -11.182 -67.674 -11.906 -67.855 -12.119C-68.947 -13.408 -70.1 -14.175 -69.764 -15.668C-69.609 -16.358 -69.472 -17.415 -70.216 -18.135z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-73.8 -16.4C-73.8 -16.4 -73.4 -9.6 -71 -8C-68.6 -6.4 -69.8 -7.2 -73 -8.4C-76.2 -9.6 -75 -10.4 -75 -10.4C-75 -10.4 -77.8 -10 -75.4 -8C-73 -6 -69.4 -3.6 -71 -3.6C-72.6 -3.6 -80.2 -7.6 -80.2 -10.4C-80.2 -13.2 -81.2 -17.3 -81.2 -17.3C-81.2 -17.3 -80.1 -18.1 -75.3 -18C-75.3 -18 -73.9 -17.3 -73.8 -16.4z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-74.6 2.2C-74.6 2.2 -83.12 -0.591 -101.6 2.8C-101.6 2.8 -92.569 0.722 -73.8 3C-63.5 4.25 -74.6 2.2 -74.6 2.2z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-72.502 2.129C-72.502 2.129 -80.748 -1.389 -99.453 0.392C-99.453 0.392 -90.275 -0.897 -71.774 2.995C-61.62 5.131 -72.502 2.129 -72.502 2.129z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-70.714 2.222C-70.714 2.222 -78.676 -1.899 -97.461 -1.514C-97.461 -1.514 -88.213 -2.118 -70.052 3.14C-60.086 6.025 -70.714 2.222 -70.714 2.222z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-69.444 2.445C-69.444 2.445 -76.268 -1.862 -93.142 -2.96C-93.142 -2.96 -84.803 -2.79 -68.922 3.319C-60.206 6.672 -69.444 2.445 -69.444 2.445z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M45.84 12.961C45.84 12.961 44.91 13.605 45.124 12.424C45.339 11.243 73.547 -1.927 77.161 -1.677C77.161 -1.677 46.913 11.529 45.84 12.961z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M42.446 13.6C42.446 13.6 41.57 14.315 41.691 13.121C41.812 11.927 68.899 -3.418 72.521 -3.452C72.521 -3.452 43.404 12.089 42.446 13.6z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M39.16 14.975C39.16 14.975 38.332 15.747 38.374 14.547C38.416 13.348 58.233 -2.149 68.045 -4.023C68.045 -4.023 50.015 4.104 39.16 14.975z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M36.284 16.838C36.284 16.838 35.539 17.532 35.577 16.453C35.615 15.373 53.449 1.426 62.28 -0.26C62.28 -0.26 46.054 7.054 36.284 16.838z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M4.6 164.801C4.6 164.801 -10.6 162.401 6.2 160.801C6.2 160.801 24.2 158.801 28.2 153.601C28.2 153.601 41.8 144.401 44.6 144.001C47.4 143.601 63.8 140.001 64.2 137.601C64.6 135.201 70.6 132.801 72.2 133.601C73.8 134.401 73.8 143.601 71 144.401C68.2 145.201 49.4 152.401 43 153.601C36.6 154.801 25 162.401 20.2 163.601C15.4 164.801 4.6 164.801 4.6 164.801z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M77.6 127.401C77.6 127.401 74.6 129.001 73.4 131.601C73.4 131.601 67 142.201 52.8 145.401C52.8 145.401 29.8 154.401 22 156.401C22 156.401 8.6 161.401 1.2 160.601C1.2 160.601 -5.8 160.801 0.4 162.401C0.4 162.401 20.6 160.401 24 158.601C24 158.601 39.6 153.401 42.6 150.801C45.6 148.201 63.8 143.201 66 141.201C68.2 139.201 78 130.801 77.6 127.401z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M18.882 158.911C18.882 158.911 24.111 158.685 22.958 160.234C21.805 161.784 19.357 160.91 19.357 160.91L18.882 158.911z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M11.68 160.263C11.68 160.263 16.908 160.037 15.756 161.586C14.603 163.136 12.155 162.263 12.155 162.263L11.68 160.263z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M1.251 161.511C1.251 161.511 6.48 161.284 5.327 162.834C4.174 164.383 1.726 163.51 1.726 163.51L1.251 161.511z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-6.383 162.055C-6.383 162.055 -1.154 161.829 -2.307 163.378C-3.46 164.928 -5.908 164.054 -5.908 164.054L-6.383 162.055z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M35.415 151.513C35.415 151.513 42.375 151.212 40.84 153.274C39.306 155.336 36.047 154.174 36.047 154.174L35.415 151.513z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M45.73 147.088C45.73 147.088 51.689 143.787 51.155 148.849C50.885 151.405 46.362 149.749 46.362 149.749L45.73 147.088z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M54.862 144.274C54.862 144.274 62.021 140.573 60.287 146.035C59.509 148.485 55.493 146.935 55.493 146.935L54.862 144.274z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M64.376 139.449C64.376 139.449 68.735 134.548 69.801 141.21C70.207 143.748 65.008 142.11 65.008 142.11L64.376 139.449z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M26.834 155.997C26.834 155.997 32.062 155.77 30.91 157.32C29.757 158.869 27.308 157.996 27.308 157.996L26.834 155.997z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M62.434 34.603C62.434 34.603 61.708 35.268 61.707 34.197C61.707 33.127 79.191 19.863 88.034 18.479C88.034 18.479 71.935 25.208 62.434 34.603z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M65.4 98.4C65.4 98.4 87.401 120.801 96.601 124.401C96.601 124.401 105.801 135.601 101.801 161.601C101.801 161.601 98.601 169.201 95.401 148.401C95.401 148.401 98.601 123.201 87.401 139.201C87.401 139.201 79 129.301 85.4 129.601C85.4 129.601 88.601 131.601 89.001 130.001C89.401 128.401 81.4 114.801 64.2 100.4C47 86 65.4 98.4 65.4 98.4z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M7 137.201C7 137.201 6.8 135.401 8.6 136.201C10.4 137.001 104.601 143.201 136.201 167.201C136.201 167.201 91.001 144.001 7 137.201z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M17.4 132.801C17.4 132.801 17.2 131.001 19 131.801C20.8 132.601 157.401 131.601 181.001 164.001C181.001 164.001 159.001 138.801 17.4 132.801z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M29 128.801C29 128.801 28.8 127.001 30.6 127.801C32.4 128.601 205.801 115.601 229.401 148.001C229.401 148.001 219.801 122.401 29 128.801z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M39 124.001C39 124.001 38.8 122.201 40.6 123.001C42.4 123.801 164.601 85.2 188.201 117.601C188.201 117.601 174.801 93 39 124.001z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-19 146.801C-19 146.801 -19.2 145.001 -17.4 145.801C-15.6 146.601 2.2 148.801 4.2 187.601C4.2 187.601 -3 145.601 -19 146.801z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-27.8 148.401C-27.8 148.401 -28 146.601 -26.2 147.401C-24.4 148.201 -10.2 143.601 -13 182.401C-13 182.401 -11.8 147.201 -27.8 148.401z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-35.8 148.801C-35.8 148.801 -36 147.001 -34.2 147.801C-32.4 148.601 -17 149.201 -29.4 171.601C-29.4 171.601 -19.8 147.601 -35.8 148.801z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M11.526 104.465C11.526 104.465 11.082 106.464 12.631 105.247C28.699 92.622 61.141 33.72 116.826 28.086C116.826 28.086 78.518 15.976 11.526 104.465z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M22.726 102.665C22.726 102.665 21.363 101.472 23.231 100.847C25.099 100.222 137.541 27.72 176.826 35.686C176.826 35.686 149.719 28.176 22.726 102.665z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M1.885 108.767C1.885 108.767 1.376 110.366 3.087 109.39C12.062 104.27 15.677 47.059 59.254 45.804C59.254 45.804 26.843 31.09 1.885 108.767z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-18.038 119.793C-18.038 119.793 -19.115 121.079 -17.162 120.825C-6.916 119.493 14.489 78.222 58.928 83.301C58.928 83.301 26.962 68.955 -18.038 119.793z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-6.8 113.667C-6.8 113.667 -7.611 115.136 -5.742 114.511C4.057 111.237 17.141 66.625 61.729 63.078C61.729 63.078 27.603 55.135 -6.8 113.667z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-25.078 124.912C-25.078 124.912 -25.951 125.954 -24.369 125.748C-16.07 124.669 1.268 91.24 37.264 95.354C37.264 95.354 11.371 83.734 -25.078 124.912z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-32.677 130.821C-32.677 130.821 -33.682 131.866 -32.091 131.748C-27.923 131.439 2.715 98.36 21.183 113.862C21.183 113.862 9.168 95.139 -32.677 130.821z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M36.855 98.898C36.855 98.898 35.654 97.543 37.586 97.158C39.518 96.774 160.221 39.061 198.184 51.927C198.184 51.927 172.243 41.053 36.855 98.898z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M3.4 163.201C3.4 163.201 3.2 161.401 5 162.201C6.8 163.001 22.2 163.601 9.8 186.001C9.8 186.001 19.4 162.001 3.4 163.201z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M13.8 161.601C13.8 161.601 13.6 159.801 15.4 160.601C17.2 161.401 35 163.601 37 202.401C37 202.401 29.8 160.401 13.8 161.601z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M20.6 160.001C20.6 160.001 20.4 158.201 22.2 159.001C24 159.801 48.6 163.201 72.2 195.601C72.2 195.601 36.6 158.801 20.6 160.001z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M28.225 157.972C28.225 157.972 27.788 156.214 29.678 156.768C31.568 157.322 52.002 155.423 90.099 189.599C90.099 189.599 43.924 154.656 28.225 157.972z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M38.625 153.572C38.625 153.572 38.188 151.814 40.078 152.368C41.968 152.922 76.802 157.423 128.499 192.399C128.499 192.399 54.324 150.256 38.625 153.572z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-1.8 142.001C-1.8 142.001 -2 140.201 -0.2 141.001C1.6 141.801 55 144.401 85.4 171.201C85.4 171.201 50.499 146.426 -1.8 142.001z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M-11.8 146.001C-11.8 146.001 -12 144.201 -10.2 145.001C-8.4 145.801 16.2 149.201 39.8 181.601C39.8 181.601 4.2 144.801 -11.8 146.001z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M49.503 148.962C49.503 148.962 48.938 147.241 50.864 147.655C52.79 148.068 87.86 150.004 141.981 181.098C141.981 181.098 64.317 146.704 49.503 148.962z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M57.903 146.562C57.903 146.562 57.338 144.841 59.264 145.255C61.19 145.668 96.26 147.604 150.381 178.698C150.381 178.698 73.317 143.904 57.903 146.562z"/>
+ </g>
+ <g style="fill: #ffffff; stroke:#000000; stroke-width:0.1">
+ <path d="M67.503 141.562C67.503 141.562 66.938 139.841 68.864 140.255C70.79 140.668 113.86 145.004 203.582 179.298C203.582 179.298 82.917 138.904 67.503 141.562z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-43.8 148.401C-43.8 148.401 -38.6 148.001 -39.8 149.601C-41 151.201 -43.4 150.401 -43.4 150.401L-43.8 148.401z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-13 162.401C-13 162.401 -7.8 162.001 -9 163.601C-10.2 165.201 -12.6 164.401 -12.6 164.401L-13 162.401z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-21.8 162.001C-21.8 162.001 -16.6 161.601 -17.8 163.201C-19 164.801 -21.4 164.001 -21.4 164.001L-21.8 162.001z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-117.169 150.182C-117.169 150.182 -112.124 151.505 -113.782 152.624C-115.439 153.744 -117.446 152.202 -117.446 152.202L-117.169 150.182z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-115.169 140.582C-115.169 140.582 -110.124 141.905 -111.782 143.024C-113.439 144.144 -115.446 142.602 -115.446 142.602L-115.169 140.582z"/>
+ </g>
+ <g style="fill: #000000">
+ <path d="M-122.369 136.182C-122.369 136.182 -117.324 137.505 -118.982 138.624C-120.639 139.744 -122.646 138.202 -122.646 138.202L-122.369 136.182z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-42.6 211.201C-42.6 211.201 -44.2 211.201 -48.2 213.201C-50.2 213.201 -61.4 216.801 -67 226.801C-67 226.801 -54.6 217.201 -42.6 211.201z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M45.116 303.847C45.257 304.105 45.312 304.525 45.604 304.542C46.262 304.582 47.495 304.883 47.37 304.247C46.522 299.941 45.648 295.004 41.515 293.197C40.876 292.918 39.434 293.331 39.36 294.215C39.233 295.739 39.116 297.088 39.425 298.554C39.725 299.975 41.883 299.985 42.8 298.601C43.736 300.273 44.168 302.116 45.116 303.847z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M34.038 308.581C34.786 309.994 34.659 311.853 36.074 312.416C36.814 312.71 38.664 311.735 38.246 310.661C37.444 308.6 37.056 306.361 35.667 304.55C35.467 304.288 35.707 303.755 35.547 303.427C34.953 302.207 33.808 301.472 32.4 301.801C31.285 304.004 32.433 306.133 33.955 307.842C34.091 307.994 33.925 308.37 34.038 308.581z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-5.564 303.391C-5.672 303.014 -5.71 302.551 -5.545 302.23C-5.014 301.197 -4.221 300.075 -4.558 299.053C-4.906 297.997 -6.022 298.179 -6.672 298.748C-7.807 299.742 -7.856 301.568 -8.547 302.927C-8.743 303.313 -8.692 303.886 -9.133 304.277C-9.607 304.698 -10.047 306.222 -9.951 306.793C-9.898 307.106 -10.081 317.014 -9.859 316.751C-9.24 316.018 -6.19 306.284 -6.121 305.392C-6.064 304.661 -5.332 304.196 -5.564 303.391z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-31.202 296.599C-28.568 294.1 -25.778 291.139 -26.22 287.427C-26.336 286.451 -28.111 286.978 -28.298 287.824C-29.1 291.449 -31.139 294.11 -33.707 296.502C-35.903 298.549 -37.765 304.893 -38 305.401C-34.303 300.145 -32.046 297.399 -31.202 296.599z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-44.776 290.635C-44.253 290.265 -44.555 289.774 -44.338 289.442C-43.385 287.984 -42.084 286.738 -42.066 285C-42.063 284.723 -42.441 284.414 -42.776 284.638C-43.053 284.822 -43.395 284.952 -43.503 285.082C-45.533 287.531 -46.933 290.202 -48.376 293.014C-48.559 293.371 -49.703 297.862 -49.39 297.973C-49.151 298.058 -47.431 293.877 -47.221 293.763C-45.958 293.077 -45.946 291.462 -44.776 290.635z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-28.043 310.179C-27.599 309.31 -26.023 308.108 -26.136 307.219C-26.254 306.291 -25.786 304.848 -26.698 305.536C-27.955 306.484 -31.404 307.833 -31.674 313.641C-31.7 314.212 -28.726 311.519 -28.043 310.179z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-13.6 293.001C-13.2 292.333 -12.492 292.806 -12.033 292.543C-11.385 292.171 -10.774 291.613 -10.482 290.964C-9.512 288.815 -7.743 286.995 -7.6 284.601C-9.091 283.196 -9.77 285.236 -10.4 286.201C-11.723 284.554 -12.722 286.428 -14.022 286.947C-14.092 286.975 -14.305 286.628 -14.38 286.655C-15.557 287.095 -16.237 288.176 -17.235 288.957C-17.406 289.091 -17.811 288.911 -17.958 289.047C-18.61 289.65 -19.583 289.975 -19.863 290.657C-20.973 293.364 -24.113 295.459 -26 303.001C-25.619 303.91 -21.488 296.359 -21.001 295.661C-20.165 294.465 -20.047 297.322 -18.771 296.656C-18.72 296.629 -18.534 296.867 -18.4 297.001C-18.206 296.721 -17.988 296.492 -17.6 296.601C-17.6 296.201 -17.734 295.645 -17.533 295.486C-16.296 294.509 -16.38 293.441 -15.6 292.201C-15.142 292.99 -14.081 292.271 -13.6 293.001z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M46.2 347.401C46.2 347.401 53.6 327.001 49.2 315.801C49.2 315.801 60.6 337.401 56 348.601C56 348.601 55.6 338.201 51.6 333.201C51.6 333.201 47.6 346.001 46.2 347.401z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M31.4 344.801C31.4 344.801 36.8 336.001 28.8 317.601C28.8 317.601 28 338.001 21.2 349.001C21.2 349.001 35.4 328.801 31.4 344.801z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M21.4 342.801C21.4 342.801 21.2 322.801 21.6 319.801C21.6 319.801 17.8 336.401 7.6 346.001C7.6 346.001 22 334.001 21.4 342.801z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M11.8 310.801C11.8 310.801 17.8 324.401 7.8 342.801C7.8 342.801 14.2 330.601 9.4 323.601C9.4 323.601 12 320.201 11.8 310.801z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-7.4 342.401C-7.4 342.401 -8.4 326.801 -6.6 324.601C-6.6 324.601 -6.4 318.201 -6.8 317.201C-6.8 317.201 -2.8 311.001 -2.6 318.401C-2.6 318.401 -1.2 326.201 1.6 330.801C1.6 330.801 5.2 336.201 5 342.601C5 342.601 -5 312.401 -7.4 342.401z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-11 314.801C-11 314.801 -17.6 325.601 -19.4 344.601C-19.4 344.601 -20.8 338.401 -17 324.001C-17 324.001 -12.8 308.601 -11 314.801z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-32.8 334.601C-32.8 334.601 -27.8 329.201 -26.4 324.201C-26.4 324.201 -22.8 308.401 -29.2 317.001C-29.2 317.001 -29 325.001 -37.2 332.401C-37.2 332.401 -32.4 330.001 -32.8 334.601z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-38.6 329.601C-38.6 329.601 -35.2 312.201 -34.4 311.401C-34.4 311.401 -32.6 308.001 -35.4 311.201C-35.4 311.201 -44.2 330.401 -48.2 337.001C-48.2 337.001 -40.2 327.801 -38.6 329.601z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-44.4 313.001C-44.4 313.001 -32.8 290.601 -54.6 316.401C-54.6 316.401 -43.6 306.601 -44.4 313.001z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M-59.8 298.401C-59.8 298.401 -55 279.601 -52.4 279.801C-52.4 279.801 -44.2 270.801 -50.8 281.401C-50.8 281.401 -56.8 291.001 -56.2 300.801C-56.2 300.801 -56.8 291.201 -59.8 298.401z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M270.5 287C270.5 287 258.5 277 256 273.5C256 273.5 269.5 292 269.5 299C269.5 299 272 291.5 270.5 287z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M276 265C276 265 255 250 251.5 242.5C251.5 242.5 278 272 278 276.5C278 276.5 278.5 267.5 276 265z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M293 111C293 111 281 103 279.5 105C279.5 105 290 111.5 292.5 120C292.5 120 291 111 293 111z"/>
+ </g>
+ <g style="fill: #cccccc">
+ <path d="M301.5 191.5L284 179.5C284 179.5 303 196.5 303.5 200.5L301.5 191.5z"/>
+ </g>
+ <g style="stroke:#000000">
+ <path d="M-89.25 169L-67.25 173.75"/>
+ </g>
+ <g style="stroke:#000000">
+ <path d="M-39 331C-39 331 -39.5 327.5 -48.5 338"/>
+ </g>
+ <g style="stroke:#000000">
+ <path d="M-33.5 336C-33.5 336 -31.5 329.5 -38 334"/>
+ </g>
+ <g style="stroke:#000000">
+ <path d="M20.5 344.5C20.5 344.5 22 333.5 10.5 346.5"/>
+ </g>
+</g>
+</svg>
+
diff --git a/sources/pyside6/tests/QtSvgWidgets/CMakeLists.txt b/sources/pyside6/tests/QtSvgWidgets/CMakeLists.txt
new file mode 100644
index 000000000..61952169a
--- /dev/null
+++ b/sources/pyside6/tests/QtSvgWidgets/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(qsvgwidget_test.py)
diff --git a/sources/pyside6/tests/QtSvgWidgets/QtSvgWidgets.pyproject b/sources/pyside6/tests/QtSvgWidgets/QtSvgWidgets.pyproject
new file mode 100644
index 000000000..6b441ea3e
--- /dev/null
+++ b/sources/pyside6/tests/QtSvgWidgets/QtSvgWidgets.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["qsvgwidget_test.py"]
+}
diff --git a/sources/pyside6/tests/QtSvgWidgets/qsvgwidget_test.py b/sources/pyside6/tests/QtSvgWidgets/qsvgwidget_test.py
new file mode 100644
index 000000000..552d6f49a
--- /dev/null
+++ b/sources/pyside6/tests/QtSvgWidgets/qsvgwidget_test.py
@@ -0,0 +1,41 @@
+#!/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.QtCore import QFile, QFileInfo, QDir
+from PySide6.QtWidgets import QApplication
+from PySide6.QtSvgWidgets import QSvgWidget
+
+
+class QSvgWidgetTest(unittest.TestCase):
+
+ def testLoad(self):
+ directory = os.path.dirname(__file__)
+ tigerPath = QDir.cleanPath(f"{directory}/../QtSvg/tiger.svg")
+ self.assertTrue(QFileInfo.exists(tigerPath))
+
+ app = QApplication([])
+ fromFile = QSvgWidget()
+ fromFile.load(tigerPath)
+ self.assertTrue(fromFile.renderer().isValid())
+
+ tigerFile = QFile(tigerPath)
+ tigerFile.open(QFile.ReadOnly)
+ tigerData = tigerFile.readAll()
+ fromContents = QSvgWidget()
+ fromContents.load(tigerData)
+ self.assertTrue(fromContents.renderer().isValid())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtTest/CMakeLists.txt b/sources/pyside6/tests/QtTest/CMakeLists.txt
new file mode 100644
index 000000000..21a585ea4
--- /dev/null
+++ b/sources/pyside6/tests/QtTest/CMakeLists.txt
@@ -0,0 +1,9 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+PYSIDE_TEST(click_test.py)
+PYSIDE_TEST(eventfilter_test.py)
+# The test is currently permanently broken, needs to be fixed.
+#PYSIDE_TEST(touchevent_test.py)
+PYSIDE_TEST(qsignalspy_test.py)
+PYSIDE_TEST(qvalidator_test.py)
diff --git a/sources/pyside6/tests/QtTest/QtTest.pyproject b/sources/pyside6/tests/QtTest/QtTest.pyproject
new file mode 100644
index 000000000..151c0ef08
--- /dev/null
+++ b/sources/pyside6/tests/QtTest/QtTest.pyproject
@@ -0,0 +1,7 @@
+{
+ "files": ["click_test.py",
+ "eventfilter_test.py",
+ "qsignalspy_test.py",
+ "qvalidator_test.py",
+ "touchevent_test.py"]
+}
diff --git a/sources/pyside6/tests/QtTest/click_test.py b/sources/pyside6/tests/QtTest/click_test.py
new file mode 100644
index 000000000..da8b2dcf6
--- /dev/null
+++ b/sources/pyside6/tests/QtTest/click_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
+
+'''QtTest mouse click functionalities'''
+
+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 Qt, QObject
+from PySide6.QtWidgets import QPushButton, QLineEdit
+from PySide6.QtTest import QTest
+
+from helper.usesqapplication import UsesQApplication
+
+
+class MouseClickTest(UsesQApplication):
+
+ def testBasic(self):
+ '''QTest.mouseClick with QCheckBox'''
+ button = QPushButton()
+ button.setCheckable(True)
+ button.setChecked(False)
+
+ QTest.mouseClick(button, Qt.LeftButton)
+ self.assertTrue(button.isChecked())
+
+ QTest.mouseClick(button, Qt.LeftButton)
+ self.assertFalse(button.isChecked())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtTest/eventfilter_test.py b/sources/pyside6/tests/QtTest/eventfilter_test.py
new file mode 100644
index 000000000..c57974c0d
--- /dev/null
+++ b/sources/pyside6/tests/QtTest/eventfilter_test.py
@@ -0,0 +1,57 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Tests for QKeyEvent'''
+
+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 Qt, QObject, QEvent
+from PySide6.QtGui import QKeyEvent
+from PySide6.QtWidgets import QLineEdit
+from PySide6.QtTest import QTest
+
+from helper.usesqapplication import UsesQApplication
+
+
+class KeyEventFilter(QObject):
+
+ def __init__(self, widget, eventType, key):
+ super().__init__()
+
+ self.widget = widget
+ self.eventType = eventType
+ self.key = key
+
+ self.processed = False
+
+ def eventFilter(self, obj, event):
+ if self.widget == obj and event.type() == self.eventType and \
+ isinstance(event, QKeyEvent) and event.key() == self.key:
+ self.processed = True
+ return True
+
+ return False
+
+
+class EventFilterTest(UsesQApplication):
+
+ def testKeyEvent(self):
+ widget = QLineEdit()
+ key = Qt.Key_A
+ eventFilter = KeyEventFilter(widget, QEvent.KeyPress, key)
+ widget.installEventFilter(eventFilter)
+
+ QTest.keyClick(widget, key)
+
+ self.assertTrue(eventFilter.processed)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtTest/qsignalspy_test.py b/sources/pyside6/tests/QtTest/qsignalspy_test.py
new file mode 100644
index 000000000..06f05b4b8
--- /dev/null
+++ b/sources/pyside6/tests/QtTest/qsignalspy_test.py
@@ -0,0 +1,42 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''QtTest QSignalSpy'''
+
+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 Qt, QObject, SIGNAL
+from PySide6.QtGui import QStandardItem, QStandardItemModel
+from PySide6.QtTest import QTest, QSignalSpy
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QSignalSpyTest(UsesQApplication):
+
+ def setUp(self):
+ super().setUp()
+ self._model = QStandardItemModel(0, 1)
+ self._model.appendRow(QStandardItem('text1'))
+
+ def testStringBased(self):
+ s = SIGNAL('dataChanged(QModelIndex,QModelIndex,QList<int>)')
+ spy = QSignalSpy(self._model, s)
+ self._model.item(0, 0).setText('text2')
+ self.assertEqual(spy.count(), 1)
+
+ def testSignal(self):
+ spy = QSignalSpy(self._model.dataChanged)
+ self._model.item(0, 0).setText('text3')
+ self.assertEqual(spy.count(), 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtTest/qvalidator_test.py b/sources/pyside6/tests/QtTest/qvalidator_test.py
new file mode 100644
index 000000000..2382b8605
--- /dev/null
+++ b/sources/pyside6/tests/QtTest/qvalidator_test.py
@@ -0,0 +1,122 @@
+# 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 QTimer, Qt
+from PySide6.QtGui import QValidator
+from PySide6.QtWidgets import QLineEdit
+from PySide6.QtTest import QTest
+from helper.usesqapplication import UsesQApplication
+
+
+class MyValidator1(QValidator):
+ def fixup(self, input):
+ return "fixed"
+
+ def validate(self, input, pos):
+ return (QValidator.Acceptable, "fixed", 1)
+
+
+class MyValidator2(QValidator):
+ def fixup(self, input):
+ return "fixed"
+
+ def validate(self, input, pos):
+ return (QValidator.Acceptable, "fixed")
+
+
+class MyValidator3(QValidator):
+ def fixup(self, input):
+ return "fixed"
+
+ def validate(self, input, pos):
+ return (QValidator.Acceptable,)
+
+
+class MyValidator4(QValidator):
+ def fixup(self, input):
+ return "fixed"
+
+ def validate(self, input, pos):
+ return QValidator.Acceptable
+
+
+class MyValidator5(QValidator):
+ def validate(self, input, pos):
+ if input.islower():
+ return (QValidator.Intermediate, input, pos)
+ else:
+ return (QValidator.Acceptable, input, pos)
+
+ def fixup(self, input):
+ return "22"
+
+
+class QValidatorTest(UsesQApplication):
+ def testValidator1(self):
+ line = QLineEdit()
+ line.setValidator(MyValidator1())
+ line.show()
+ line.setText("foo")
+
+ QTimer.singleShot(0, line.close)
+ self.app.exec()
+
+ self.assertEqual(line.text(), "fixed")
+ self.assertEqual(line.cursorPosition(), 1)
+
+ def testValidator2(self):
+ line = QLineEdit()
+ line.setValidator(MyValidator2())
+ line.show()
+ line.setText("foo")
+
+ QTimer.singleShot(0, line.close)
+ self.app.exec()
+
+ self.assertEqual(line.text(), "fixed")
+ self.assertEqual(line.cursorPosition(), 3)
+
+ def testValidator3(self):
+ line = QLineEdit()
+ line.setValidator(MyValidator3())
+ line.show()
+ line.setText("foo")
+
+ QTimer.singleShot(0, line.close)
+ self.app.exec()
+
+ self.assertEqual(line.text(), "foo")
+ self.assertEqual(line.cursorPosition(), 3)
+
+ def testValidator4(self):
+ line = QLineEdit()
+ line.setValidator(MyValidator4())
+ line.show()
+ line.setText("foo")
+
+ QTimer.singleShot(0, line.close)
+ self.app.exec()
+
+ self.assertEqual(line.text(), "foo")
+ self.assertEqual(line.cursorPosition(), 3)
+
+ def testValidator5(self):
+ line = QLineEdit()
+ line.show()
+ line.setValidator(MyValidator5())
+ line.setText("foo")
+ QTest.keyClick(line, Qt.Key_Return)
+ self.assertEqual(line.text(), "22")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtTest/touchevent_test.py b/sources/pyside6/tests/QtTest/touchevent_test.py
new file mode 100644
index 000000000..bc07c25ed
--- /dev/null
+++ b/sources/pyside6/tests/QtTest/touchevent_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 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 helper.usesqapplication import UsesQApplication
+
+from PySide6.QtWidgets import QWidget
+from PySide6.QtCore import QPoint, QTimer, Qt, QEvent
+from PySide6.QtGui import QTouchDevice
+from PySide6.QtTest import QTest
+
+
+class MyWidget(QWidget):
+ def __init__(self, parent=None):
+ QWidget.__init__(self, parent)
+ self._sequence = []
+ # Fixme (Qt 5): The device needs to be registered (using
+ # QWindowSystemInterface::registerTouchDevice()) for the test to work
+ self._device = QTouchDevice()
+ self.setAttribute(Qt.WA_AcceptTouchEvents)
+ QTimer.singleShot(200, self.generateEvent)
+
+ def event(self, e):
+ self._sequence.append(e.type())
+ return QWidget.event(self, e)
+
+ def generateEvent(self):
+ o = QTest.touchEvent(self, self._device)
+ o.press(0, QPoint(10, 10))
+ o.commit()
+ del o
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ QTest.touchEvent(self, self._device).press(0, QPoint(10, 10))
+ QTest.touchEvent(self, self._device).stationary(0).press(1, QPoint(40, 10))
+ QTest.touchEvent(self, self._device).move(0, QPoint(12, 12)).move(1, QPoint(45, 5))
+ QTest.touchEvent(self, self._device).release(0, QPoint(12, 12)).release(1, QPoint(45, 5))
+ QTimer.singleShot(200, self.deleteLater)
+
+
+class TouchEventTest(UsesQApplication):
+ def testCreateEvent(self):
+ w = MyWidget()
+ w.show()
+ self.app.exec()
+ # same values as C++
+ self.assertEqual(w._sequence.count(QEvent.Type.TouchBegin), 2)
+ self.assertEqual(w._sequence.count(QEvent.Type.TouchUpdate), 2)
+ self.assertEqual(w._sequence.count(QEvent.Type.TouchEnd), 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtTextToSpeech/CMakeLists.txt b/sources/pyside6/tests/QtTextToSpeech/CMakeLists.txt
new file mode 100644
index 000000000..6f5851587
--- /dev/null
+++ b/sources/pyside6/tests/QtTextToSpeech/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(qtexttospeech_test.py)
diff --git a/sources/pyside6/tests/QtTextToSpeech/QtTextToSpeech.pyproject b/sources/pyside6/tests/QtTextToSpeech/QtTextToSpeech.pyproject
new file mode 100644
index 000000000..eef38fc22
--- /dev/null
+++ b/sources/pyside6/tests/QtTextToSpeech/QtTextToSpeech.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["qtexttospeech_test.py"]
+}
diff --git a/sources/pyside6/tests/QtTextToSpeech/qtexttospeech_test.py b/sources/pyside6/tests/QtTextToSpeech/qtexttospeech_test.py
new file mode 100644
index 000000000..6ff66c047
--- /dev/null
+++ b/sources/pyside6/tests/QtTextToSpeech/qtexttospeech_test.py
@@ -0,0 +1,49 @@
+#!/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
+
+'''Test cases for QTextToSpeech methods'''
+
+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 QTimer
+from PySide6.QtWidgets import QApplication
+
+try:
+ from PySide6.QtTextToSpeech import QTextToSpeech, QVoice
+except ImportError:
+ print("Skipping test due to missing QtTextToSpeech module")
+ sys.exit(0)
+
+
+class QTextToSpeechTestCase(UsesQApplication):
+ '''Tests related to QTextToSpeech'''
+ def testSay(self):
+ engines = QTextToSpeech.availableEngines()
+ if len(engines) > 1 and engines[0] == "mock":
+ engines[0], engines[1] = engines[1], engines[0]
+ if not engines:
+ print('No QTextToSpeech engines available')
+ else:
+ speech = QTextToSpeech(engines[0])
+ speech.stateChanged.connect(self._slotStateChanged)
+ speech.say("Hello, PySide6")
+ QTimer.singleShot(5000, self.app.quit)
+ self.app.exec()
+
+ def _slotStateChanged(self, state):
+ if (state == QTextToSpeech.State.Ready):
+ self.app.quit()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtUiTools/CMakeLists.txt b/sources/pyside6/tests/QtUiTools/CMakeLists.txt
new file mode 100644
index 000000000..08c6f1577
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/CMakeLists.txt
@@ -0,0 +1,16 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+PYSIDE_TEST(bug_360.py)
+PYSIDE_TEST(bug_376.py)
+PYSIDE_TEST(bug_392.py)
+PYSIDE_TEST(bug_426.py)
+PYSIDE_TEST(bug_552.py)
+PYSIDE_TEST(bug_797.py)
+PYSIDE_TEST(bug_909.py)
+PYSIDE_TEST(bug_913.py)
+PYSIDE_TEST(bug_958.py)
+PYSIDE_TEST(bug_965.py)
+PYSIDE_TEST(bug_1060.py)
+PYSIDE_TEST(uiloader_test.py)
+PYSIDE_TEST(ui_test.py)
diff --git a/sources/pyside6/tests/QtUiTools/QtUiTools.pyproject b/sources/pyside6/tests/QtUiTools/QtUiTools.pyproject
new file mode 100644
index 000000000..a83758b87
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/QtUiTools.pyproject
@@ -0,0 +1,28 @@
+{
+ "files": ["action.ui",
+ "bug_1060.py",
+ "bug_1060.ui",
+ "bug_360.py",
+ "bug_376.py",
+ "bug_392.py",
+ "bug_426.py",
+ "bug_426.ui",
+ "bug_552.py",
+ "bug_552.ui",
+ "bug_797.py",
+ "bug_909.py",
+ "bug_909.ui",
+ "bug_913.py",
+ "bug_913.ui",
+ "bug_958.py",
+ "bug_958.ui",
+ "bug_965.py",
+ "bug_965.ui",
+ "loadUiType_test.py",
+ "minimal.ui",
+ "pycustomwidget.ui",
+ "pycustomwidget2.ui",
+ "test.ui",
+ "ui_test.py",
+ "uiloader_test.py"]
+}
diff --git a/sources/pyside6/tests/QtUiTools/action.ui b/sources/pyside6/tests/QtUiTools/action.ui
new file mode 100644
index 000000000..9eda559de
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/action.ui
@@ -0,0 +1,16 @@
+<ui version="4.0">
+ <class>main_window</class>
+ <widget class="QMainWindow" name="main_window">
+ <widget class="QWidget" name="centralwidget"/>
+ <widget class="QMenuBar" name="menubar"/>
+ <widget class="QStatusBar" name="statusbar">
+ <action name="actionFoo">
+ <property name="text">
+ <string>foo</string>
+ </property>
+ </action>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/sources/pyside6/tests/QtUiTools/bug_1060.py b/sources/pyside6/tests/QtUiTools/bug_1060.py
new file mode 100644
index 000000000..52624a2a9
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_1060.py
@@ -0,0 +1,32 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+''' unit test for BUG #1060 '''
+
+import os
+import sys
+
+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.QtWidgets import QApplication
+from PySide6.QtUiTools import QUiLoader
+
+
+class MyQUiLoader(QUiLoader):
+ def __init__(self):
+ super().__init__()
+
+ def createWidget(self, *args):
+ return super(MyQUiLoader, self).createWidget(*args)
+
+
+if __name__ == "__main__":
+ app = QApplication([])
+
+ file = Path(__file__).resolve().parent / 'bug_1060.ui'
+ assert (file.is_file())
+ ui = MyQUiLoader().load(file)
+ ui.show()
diff --git a/sources/pyside6/tests/QtUiTools/bug_1060.ui b/sources/pyside6/tests/QtUiTools/bug_1060.ui
new file mode 100644
index 000000000..f4044a8c2
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_1060.ui
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>100</width>
+ <height>100</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/sources/pyside6/tests/QtUiTools/bug_360.py b/sources/pyside6/tests/QtUiTools/bug_360.py
new file mode 100644
index 000000000..8ca764eae
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_360.py
@@ -0,0 +1,48 @@
+# 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.QtWidgets import QFrame, QWidget
+from PySide6.QtUiTools import QUiLoader
+
+
+class MyQUiLoader(QUiLoader):
+ def __init__(self, baseinstance):
+ super().__init__()
+ self.baseinstance = baseinstance
+ self._widgets = []
+
+ def createWidget(self, className, parent=None, name=""):
+ widget = QUiLoader.createWidget(self, className, parent, name)
+ self._widgets.append(widget)
+ if parent is None:
+ return self.baseinstance
+ else:
+ setattr(self.baseinstance, name, widget)
+ return widget
+
+
+class ButTest(UsesQApplication):
+ def testCase(self):
+ w = QWidget()
+ loader = MyQUiLoader(w)
+
+ filePath = os.path.join(os.path.dirname(__file__), 'minimal.ui')
+ ui = loader.load(filePath)
+
+ self.assertEqual(len(loader._widgets), 1)
+ self.assertEqual(type(loader._widgets[0]), QFrame)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtUiTools/bug_376.py b/sources/pyside6/tests/QtUiTools/bug_376.py
new file mode 100644
index 000000000..eefc1fe05
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_376.py
@@ -0,0 +1,31 @@
+# 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.QtWidgets import QFrame, QWidget
+from PySide6.QtUiTools import QUiLoader
+
+
+class BugTest(UsesQApplication):
+ def testCase(self):
+ w = QWidget()
+ loader = QUiLoader()
+
+ filePath = os.path.join(os.path.dirname(__file__), 'test.ui')
+ result = loader.load(filePath, w)
+ self.assertTrue(isinstance(result.child_object, QFrame))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtUiTools/bug_392.py b/sources/pyside6/tests/QtUiTools/bug_392.py
new file mode 100644
index 000000000..4d69fdbec
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_392.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(False)
+
+from helper.usesqapplication import UsesQApplication
+
+from PySide6.QtGui import QAction
+from PySide6.QtWidgets import QComboBox, QWidget
+from PySide6.QtUiTools import QUiLoader
+
+
+class MyWidget(QComboBox):
+ def __init__(self, parent=None):
+ QComboBox.__init__(self, parent)
+
+ def isPython(self):
+ return True
+
+
+class BugTest(UsesQApplication):
+ def testCase(self):
+ w = QWidget()
+ loader = QUiLoader()
+
+ filePath = os.path.join(os.path.dirname(__file__), 'action.ui')
+ result = loader.load(filePath, w)
+ self.assertTrue(isinstance(result.actionFoo, QAction))
+
+ def testPythonCustomWidgets(self):
+ w = QWidget()
+ loader = QUiLoader()
+ loader.registerCustomWidget(MyWidget)
+ self.assertTrue('MyWidget' in loader.availableWidgets())
+
+ filePath = os.path.join(os.path.dirname(__file__), 'pycustomwidget.ui')
+ result = loader.load(filePath, w)
+ self.assertTrue(isinstance(result.custom, MyWidget))
+ self.assertTrue(result.custom.isPython())
+
+ def testPythonCustomWidgetsTwice(self):
+ w = QWidget()
+ loader = QUiLoader()
+ loader.registerCustomWidget(MyWidget)
+ self.assertTrue('MyWidget' in loader.availableWidgets())
+
+ filePath = os.path.join(os.path.dirname(__file__), 'pycustomwidget2.ui')
+ result = loader.load(filePath, w)
+ self.assertTrue(isinstance(result.custom, MyWidget))
+ self.assertTrue(isinstance(result.custom2, MyWidget))
+ self.assertTrue(result.custom.isPython())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtUiTools/bug_426.py b/sources/pyside6/tests/QtUiTools/bug_426.py
new file mode 100644
index 000000000..3a568e4e2
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_426.py
@@ -0,0 +1,32 @@
+# 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 QTimer
+from PySide6.QtGui import QAction, QActionGroup
+from PySide6.QtWidgets import QApplication, QWidget
+from PySide6.QtUiTools import QUiLoader
+
+
+class Window(object):
+ def __init__(self):
+ loader = QUiLoader()
+ filePath = os.path.join(os.path.dirname(__file__), 'bug_426.ui')
+ self.widget = loader.load(filePath)
+ self.group = QActionGroup(self.widget)
+ self.widget.show()
+ QTimer.singleShot(0, self.widget.close)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ win = Window()
+ sys.exit(app.exec())
diff --git a/sources/pyside6/tests/QtUiTools/bug_426.ui b/sources/pyside6/tests/QtUiTools/bug_426.ui
new file mode 100644
index 000000000..99353cd2b
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_426.ui
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/sources/pyside6/tests/QtUiTools/bug_552.py b/sources/pyside6/tests/QtUiTools/bug_552.py
new file mode 100644
index 000000000..06a6b72a4
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_552.py
@@ -0,0 +1,37 @@
+# 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
+from PySide6.QtWidgets import QApplication, QFrame, QWidget
+from PySide6.QtUiTools import QUiLoader
+
+
+class View_1(QWidget):
+
+ def __init__(self):
+ super().__init__()
+ loader = QUiLoader()
+ file = Path(__file__).resolve().parent / 'bug_552.ui'
+ assert (file.is_file())
+ widget = loader.load(os.fspath(file), self)
+ self.children = []
+ for child in widget.findChildren(QObject, None):
+ self.children.append(child)
+ self.t = widget.tabWidget
+ self.t.removeTab(0)
+
+
+app = QApplication([])
+window = View_1()
+window.show()
+
+# If it doesn't crash it works :-)
diff --git a/sources/pyside6/tests/QtUiTools/bug_552.ui b/sources/pyside6/tests/QtUiTools/bug_552.ui
new file mode 100644
index 000000000..f98da4421
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_552.ui
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="geometry">
+ <rect>
+ <x>130</x>
+ <y>80</y>
+ <width>139</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ </widget>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>Tab 2</string>
+ </attribute>
+ </widget>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/sources/pyside6/tests/QtUiTools/bug_797.py b/sources/pyside6/tests/QtUiTools/bug_797.py
new file mode 100644
index 000000000..3dae7afb7
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_797.py
@@ -0,0 +1,25 @@
+# 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.QtUiTools import QUiLoader
+from PySide6.QtCore import QFile
+from PySide6.QtWidgets import QApplication, QWidget
+
+
+app = QApplication([])
+loader = QUiLoader()
+file = Path(__file__).resolve().parent / 'bug_552.ui'
+assert (file.is_file())
+file = QFile(file)
+w = QWidget()
+# An exception can't be thrown
+mainWindow = loader.load(file, w)
diff --git a/sources/pyside6/tests/QtUiTools/bug_909.py b/sources/pyside6/tests/QtUiTools/bug_909.py
new file mode 100644
index 000000000..cd4d50a0b
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_909.py
@@ -0,0 +1,37 @@
+# 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 QFile
+from PySide6.QtWidgets import QTabWidget
+from PySide6.QtUiTools import QUiLoader
+
+from helper.usesqapplication import UsesQApplication
+
+
+class TestDestruction(UsesQApplication):
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testBug909(self):
+ file = Path(__file__).resolve().parent / 'bug_909.ui'
+ self.assertTrue(file.is_file())
+ fileName = QFile(file)
+ loader = QUiLoader()
+ main_win = loader.load(fileName)
+ self.assertEqual(sys.getrefcount(main_win), 2)
+ fileName.close()
+
+ tw = QTabWidget(main_win)
+ main_win.setCentralWidget(tw)
+ main_win.show()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtUiTools/bug_909.ui b/sources/pyside6/tests/QtUiTools/bug_909.ui
new file mode 100644
index 000000000..b07f62d05
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_909.ui
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>600</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralwidget"/>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>25</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/sources/pyside6/tests/QtUiTools/bug_913.py b/sources/pyside6/tests/QtUiTools/bug_913.py
new file mode 100644
index 000000000..85df29d11
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_913.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env 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.QtWidgets import QApplication
+from PySide6.QtUiTools import QUiLoader
+
+
+class TestBug913 (unittest.TestCase):
+
+ def testIt(self):
+ app = QApplication([])
+
+ loader = QUiLoader()
+ file = Path(__file__).resolve().parent / 'bug_913.ui'
+ self.assertTrue(file.is_file())
+ widget = loader.load(file)
+ widget.tabWidget.currentIndex() # direct child is available as member
+ widget.le_first.setText('foo') # child of QTabWidget must also be available!
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtUiTools/bug_913.ui b/sources/pyside6/tests/QtUiTools/bug_913.ui
new file mode 100644
index 000000000..0fc95fd53
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_913.ui
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>First name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="le_first"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Last name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="le_last"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>Tab 2</string>
+ </attribute>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/sources/pyside6/tests/QtUiTools/bug_958.py b/sources/pyside6/tests/QtUiTools/bug_958.py
new file mode 100644
index 000000000..2f8dfab62
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_958.py
@@ -0,0 +1,40 @@
+# 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.QtWidgets import QMainWindow
+from PySide6.QtUiTools import QUiLoader
+from helper.timedqapplication import TimedQApplication
+
+
+class Gui_Qt(QMainWindow):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ lLoader = QUiLoader()
+
+ # this used to cause a segfault because the old inject code used to destroy the parent layout
+ file = Path(__file__).resolve().parent / 'bug_958.ui'
+ assert (file.is_file())
+ self._cw = lLoader.load(file, self)
+
+ self.setCentralWidget(self._cw)
+
+
+class BugTest(TimedQApplication):
+ def testCase(self):
+ lMain = Gui_Qt()
+ lMain.show()
+ self.app.exec()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtUiTools/bug_958.ui b/sources/pyside6/tests/QtUiTools/bug_958.ui
new file mode 100644
index 000000000..57cdbddba
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_958.ui
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>customWidget</class>
+ <widget class="QWidget" name="customWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>626</width>
+ <height>578</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>500</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTableWidget" name="resultTable"/>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="progressBar">
+ <property name="value">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="actionLayout">
+ <item>
+ <widget class="QPushButton" name="processButton">
+ <property name="text">
+ <string>&amp;Berechnen</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/sources/pyside6/tests/QtUiTools/bug_965.py b/sources/pyside6/tests/QtUiTools/bug_965.py
new file mode 100644
index 000000000..2308cbeed
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_965.py
@@ -0,0 +1,35 @@
+# 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.QtUiTools import QUiLoader
+
+from helper.usesqapplication import UsesQApplication
+
+
+class MyQUiLoader(QUiLoader):
+ def __init__(self):
+ super().__init__()
+
+ def createWidget(self, className, parent=None, name=""):
+ return None
+
+
+class BugTest(UsesQApplication):
+ def testCase(self):
+ loader = MyQUiLoader()
+ file = Path(__file__).resolve().parent / 'bug_965.ui'
+ self.assertTrue(file.is_file())
+ self.assertRaises(RuntimeError, loader.load, file)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtUiTools/bug_965.ui b/sources/pyside6/tests/QtUiTools/bug_965.ui
new file mode 100644
index 000000000..e324db829
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/bug_965.ui
@@ -0,0 +1,27 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+ <property name="objectName" >
+ <string notr="true" >MainWindow</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>600</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>MainWindow</string>
+ </property>
+ <widget class="QMenuBar" name="menubar" />
+ <widget class="QWidget" name="centralwidget" />
+ <widget class="QStatusBar" name="statusbar" />
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <connections/>
+</ui>
diff --git a/sources/pyside6/tests/QtUiTools/loadUiType_test.py b/sources/pyside6/tests/QtUiTools/loadUiType_test.py
new file mode 100644
index 000000000..b0842318c
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/loadUiType_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(False)
+
+from helper.usesqapplication import UsesQApplication
+
+from PySide6.QtWidgets import QWidget, QFrame, QPushButton
+from PySide6.QtUiTools import loadUiType
+
+
+class loadUiTypeTester(UsesQApplication):
+ def testFunction(self):
+ filePath = os.path.join(os.path.dirname(__file__), "minimal.ui")
+ loaded = loadUiType(filePath)
+ self.assertNotEqual(loaded, None)
+
+ # (<class '__main__.Ui_Form'>, <class 'PySide6.QtWidgets.QFrame'>)
+ generated, base = loaded
+
+ # Generated class contains retranslateUi method
+ self.assertTrue("retranslateUi" in dir(generated))
+
+ # Base class instance will be QFrame for this example
+ self.assertTrue(isinstance(base(), QFrame))
+
+ anotherFileName = os.path.join(os.path.dirname(__file__), "test.ui")
+ another = loadUiType(anotherFileName)
+ self.assertNotEqual(another, None)
+
+ generated, base = another
+ # Base class instance will be QWidget for this example
+ self.assertTrue(isinstance(base(), QWidget))
+
+ w = base()
+ ui = generated()
+ ui.setupUi(w)
+
+ self.assertTrue(isinstance(ui.child_object, QFrame))
+ self.assertTrue(isinstance(ui.grandson_object, QPushButton))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtUiTools/minimal.ui b/sources/pyside6/tests/QtUiTools/minimal.ui
new file mode 100644
index 000000000..c6bb70cda
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/minimal.ui
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QFrame" name="Form">
+ </widget>
+</ui>
diff --git a/sources/pyside6/tests/QtUiTools/pycustomwidget.ui b/sources/pyside6/tests/QtUiTools/pycustomwidget.ui
new file mode 100644
index 000000000..c066153a0
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/pycustomwidget.ui
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>qwidget</class>
+ <widget class="QWidget" name="qwidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string/>
+ </property>
+ <widget class="MyWidget" name="custom">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>79</width>
+ <height>23</height>
+ </rect>
+ </property>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>MyWidget</class>
+ <extends>QComboBox</extends>
+ <header>customwidget</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/sources/pyside6/tests/QtUiTools/pycustomwidget2.ui b/sources/pyside6/tests/QtUiTools/pycustomwidget2.ui
new file mode 100644
index 000000000..8826ac1fb
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/pycustomwidget2.ui
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>qwidget</class>
+ <widget class="QWidget" name="qwidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string/>
+ </property>
+
+ <widget class="MyWidget" name="custom">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>79</width>
+ <height>23</height>
+ </rect>
+ </property>
+ </widget>
+
+ <widget class="MyWidget" name="custom2">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>79</width>
+ <height>23</height>
+ </rect>
+ </property>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>MyWidget</class>
+ <extends>QComboBox</extends>
+ <header>customwidget</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/sources/pyside6/tests/QtUiTools/test.ui b/sources/pyside6/tests/QtUiTools/test.ui
new file mode 100644
index 000000000..60afe22b3
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/test.ui
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>185</width>
+ <height>133</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <widget class="QFrame" name="child_object">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>181</width>
+ <height>131</height>
+ </rect>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <widget class="QPushButton" name="grandson_object">
+ <property name="geometry">
+ <rect>
+ <x>50</x>
+ <y>60</y>
+ <width>80</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>PushButton</string>
+ </property>
+ </widget>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/sources/pyside6/tests/QtUiTools/ui_test.py b/sources/pyside6/tests/QtUiTools/ui_test.py
new file mode 100644
index 000000000..4e2fa808b
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/ui_test.py
@@ -0,0 +1,25 @@
+# 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.QtUiTools import QUiLoader
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QUiLoaderCreation(UsesQApplication):
+
+ def testConstructor(self):
+ loader = QUiLoader()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtUiTools/uiloader_test.py b/sources/pyside6/tests/QtUiTools/uiloader_test.py
new file mode 100644
index 000000000..19e26912e
--- /dev/null
+++ b/sources/pyside6/tests/QtUiTools/uiloader_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 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.QtWidgets import QWidget
+from PySide6.QtUiTools import QUiLoader
+
+
+class OverridingLoader(QUiLoader):
+ def createWidget(self, class_name, parent=None, name=''):
+ if class_name == 'QWidget':
+ w = QWidget(parent)
+ w.setObjectName(name)
+ return w
+ return QUiLoader.createWidget(self, class_name, parent, name)
+
+
+class QUiLoaderTester(UsesQApplication):
+ def setUp(self):
+ UsesQApplication.setUp(self)
+ self._filePath = os.path.join(os.path.dirname(__file__), 'test.ui')
+
+ def testLoadFile(self):
+ loader = QUiLoader()
+ parent = QWidget()
+ w = loader.load(self._filePath, parent)
+ self.assertNotEqual(w, None)
+
+ self.assertEqual(len(parent.children()), 1)
+
+ child = w.findChild(QWidget, "child_object")
+ self.assertNotEqual(child, None)
+ self.assertEqual(w.findChild(QWidget, "grandson_object"), child.findChild(QWidget, "grandson_object"))
+
+ def testLoadFileOverride(self):
+ # PYSIDE-1070, override QUiLoader::createWidget() with parent=None crashes
+ loader = OverridingLoader()
+ w = loader.load(self._filePath)
+ self.assertNotEqual(w, None)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWebChannel/CMakeLists.txt b/sources/pyside6/tests/QtWebChannel/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtWebChannel/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtWebEngineCore/CMakeLists.txt b/sources/pyside6/tests/QtWebEngineCore/CMakeLists.txt
new file mode 100644
index 000000000..c855d119d
--- /dev/null
+++ b/sources/pyside6/tests/QtWebEngineCore/CMakeLists.txt
@@ -0,0 +1,5 @@
+# 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_TEST(web_engine_custom_scheme.py)
+PYSIDE_TEST(qwebenginecookiestore_test.py)
diff --git a/sources/pyside6/tests/QtWebEngineCore/QtWebEngineCore.pyproject b/sources/pyside6/tests/QtWebEngineCore/QtWebEngineCore.pyproject
new file mode 100644
index 000000000..25923c2a8
--- /dev/null
+++ b/sources/pyside6/tests/QtWebEngineCore/QtWebEngineCore.pyproject
@@ -0,0 +1,4 @@
+{
+ "files": ["qwebenginecookiestore_test.py",
+ "web_engine_custom_scheme.py"]
+}
diff --git a/sources/pyside6/tests/QtWebEngineCore/qwebenginecookiestore_test.py b/sources/pyside6/tests/QtWebEngineCore/qwebenginecookiestore_test.py
new file mode 100644
index 000000000..a30c72a8e
--- /dev/null
+++ b/sources/pyside6/tests/QtWebEngineCore/qwebenginecookiestore_test.py
@@ -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
+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 QUrl
+from PySide6.QtWidgets import QApplication
+from PySide6.QtWebEngineWidgets import QWebEngineView
+
+from helper.usesqapplication import UsesQApplication
+
+
+class TestQWebEngineCookieStore(UsesQApplication):
+ def testBasicFilter(self):
+ src_dir = Path(__file__).resolve().parent
+ html_path = src_dir / "resources" / "index.html"
+ view = QWebEngineView()
+ cookie_store = view.page().profile().cookieStore()
+ firstPartyUrlPaths = []
+
+ def cookie_filter(request):
+ nonlocal firstPartyUrlPaths
+ firstPartyUrlPaths.append(Path(request.firstPartyUrl.toLocalFile()))
+ return False
+
+ cookie_store.setCookieFilter(cookie_filter)
+ view.loadFinished.connect(self._slot_loaded)
+ view.load(QUrl.fromLocalFile(html_path))
+ view.show()
+ self.app.exec()
+
+ self.assertEqual(len(firstPartyUrlPaths), 2)
+ self.assertListEqual(firstPartyUrlPaths, [html_path, html_path])
+
+ def _slot_loaded(self):
+ QApplication.quit()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWebEngineCore/resources/index.html b/sources/pyside6/tests/QtWebEngineCore/resources/index.html
new file mode 100644
index 000000000..4c020b714
--- /dev/null
+++ b/sources/pyside6/tests/QtWebEngineCore/resources/index.html
@@ -0,0 +1,12 @@
+<html>
+ <head>
+ <script type="text/javascript">
+function setCookie() {
+ document.cookie = "test1"
+ document.cookie = "test2"
+}
+</script>
+ </head>
+ <body onload="setCookie()">
+ </body>
+</html>
diff --git a/sources/pyside6/tests/QtWebEngineCore/web_engine_custom_scheme.py b/sources/pyside6/tests/QtWebEngineCore/web_engine_custom_scheme.py
new file mode 100644
index 000000000..10c8e88d7
--- /dev/null
+++ b/sources/pyside6/tests/QtWebEngineCore/web_engine_custom_scheme.py
@@ -0,0 +1,70 @@
+# 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 QBuffer, Qt, QTimer
+from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout
+from PySide6.QtWebEngineWidgets import QWebEngineView
+from PySide6.QtWebEngineCore import (QWebEngineProfile,
+ QWebEngineUrlScheme,
+ QWebEngineUrlSchemeHandler)
+
+
+class TestSchemeHandler(QWebEngineUrlSchemeHandler):
+ def requestStarted(self, request):
+ if request.requestUrl() == "testpy:hello":
+ request.redirect("testpy:goodbye")
+ return
+
+ self.buffer = QBuffer()
+ self.buffer.setData(bytes("Really nice goodbye text.", "UTF-8"))
+ self.buffer.aboutToClose.connect(self.buffer.deleteLater)
+ request.reply(bytes("text/plain;charset=utf-8", "UTF-8"), self.buffer)
+
+
+class MainTest(unittest.TestCase):
+ def test_SchemeHandlerRedirect(self):
+ self._loaded = False
+ QApplication.setAttribute(Qt.AA_ShareOpenGLContexts)
+ app = QApplication([])
+
+ scheme_name = bytes("testpy", "UTF-8")
+ scheme = QWebEngineUrlScheme(scheme_name)
+ scheme.setSyntax(QWebEngineUrlScheme.Syntax.Path)
+ QWebEngineUrlScheme.registerScheme(scheme)
+ handler = TestSchemeHandler()
+ profile = QWebEngineProfile.defaultProfile()
+ profile.installUrlSchemeHandler(scheme_name, handler)
+
+ top_level_widget = QWidget()
+ top_level_widget.setWindowTitle('web_engine_custom_scheme.py')
+ top_level_widget.resize(400, 400)
+ layout = QVBoxLayout(top_level_widget)
+ view = QWebEngineView()
+ layout.addWidget(view)
+
+ view.loadFinished.connect(self._slot_loaded)
+ QTimer.singleShot(5000, app.quit)
+
+ top_level_widget.show()
+ view.load("testpy:hello")
+ app.exec()
+
+ self.assertTrue(self._loaded)
+ self.assertEqual(view.url(), "testpy:goodbye")
+
+ def _slot_loaded(self):
+ self._loaded = True
+ QApplication.quit()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWebEngineQuick/CMakeLists.txt b/sources/pyside6/tests/QtWebEngineQuick/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtWebEngineQuick/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtWebEngineWidgets/CMakeLists.txt b/sources/pyside6/tests/QtWebEngineWidgets/CMakeLists.txt
new file mode 100644
index 000000000..ce2c6eeae
--- /dev/null
+++ b/sources/pyside6/tests/QtWebEngineWidgets/CMakeLists.txt
@@ -0,0 +1,4 @@
+# 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_TEST(pyside-474-qtwebengineview.py)
diff --git a/sources/pyside6/tests/QtWebEngineWidgets/QtWebEngineWidgets.pyproject b/sources/pyside6/tests/QtWebEngineWidgets/QtWebEngineWidgets.pyproject
new file mode 100644
index 000000000..e44646682
--- /dev/null
+++ b/sources/pyside6/tests/QtWebEngineWidgets/QtWebEngineWidgets.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["pyside-474-qtwebengineview.py"]
+}
diff --git a/sources/pyside6/tests/QtWebEngineWidgets/fox.html b/sources/pyside6/tests/QtWebEngineWidgets/fox.html
new file mode 100644
index 000000000..da873b1cc
--- /dev/null
+++ b/sources/pyside6/tests/QtWebEngineWidgets/fox.html
@@ -0,0 +1,7 @@
+<html>
+<title>Title</title>
+<meta name="description" content="PySide Test METADATA." />
+<body>
+<p>The quick <b>brown</b> fox <i>jumps</i> over the lazy dog.</p>
+</body>
+</html>
diff --git a/sources/pyside6/tests/QtWebEngineWidgets/pyside-474-qtwebengineview.py b/sources/pyside6/tests/QtWebEngineWidgets/pyside-474-qtwebengineview.py
new file mode 100644
index 000000000..3739e956a
--- /dev/null
+++ b/sources/pyside6/tests/QtWebEngineWidgets/pyside-474-qtwebengineview.py
@@ -0,0 +1,59 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+from functools import partial
+import os
+import sys
+import unittest
+
+TEST_DIR = os.path.dirname(os.path.abspath(__file__))
+
+sys.path.append(os.path.dirname(TEST_DIR))
+from init_paths import init_test_paths
+init_test_paths(False)
+
+from PySide6.QtCore import QCoreApplication, QSize, QUrl, Qt
+from PySide6.QtWidgets import QApplication, QVBoxLayout, QWidget
+from PySide6.QtWebEngineCore import QWebEnginePage
+from PySide6.QtWebEngineWidgets import QWebEngineView
+
+
+class MainTest(unittest.TestCase):
+
+ def test_WebEngineView_findText_exists(self):
+ app = QApplication.instance() or QApplication()
+ top_level = QWidget()
+ layout = QVBoxLayout(top_level)
+ self._view = QWebEngineView()
+ self._view.loadFinished.connect(self.loaded)
+ self._view.load(QUrl.fromLocalFile(os.path.join(TEST_DIR, "fox.html")))
+ self._view.setMinimumSize(QSize(400, 300))
+ self._callback_count = 0
+ layout.addWidget(self._view)
+ top_level.show()
+ app.exec()
+
+ def found_callback(self, found):
+ self.assertTrue(found)
+ self._callback_count += 1
+ if self._callback_count == 2:
+ QCoreApplication.quit()
+
+ def javascript_callback(self, result):
+ self.assertEqual(result, "Title")
+ self._callback_count += 1
+ if self._callback_count == 2:
+ QCoreApplication.quit()
+
+ def loaded(self, ok):
+ self.assertTrue(ok)
+ if not ok:
+ QCoreApplication.quit()
+ self._view.page().runJavaScript("document.title", 1,
+ partial(self.javascript_callback))
+ self._view.findText("fox", QWebEnginePage.FindFlag(0),
+ partial(self.found_callback))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWebSockets/CMakeLists.txt b/sources/pyside6/tests/QtWebSockets/CMakeLists.txt
new file mode 100644
index 000000000..2f7cb08b9
--- /dev/null
+++ b/sources/pyside6/tests/QtWebSockets/CMakeLists.txt
@@ -0,0 +1 @@
+# Please add some tests, here
diff --git a/sources/pyside6/tests/QtWidgets/CMakeLists.txt b/sources/pyside6/tests/QtWidgets/CMakeLists.txt
new file mode 100644
index 000000000..01b7d08ea
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/CMakeLists.txt
@@ -0,0 +1,134 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#Keep this in alphabetical sort
+
+PYSIDE_TEST(action_clear.py)
+PYSIDE_TEST(add_action_test.py)
+PYSIDE_TEST(api2_test.py)
+PYSIDE_TEST(application_test.py)
+PYSIDE_TEST(bug_172.py)
+PYSIDE_TEST(bug_243.py)
+PYSIDE_TEST(bug_307.py)
+PYSIDE_TEST(bug_338.py)
+PYSIDE_TEST(bug_389.py)
+PYSIDE_TEST(bug_400.py)
+PYSIDE_TEST(bug_429.py)
+PYSIDE_TEST(bug_430.py)
+PYSIDE_TEST(bug_433.py)
+PYSIDE_TEST(bug_467.py)
+PYSIDE_TEST(bug_480.py)
+PYSIDE_TEST(bug_512.py)
+PYSIDE_TEST(bug_525.py)
+PYSIDE_TEST(bug_546.py)
+PYSIDE_TEST(bug_547.py)
+PYSIDE_TEST(bug_549.py)
+PYSIDE_TEST(bug_569.py)
+PYSIDE_TEST(bug_575.py)
+PYSIDE_TEST(bug_576.py)
+PYSIDE_TEST(bug_585.py)
+PYSIDE_TEST(bug_589.py)
+PYSIDE_TEST(bug_635.py)
+PYSIDE_TEST(bug_640.py)
+PYSIDE_TEST(bug_653.py)
+PYSIDE_TEST(bug_662.py)
+PYSIDE_TEST(bug_667.py)
+PYSIDE_TEST(bug_668.py)
+PYSIDE_TEST(bug_674.py)
+PYSIDE_TEST(bug_675.py)
+PYSIDE_TEST(bug_688.py)
+PYSIDE_TEST(bug_693.py)
+PYSIDE_TEST(bug_696.py)
+PYSIDE_TEST(bug_711.py)
+PYSIDE_TEST(bug_722.py)
+PYSIDE_TEST(bug_728.py)
+PYSIDE_TEST(bug_736.py)
+PYSIDE_TEST(bug_750.py)
+PYSIDE_TEST(bug_778.py)
+PYSIDE_TEST(bug_793.py)
+PYSIDE_TEST(bug_811.py)
+PYSIDE_TEST(bug_834.py)
+PYSIDE_TEST(bug_836.py)
+PYSIDE_TEST(bug_844.py)
+PYSIDE_TEST(bug_854.py)
+PYSIDE_TEST(bug_860.py)
+PYSIDE_TEST(bug_862.py)
+PYSIDE_TEST(bug_871.py)
+PYSIDE_TEST(bug_879.py)
+PYSIDE_TEST(bug_919.py)
+PYSIDE_TEST(bug_921.py)
+PYSIDE_TEST(bug_941.py)
+PYSIDE_TEST(bug_964.py)
+PYSIDE_TEST(bug_967.py)
+PYSIDE_TEST(bug_972.py)
+PYSIDE_TEST(bug_979.py)
+PYSIDE_TEST(bug_988.py)
+PYSIDE_TEST(bug_998.py)
+PYSIDE_TEST(bug_1002.py)
+PYSIDE_TEST(bug_1006.py)
+PYSIDE_TEST(bug_1048.py)
+PYSIDE_TEST(bug_1077.py)
+PYSIDE_TEST(customproxywidget_test.py)
+PYSIDE_TEST(grandparent_method_test.py)
+PYSIDE_TEST(hashabletype_test.py)
+PYSIDE_TEST(keep_reference_test.py)
+PYSIDE_TEST(missing_symbols_test.py)
+PYSIDE_TEST(paint_event_test.py)
+PYSIDE_TEST(parent_method_test.py)
+PYSIDE_TEST(private_mangle_test.py)
+PYSIDE_TEST(python_properties_test.py)
+PYSIDE_TEST(qabstracttextdocumentlayout_test.py)
+PYSIDE_TEST(qaccessible_test.py)
+PYSIDE_TEST(qaction_test.py)
+PYSIDE_TEST(qapp_issue_585.py)
+PYSIDE_TEST(qapp_test.py)
+PYSIDE_TEST(qapplication_test.py)
+PYSIDE_TEST(qapplication_exit_segfault_test.py)
+PYSIDE_TEST(qdialog_test.py)
+PYSIDE_TEST(qdynamic_signal.py)
+# TODO: This passes, but requires manual button clicking (at least on mac)
+#PYSIDE_TEST(qfontdialog_test.py)
+PYSIDE_TEST(qformlayout_test.py)
+PYSIDE_TEST(qgraphicsitem_test.py)
+PYSIDE_TEST(qgraphicsitem_isblocked_test.py)
+PYSIDE_TEST(qgraphicsobjectreimpl_test.py)
+PYSIDE_TEST(qgraphicsproxywidget_test.py)
+PYSIDE_TEST(qgraphicsscene_test.py)
+PYSIDE_TEST(qinputdialog_get_test.py)
+PYSIDE_TEST(qkeysequenceedit_test.py)
+PYSIDE_TEST(qlabel_test.py)
+PYSIDE_TEST(qlayout_ref_test.py)
+PYSIDE_TEST(qlayout_test.py)
+PYSIDE_TEST(qlcdnumber_test.py)
+PYSIDE_TEST(qlistwidget_test.py)
+PYSIDE_TEST(qlistwidgetitem_test.py)
+PYSIDE_TEST(qmainwindow_test.py)
+PYSIDE_TEST(qmenu_test.py)
+PYSIDE_TEST(qmenuadd_test.py)
+PYSIDE_TEST(qobject_mi_test.py)
+PYSIDE_TEST(qpicture_test.py)
+PYSIDE_TEST(qpushbutton_test.py)
+PYSIDE_TEST(qsplitter_test.py)
+PYSIDE_TEST(qstyle_test.py)
+PYSIDE_TEST(qstyleoption_test.py)
+PYSIDE_TEST(qtableview_test.py)
+PYSIDE_TEST(qtabwidget_test.py)
+PYSIDE_TEST(qtabwidgetclear_test.py)
+PYSIDE_TEST(qtextedit_test.py)
+PYSIDE_TEST(qtextedit_signal_test.py)
+PYSIDE_TEST(qtreeview_test.py)
+PYSIDE_TEST(qtreewidget_test.py)
+PYSIDE_TEST(qtreewidgetitem_test.py)
+PYSIDE_TEST(qtoolbar_test.py)
+PYSIDE_TEST(qtoolbox_test.py)
+PYSIDE_TEST(qvariant_test.py)
+PYSIDE_TEST(qwidget_setlayout_test.py)
+PYSIDE_TEST(qwidget_test.py)
+PYSIDE_TEST(qcolormap_test.py)
+PYSIDE_TEST(reference_count_test.py)
+PYSIDE_TEST(signature_test.py)
+PYSIDE_TEST(standardpixmap_test.py)
+PYSIDE_TEST(test_module_template.py)
+PYSIDE_TEST(virtual_protected_inheritance_test.py)
+PYSIDE_TEST(virtual_pure_override_test.py)
+PYSIDE_TEST(wrong_return_test.py)
diff --git a/sources/pyside6/tests/QtWidgets/QtWidgets.pyproject b/sources/pyside6/tests/QtWidgets/QtWidgets.pyproject
new file mode 100644
index 000000000..36c000165
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/QtWidgets.pyproject
@@ -0,0 +1,130 @@
+{
+ "files": ["action_clear.py",
+ "add_action_test.py",
+ "api2_test.py",
+ "application_test.py",
+ "bug_1002.py",
+ "bug_1006.py",
+ "bug_1048.py",
+ "bug_1077.py",
+ "bug_172.py",
+ "bug_243.py",
+ "bug_307.py",
+ "bug_338.py",
+ "bug_389.py",
+ "bug_400.py",
+ "bug_429.py",
+ "bug_430.py",
+ "bug_433.py",
+ "bug_467.py",
+ "bug_480.py",
+ "bug_512.py",
+ "bug_525.py",
+ "bug_546.py",
+ "bug_547.py",
+ "bug_549.py",
+ "bug_569.py",
+ "bug_575.py",
+ "bug_576.py",
+ "bug_585.py",
+ "bug_589.py",
+ "bug_635.py",
+ "bug_640.py",
+ "bug_653.py",
+ "bug_662.py",
+ "bug_667.py",
+ "bug_668.py",
+ "bug_674.py",
+ "bug_675.py",
+ "bug_688.py",
+ "bug_693.py",
+ "bug_696.py",
+ "bug_711.py",
+ "bug_722.py",
+ "bug_728.py",
+ "bug_736.py",
+ "bug_750.py",
+ "bug_778.py",
+ "bug_793.py",
+ "bug_811.py",
+ "bug_834.py",
+ "bug_836.py",
+ "bug_844.py",
+ "bug_854.py",
+ "bug_860.py",
+ "bug_862.py",
+ "bug_871.py",
+ "bug_879.py",
+ "bug_919.py",
+ "bug_921.py",
+ "bug_941.py",
+ "bug_964.py",
+ "bug_967.py",
+ "bug_972.py",
+ "bug_979.py",
+ "bug_988.py",
+ "bug_998.py",
+ "customproxywidget_test.py",
+ "grandparent_method_test.py",
+ "hashabletype_test.py",
+ "import_test.py",
+ "keep_reference_test.py",
+ "missing_symbols_test.py",
+ "paint_event_test.py",
+ "parent_method_test.py",
+ "private_mangle_test.py",
+ "python_properties_test.py",
+ "qabstracttextdocumentlayout_test.py",
+ "qaccessible_test.py",
+ "qaction_test.py",
+ "qapp_issue_585.py",
+ "qapp_test.py",
+ "qapplication_exit_segfault_test.py",
+ "qapplication_test.py",
+ "qcolormap_test.py",
+ "qdynamic_signal.py",
+ "qfontdialog_test.py",
+ "qformlayout_test.py",
+ "qgraphicsitem_isblocked_test.py",
+ "qgraphicsitem_test.py",
+ "qgraphicsobjectreimpl_test.py",
+ "qgraphicsproxywidget_test.py",
+ "qgraphicsscene_test.py",
+ "qinputdialog_get_test.py",
+ "qkeysequenceedit_test.py",
+ "qlabel_test.py",
+ "qlayout_ref_test.py",
+ "qlayout_test.py",
+ "qlcdnumber_test.py",
+ "qlistwidget_test.py",
+ "qlistwidgetitem_test.py",
+ "qmainwindow_test.py",
+ "qmenu_test.py",
+ "qmenuadd_test.py",
+ "qobject_mi_test.py",
+ "qpicture_test.py",
+ "qpushbutton_test.py",
+ "qsplitter_test.py",
+ "qstyle_test.py",
+ "qstyleoption_test.py",
+ "qtableview_test.py",
+ "qtabwidget_test.py",
+ "qtabwidgetclear_test.py",
+ "qtextedit_signal_test.py",
+ "qtextedit_test.py",
+ "qtoolbar_test.py",
+ "qtoolbox_test.py",
+ "qtreeview_test.py",
+ "qtreewidget_test.py",
+ "qtreewidgetitem_test.py",
+ "qvariant_test.py",
+ "qwidget_setlayout_test.py",
+ "qwidget_test.py",
+ "reference_count_test.py",
+ "signature_test.py",
+ "standardpixmap_test.py",
+ "test_module_template.py",
+ "virtual_protected_inheritance_test.py",
+ "virtual_pure_override_test.py",
+ "wrong_return_test.py"]
+}
diff --git a/sources/pyside6/tests/QtWidgets/action_clear.py b/sources/pyside6/tests/QtWidgets/action_clear.py
new file mode 100644
index 000000000..5563a4899
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/action_clear.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 gc
+import os
+import sys
+import unittest
+import weakref
+
+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.QtWidgets import QMenu, QWidget, QMenuBar, QToolBar
+from helper.usesqapplication import UsesQApplication
+
+
+class TestQActionLifeCycle(UsesQApplication):
+ def actionDestroyed(self, act):
+ self._actionDestroyed = True
+
+ def testMenu(self):
+ self._actionDestroyed = False
+ w = QWidget()
+ menu = QMenu(w)
+ act = menu.addAction("MENU")
+ _ref = weakref.ref(act, self.actionDestroyed)
+ act = None
+ self.assertFalse(self._actionDestroyed)
+ menu.clear()
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertTrue(self._actionDestroyed)
+
+ def testMenuBar(self):
+ self._actionDestroyed = False
+ w = QWidget()
+ menuBar = QMenuBar(w)
+ act = menuBar.addAction("MENU")
+ _ref = weakref.ref(act, self.actionDestroyed)
+ act = None
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertFalse(self._actionDestroyed)
+ menuBar.clear()
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertTrue(self._actionDestroyed)
+
+ def testToolBar(self):
+ self._actionDestroyed = False
+ w = QWidget()
+ toolBar = QToolBar(w)
+ act = toolBar.addAction("MENU")
+ _ref = weakref.ref(act, self.actionDestroyed)
+ act = None
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertFalse(self._actionDestroyed)
+ toolBar.clear()
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertTrue(self._actionDestroyed)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/add_action_test.py b/sources/pyside6/tests/QtWidgets/add_action_test.py
new file mode 100644
index 000000000..3ca1660a9
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/add_action_test.py
@@ -0,0 +1,60 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Tests for QMenuBar.addAction(identifier, callback) calls'''
+
+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 Qt, SLOT
+from PySide6.QtGui import QAction
+from PySide6.QtWidgets import QMenuBar, QPushButton
+
+from helper.usesqapplication import UsesQApplication
+
+
+class AddActionTest(UsesQApplication):
+ '''QMenuBar addAction'''
+
+ def tearDown(self):
+ try:
+ del self.called
+ except AttributeError:
+ pass
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(AddActionTest, self).tearDown()
+
+ def _callback(self):
+ self.called = True
+
+ def testBasic(self):
+ '''QMenuBar.addAction(id, callback)'''
+ menubar = QMenuBar()
+ action = menubar.addAction("Accounts", self._callback)
+ action.activate(QAction.Trigger)
+ action.setShortcut(Qt.Key_A)
+ self.assertTrue(self.called)
+
+ def testWithCppSlot(self):
+ '''QMenuBar.addAction(id, object, slot)'''
+ menubar = QMenuBar()
+ widget = QPushButton()
+ widget.setCheckable(True)
+ widget.setChecked(False)
+ action = menubar.addAction("Accounts", widget, SLOT("toggle()"))
+ action.setShortcut(Qt.Key_A)
+ action.activate(QAction.Trigger)
+ self.assertTrue(widget.isChecked())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/api2_test.py b/sources/pyside6/tests/QtWidgets/api2_test.py
new file mode 100644
index 000000000..e38672016
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/api2_test.py
@@ -0,0 +1,73 @@
+# 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 cases for PySide API2 support'''
+
+
+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.QtGui import QIntValidator, QValidator
+from PySide6.QtWidgets import QWidget, QSpinBox, QApplication
+
+from helper.usesqapplication import UsesQApplication
+
+
+class WidgetValidatorQInt(QWidget, QIntValidator):
+ def __init__(self, parent=None):
+ QWidget.__init__(self, parent)
+ QIntValidator.__init__(self, parent)
+
+
+class WidgetValidatorQSpinBox(QSpinBox):
+ def __init__(self, parent=None):
+ QSpinBox.__init__(self, parent)
+
+ def fixup(self, text):
+ print("It was called!")
+
+
+class DoubleQObjectInheritanceTest(UsesQApplication):
+
+ def testDouble(self):
+ '''Double inheritance from QObject classes'''
+
+ obj = WidgetValidatorQInt()
+
+ # QIntValidator methods
+ state, string, number = obj.validate('Test', 0)
+ self.assertEqual(state, QValidator.Invalid)
+ state, string, number = obj.validate('33', 0)
+ self.assertEqual(state, QValidator.Acceptable)
+
+ def testQSpinBox(self):
+ obj = WidgetValidatorQSpinBox()
+
+ obj.setRange(1, 10)
+ obj.setValue(0)
+ self.assertEqual(obj.value(), 1)
+
+
+class QClipboardTest(UsesQApplication):
+
+ def testQClipboard(self):
+ # skip this test on macOS because the clipboard is not available during the ssh session
+ # this cause problems in the buildbot
+ if sys.platform == 'darwin':
+ return
+ clip = QApplication.clipboard()
+ clip.setText("Testing this thing!")
+
+ text, subtype = clip.text("")
+ self.assertEqual(subtype, "plain")
+ self.assertEqual(text, "Testing this thing!")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/application_test.py b/sources/pyside6/tests/QtWidgets/application_test.py
new file mode 100644
index 000000000..1b2477fd7
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/application_test.py
@@ -0,0 +1,42 @@
+#!/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 TestObject
+from PySide6.QtWidgets import QApplication
+from PySide6 import __all__ as all
+
+
+class QApplicationInstance(unittest.TestCase):
+
+ def appDestroyed(self):
+ self.assertTrue(False)
+
+ def testInstanceObject(self):
+ self.assertEqual(type(qApp), type(None))
+ TestObject.createApp()
+ app1 = QApplication.instance()
+ app2 = QApplication.instance()
+ app1.setObjectName("MyApp")
+ self.assertEqual(app1, app2)
+ self.assertEqual(app2.objectName(), app1.objectName())
+ # We no longer support qApp when embedding
+ # if len(all) > 3:
+ # # an import triggers qApp initialization
+ # __import__("PySide6." + all[-1])
+ # self.assertEqual(app1, qApp)
+ app1.destroyed.connect(self.appDestroyed)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_1002.py b/sources/pyside6/tests/QtWidgets/bug_1002.py
new file mode 100644
index 000000000..98ae66c47
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_1002.py
@@ -0,0 +1,35 @@
+# 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.QtWidgets import QWidget, QPushButton
+
+from helper.usesqapplication import UsesQApplication
+
+
+class TestBug1002 (UsesQApplication):
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testReturnWindow(self):
+ widget = QWidget()
+ button = QPushButton(widget)
+ self.assertEqual(sys.getrefcount(widget), 2)
+ window = button.window()
+ self.assertEqual(sys.getrefcount(widget), 3)
+ self.assertEqual(sys.getrefcount(window), 3)
+
+ del widget
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_1006.py b/sources/pyside6/tests/QtWidgets/bug_1006.py
new file mode 100644
index 000000000..74bf5e2da
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_1006.py
@@ -0,0 +1,99 @@
+# 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
+import weakref
+
+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 Qt
+from PySide6.QtWidgets import QDialog, QLabel, QGridLayout, QHBoxLayout, QWidget
+
+from helper.timedqapplication import TimedQApplication
+
+
+class LabelWindow(QDialog):
+ def __init__(self, parent):
+ super().__init__(parent)
+
+ self.test_layout = QGridLayout()
+ label = QLabel("Label")
+ self.test_layout.addWidget(label, 0, 0)
+ self.setLayout(self.test_layout)
+ self._destroyCalled = False
+
+ def replace(self, unit):
+ old_item = self.test_layout.itemAtPosition(0, 0)
+ old_label = old_item.widget()
+ ref = weakref.ref(old_item, self._destroyed)
+
+ self.test_layout.removeWidget(old_label)
+ unit.assertRaises(RuntimeError, old_item.widget)
+ del old_item
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ label = QLabel("Label New")
+ old_label.deleteLater()
+ label.setAlignment(Qt.AlignCenter)
+ self.test_layout.addWidget(label, 0, 0)
+
+ def _destroyed(self, obj):
+ self._destroyCalled = True
+
+
+class TestBug1006 (TimedQApplication):
+
+ def testLayoutItemLifeTime(self):
+ window = LabelWindow(None)
+ window.replace(self)
+ self.assertTrue(window._destroyCalled)
+ self.app.exec()
+
+ def testParentLayout(self):
+ def createLayout():
+ label = QLabel()
+ layout = QHBoxLayout()
+ layout.addWidget(label)
+
+ widget = QWidget()
+ widget.setLayout(layout)
+ return (layout, widget)
+ (layout, widget) = createLayout()
+ item = layout.itemAt(0)
+ self.assertTrue(isinstance(item.widget(), QWidget))
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRemoveOrphanWidget(self):
+ widget = QLabel()
+ layout = QHBoxLayout()
+ layout.addWidget(widget)
+ self.assertEqual(sys.getrefcount(widget), 3)
+
+ layout.removeWidget(widget)
+ widget.setObjectName("MyWidget")
+ self.assertEqual(sys.getrefcount(widget), 2)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRemoveChildWidget(self):
+ parent = QLabel()
+ widget = QLabel(parent)
+ self.assertEqual(sys.getrefcount(widget), 3)
+
+ layout = QHBoxLayout()
+ layout.addWidget(widget)
+ self.assertEqual(sys.getrefcount(widget), 3)
+
+ layout.removeWidget(widget)
+ widget.setObjectName("MyWidget")
+ self.assertEqual(sys.getrefcount(widget), 3)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_1048.py b/sources/pyside6/tests/QtWidgets/bug_1048.py
new file mode 100644
index 000000000..9d83e2f30
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_1048.py
@@ -0,0 +1,21 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtWidgets import QApplication, QGridLayout, QWidget
+
+
+a = QApplication([])
+
+w = QWidget()
+l = QGridLayout(w)
+
+l.itemAtPosition(0, 0)
diff --git a/sources/pyside6/tests/QtWidgets/bug_1077.py b/sources/pyside6/tests/QtWidgets/bug_1077.py
new file mode 100644
index 000000000..c9559609f
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_1077.py
@@ -0,0 +1,32 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+''' unit test for BUG #1077 '''
+
+import os
+import sys
+import time
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtGui import QSyntaxHighlighter
+from PySide6.QtWidgets import QApplication, QTextEdit, QWidget
+
+
+class Highlighter(QSyntaxHighlighter):
+ def __init__(self, parent, mode):
+ super().__init__(parent)
+ self.tstamp = time.time()
+
+
+if __name__ == "__main__":
+ app = QApplication([])
+ python = QTextEdit()
+ python.setWindowTitle("python")
+ hl = Highlighter(python.document(), "python")
+ python.show()
+ text = hl.document()
diff --git a/sources/pyside6/tests/QtWidgets/bug_172.py b/sources/pyside6/tests/QtWidgets/bug_172.py
new file mode 100644
index 000000000..2637d6d61
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_172.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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtWidgets import QApplication, QHBoxLayout, QVBoxLayout, QWidget
+
+
+if __name__ == '__main__':
+ app = QApplication([])
+
+ wdg = QWidget()
+
+ hbox = QHBoxLayout()
+
+ vbox = QVBoxLayout()
+ vbox.addLayout(hbox)
+
+ wdg.setLayout(vbox)
diff --git a/sources/pyside6/tests/QtWidgets/bug_243.py b/sources/pyside6/tests/QtWidgets/bug_243.py
new file mode 100644
index 000000000..af189837f
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_243.py
@@ -0,0 +1,28 @@
+# 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 bug 243: http://bugs.openbossa.org/show_bug.cgi?id=243'''
+
+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.QtWidgets import QApplication, QMainWindow, QLayout
+
+
+class QAppPresence(unittest.TestCase):
+
+ def testBug(self):
+ app = QApplication(sys.argv)
+ window = QMainWindow()
+ l = window.layout()
+ self.assertTrue(isinstance(l, QLayout))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_307.py b/sources/pyside6/tests/QtWidgets/bug_307.py
new file mode 100644
index 000000000..673d5183d
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_307.py
@@ -0,0 +1,37 @@
+# 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 colorsys
+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 SIGNAL
+from PySide6.QtWidgets import QPushButton, QApplication
+
+
+class Test (QApplication):
+ def __init__(self, argv):
+ super().__init__(argv)
+ self._called = False
+
+ def called(self):
+ self._called = True
+
+
+class QApplicationSignalsTest(unittest.TestCase):
+ def testQuit(self):
+ app = Test([])
+ button = QPushButton("BUTTON")
+ app.connect(button, SIGNAL("clicked()"), app.called)
+ button.click()
+ self.assertTrue(app._called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_338.py b/sources/pyside6/tests/QtWidgets/bug_338.py
new file mode 100644
index 000000000..695b4238a
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_338.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
+
+''' Test bug 338: http://bugs.openbossa.org/show_bug.cgi?id=338'''
+
+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.QtWidgets import QApplication, QGraphicsPolygonItem, QGraphicsScene
+
+
+class DiagramItem(QGraphicsPolygonItem):
+ def __init__(self, parent=None, scene=None):
+ super().__init__(parent, scene)
+
+ def itemChange(self, change, value):
+ return value
+
+
+class BugTest(unittest.TestCase):
+ def test(self):
+ app = QApplication(sys.argv)
+ scene = QGraphicsScene()
+ item = DiagramItem()
+ item2 = DiagramItem()
+ # this cause segfault
+ scene.addItem(item)
+ scene.addItem(item2)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_389.py b/sources/pyside6/tests/QtWidgets/bug_389.py
new file mode 100644
index 000000000..024908e85
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_389.py
@@ -0,0 +1,28 @@
+# 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 bug 389: http://bugs.openbossa.org/show_bug.cgi?id=389'''
+
+import sys
+import os
+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.QtGui import QIcon
+from PySide6.QtWidgets import QStyle, QWidget
+
+
+class BugTest(UsesQApplication):
+ def testCase(self):
+ s = QWidget().style()
+ i = s.standardIcon(QStyle.SP_TitleBarMinButton)
+ self.assertEqual(type(i), QIcon)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_400.py b/sources/pyside6/tests/QtWidgets/bug_400.py
new file mode 100644
index 000000000..79dfa49fc
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_400.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
+
+''' Test bug 400: http://bugs.openbossa.org/show_bug.cgi?id=400'''
+
+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.QtWidgets import QTreeWidgetItemIterator, QTreeWidgetItem, QTreeWidget
+
+
+class BugTest(UsesQApplication):
+ def testCase(self):
+ treeWidget = QTreeWidget()
+ treeWidget.setColumnCount(1)
+ items = []
+ for i in range(10):
+ items.append(QTreeWidgetItem(None, [f"item: {i}"]))
+
+ treeWidget.insertTopLevelItems(0, items)
+ _iter = QTreeWidgetItemIterator(treeWidget)
+ index = 0
+ while (_iter.value()):
+ item = _iter.value()
+ self.assertTrue(item is items[index])
+ index += 1
+ _iter += 1
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_429.py b/sources/pyside6/tests/QtWidgets/bug_429.py
new file mode 100644
index 000000000..e95c113f3
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_429.py
@@ -0,0 +1,22 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QTimer
+from PySide6.QtWidgets import QApplication, QGraphicsScene, QLabel
+
+
+app = QApplication(sys.argv)
+scene = QGraphicsScene()
+label = QLabel("hello world")
+label.show()
+QTimer.singleShot(0, label.close)
+exit(app.exec())
diff --git a/sources/pyside6/tests/QtWidgets/bug_430.py b/sources/pyside6/tests/QtWidgets/bug_430.py
new file mode 100644
index 000000000..6ef9ec7f4
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_430.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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QAbstractListModel, QModelIndex, QTimer
+from PySide6.QtWidgets import QApplication, QListView
+
+
+class ListModel(QAbstractListModel):
+ def rowCount(self, parent=QModelIndex()):
+ return 0
+
+
+if __name__ == '__main__':
+ app = QApplication([])
+ model = ListModel()
+ v = QListView()
+ v.setModel(model)
+ v.show()
+ QTimer.singleShot(0, v.close)
+ app.exec()
diff --git a/sources/pyside6/tests/QtWidgets/bug_433.py b/sources/pyside6/tests/QtWidgets/bug_433.py
new file mode 100644
index 000000000..c7fbe4b3e
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_433.py
@@ -0,0 +1,28 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QTimer
+from PySide6.QtWidgets import QApplication, QGraphicsScene, QGraphicsView
+
+
+class Test(QGraphicsView):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.s = QGraphicsScene()
+ self.setScene(self.s)
+
+
+a = QApplication(sys.argv)
+t = Test()
+t.show()
+QTimer.singleShot(0, t.close)
+sys.exit(a.exec_())
diff --git a/sources/pyside6/tests/QtWidgets/bug_467.py b/sources/pyside6/tests/QtWidgets/bug_467.py
new file mode 100644
index 000000000..af383e811
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_467.py
@@ -0,0 +1,32 @@
+# 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 bug 367: http://bugs.openbossa.org/show_bug.cgi?id=467'''
+
+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.QtWidgets import QMainWindow, QApplication
+
+
+class MyWidget(QMainWindow):
+ def __init__(self, parent=None):
+ QMainWindow.__init__(self, parent)
+
+
+class BugTest(UsesQApplication):
+ def testCase(self):
+ w = MyWidget()
+ widgets = QApplication.allWidgets()
+ self.assertTrue(w in widgets)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_480.py b/sources/pyside6/tests/QtWidgets/bug_480.py
new file mode 100644
index 000000000..2fc955561
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_480.py
@@ -0,0 +1,39 @@
+# 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.QtWidgets import (QApplication, QGridLayout, QLabel, QVBoxLayout,
+ QWidget)
+
+
+class BuggyWidget(QWidget):
+ def setup(self):
+ self.verticalLayout = QVBoxLayout(self)
+ self.gridLayout = QGridLayout()
+ self.lbl = QLabel(self)
+ self.gridLayout.addWidget(self.lbl, 0, 1, 1, 1)
+
+ # this cause a segfault during the ownership transfer
+ self.verticalLayout.addLayout(self.gridLayout)
+
+
+class LayoutTransferOwnerShip(unittest.TestCase):
+ def testBug(self):
+ app = QApplication([])
+ w = BuggyWidget()
+ w.setup()
+ w.show()
+ self.assertTrue(True)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_512.py b/sources/pyside6/tests/QtWidgets/bug_512.py
new file mode 100644
index 000000000..dab367727
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_512.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
+
+''' Test bug 512: http://bugs.openbossa.org/show_bug.cgi?id=512'''
+
+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.QtWidgets import QGridLayout, QLabel, QWidget
+
+
+class BugTest(UsesQApplication):
+ def testCase(self):
+ w = QWidget(None)
+ lbl = QLabel("Hello", w)
+ g = QGridLayout()
+ g.addWidget(lbl, 0, 0)
+ w.setLayout(g)
+ w.show()
+
+ t = g.getItemPosition(0)
+ self.assertEqual(type(t), tuple)
+ self.assertEqual(t, (0, 0, 1, 1))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_525.py b/sources/pyside6/tests/QtWidgets/bug_525.py
new file mode 100644
index 000000000..3c49cd377
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_525.py
@@ -0,0 +1,35 @@
+# 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.QtWidgets import QApplication
+from PySide6.QtWidgets import QMenu
+
+
+class M2(QMenu):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setTitle(self.tr("M2"))
+
+
+class TestMenuDerivedClass(unittest.TestCase):
+ def aboutToShowHandler(self):
+ pass
+
+ def testConnectSignal(self):
+ app = QApplication([])
+ m2 = M2()
+ # Test if the aboutToShow signal was translated to correct type
+ m2.aboutToShow.connect(self.aboutToShowHandler)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_546.py b/sources/pyside6/tests/QtWidgets/bug_546.py
new file mode 100644
index 000000000..fcec2f6d7
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_546.py
@@ -0,0 +1,27 @@
+# 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.QtWidgets import QApplication, QCompleter, QPlainTextEdit
+
+
+class TestBug546(unittest.TestCase):
+
+ """Test to check a crash at exit"""
+ def testIt(self):
+ app = QApplication([])
+ textEdit = QPlainTextEdit()
+ completer = QCompleter(("foo", "bar"), textEdit)
+ completer.setWidget(textEdit)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_547.py b/sources/pyside6/tests/QtWidgets/bug_547.py
new file mode 100644
index 000000000..dcbe20ee8
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_547.py
@@ -0,0 +1,73 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+""" Unittest for bug #547 """
+""" http://bugs.openbossa.org/show_bug.cgi?id=547 """
+
+import sys
+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.QtWidgets import QApplication, QTreeWidget, QTreeWidgetItem
+
+
+class MyMainWindow(unittest.TestCase):
+ app = QApplication(sys.argv)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testCase1(self):
+ self._tree = QTreeWidget()
+ self._tree.setColumnCount(2)
+ self._i1 = None
+ self._i11 = None
+
+ self._updateTree()
+ self.assertEqual(sys.getrefcount(self._i1), 3)
+ self.assertEqual(sys.getrefcount(self._i11), 3)
+
+ self._i11.parent().setExpanded(True)
+ self._i11.setExpanded(True)
+
+ self._updateTree()
+ self.assertEqual(sys.getrefcount(self._i1), 3)
+ self.assertEqual(sys.getrefcount(self._i11), 3)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testCase2(self):
+ self._tree = QTreeWidget()
+ self._tree.setColumnCount(2)
+ self._i1 = None
+ self._i11 = None
+
+ self._updateTree()
+ self.assertEqual(sys.getrefcount(self._i1), 3)
+ self.assertEqual(sys.getrefcount(self._i11), 3)
+
+ self._i11.parent().setExpanded(True)
+ self._i11.setExpanded(True)
+
+ self.assertEqual(sys.getrefcount(self._i1), 3)
+ self.assertEqual(sys.getrefcount(self._i11), 3)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def _updateTree(self):
+ self._tree.clear()
+ if self._i1 and self._i11:
+ self.assertEqual(sys.getrefcount(self._i1), 2)
+ self.assertEqual(sys.getrefcount(self._i11), 2)
+
+ self._i1 = QTreeWidgetItem(self._tree, ['1', ])
+ self.assertEqual(sys.getrefcount(self._i1), 3)
+ self._i11 = QTreeWidgetItem(self._i1, ['11', ])
+ self.assertEqual(sys.getrefcount(self._i11), 3)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_549.py b/sources/pyside6/tests/QtWidgets/bug_549.py
new file mode 100644
index 000000000..8efa6e679
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_549.py
@@ -0,0 +1,28 @@
+# 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.QtWidgets import QApplication, QGraphicsWidget
+
+
+class TestBug549(unittest.TestCase):
+ def testBug(self):
+ app = QApplication([])
+ w = QGraphicsWidget()
+ w.setContentsMargins(1, 2, 3, 4)
+ self.assertEqual(w.getContentsMargins(), (1, 2, 3, 4))
+ w.setWindowFrameMargins(5, 6, 7, 8)
+ self.assertEqual(w.getWindowFrameMargins(), (5, 6, 7, 8))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_569.py b/sources/pyside6/tests/QtWidgets/bug_569.py
new file mode 100644
index 000000000..0f95aed02
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_569.py
@@ -0,0 +1,30 @@
+# 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.QtWidgets import QTableWidgetItem, QListWidgetItem, QTreeWidgetItem
+
+
+class TestBug569(unittest.TestCase):
+
+ def testIt(self):
+ types = (QTableWidgetItem, QListWidgetItem, QTreeWidgetItem)
+ for t in types:
+ a = t()
+ a.__lt__ = lambda other: True
+ b = t()
+ b.__lt__ = lambda other: False
+ self.assertTrue(a < b)
+ self.assertFalse(b < a)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_575.py b/sources/pyside6/tests/QtWidgets/bug_575.py
new file mode 100644
index 000000000..f9a927817
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_575.py
@@ -0,0 +1,33 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+""" Unittest for bug #575 """
+""" http://bugs.openbossa.org/show_bug.cgi?id=575 """
+
+import sys
+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.QtWidgets import QApplication, QPlainTextEdit, QTextEdit
+
+
+class Bug575(unittest.TestCase):
+ def testPropertyValues(self):
+ app = QApplication(sys.argv)
+ textEdit = QPlainTextEdit()
+ textEdit.insertPlainText("PySide INdT")
+ selection = QTextEdit.ExtraSelection()
+ selection.cursor = textEdit.textCursor()
+ selection.cursor.setPosition(2)
+ self.assertEqual(selection.cursor.position(), 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_576.py b/sources/pyside6/tests/QtWidgets/bug_576.py
new file mode 100644
index 000000000..4a17e7aa8
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_576.py
@@ -0,0 +1,49 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+""" Unittest for bug #576 """
+""" http://bugs.openbossa.org/show_bug.cgi?id=576 """
+
+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
+from PySide6.QtWidgets import QApplication, QPushButton, QWidget
+
+
+class Bug576(unittest.TestCase):
+ def onButtonDestroyed(self, button):
+ self._destroyed = True
+ self.assertTrue(isinstance(button, QPushButton))
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testWidgetParent(self):
+ self._destroyed = False
+ app = QApplication(sys.argv)
+ w = QWidget()
+
+ b = QPushButton("test")
+ b.destroyed[QObject].connect(self.onButtonDestroyed)
+ self.assertEqual(sys.getrefcount(b), 2)
+ b.setParent(w)
+ self.assertEqual(sys.getrefcount(b), 3)
+ b.parent()
+ self.assertEqual(sys.getrefcount(b), 3)
+ b.setParent(None)
+ self.assertEqual(sys.getrefcount(b), 2)
+ del b
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertTrue(self._destroyed)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_585.py b/sources/pyside6/tests/QtWidgets/bug_585.py
new file mode 100644
index 000000000..e26ca9ce0
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_585.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
+
+'''Test bug 585: http://bugs.openbossa.org/show_bug.cgi?id=585'''
+
+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.QtWidgets import QApplication, QTreeWidget, QTreeWidgetItem
+
+
+class Bug585(unittest.TestCase):
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testCase(self):
+ app = QApplication([])
+ self._tree = QTreeWidget()
+ self._tree.setColumnCount(2)
+ i1 = QTreeWidgetItem(self._tree, ['1', ])
+ i2 = QTreeWidgetItem(self._tree, ['2', ])
+ refCount = sys.getrefcount(i1)
+
+ # this function return None
+ # because the topLevelItem does not has a parent item
+ # but still have a TreeWidget as a parent
+ self._tree.topLevelItem(0).parent()
+
+ self.assertEqual(refCount, sys.getrefcount(i1))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_589.py b/sources/pyside6/tests/QtWidgets/bug_589.py
new file mode 100644
index 000000000..a19f544a5
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_589.py
@@ -0,0 +1,32 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+# trimmed down diagramscene.py to demonstrate crash in sizeHint()
+
+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.QtWidgets import QApplication, QGraphicsProxyWidget
+
+
+class CustomWidget(QGraphicsProxyWidget):
+ def itemChange(self, eventType, value):
+ QGraphicsProxyWidget.itemChange(self, eventType, value)
+
+
+class Bug589(unittest.TestCase):
+ def testCase(self):
+ widget = QGraphicsProxyWidget()
+ custom = CustomWidget()
+ custom.setParentItem(widget)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_635.py b/sources/pyside6/tests/QtWidgets/bug_635.py
new file mode 100644
index 000000000..66a8c58c6
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_635.py
@@ -0,0 +1,41 @@
+# 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 bug 635: http://bugs.openbossa.org/show_bug.cgi?id=635'''
+
+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.QtGui import QIcon
+from PySide6.QtWidgets import QApplication, QToolBar
+
+
+class testQToolBar(unittest.TestCase):
+ def callback(self):
+ self._called = True
+
+ def testAddAction(self):
+ bar = QToolBar()
+ self._called = False
+ a = bar.addAction("act1", self.callback)
+ a.trigger()
+ self.assertTrue(self._called)
+
+ def testAddActionWithIcon(self):
+ bar = QToolBar()
+ self._called = False
+ icon = QIcon()
+ a = bar.addAction(icon, "act1", self.callback)
+ a.trigger()
+ self.assertTrue(self._called)
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_640.py b/sources/pyside6/tests/QtWidgets/bug_640.py
new file mode 100644
index 000000000..b2620b541
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_640.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)
+
+from PySide6.QtWidgets import QStyleOptionGraphicsItem
+
+
+class Bug640(unittest.TestCase):
+ def testIt(self):
+ option = QStyleOptionGraphicsItem()
+ a = option.state # crash!?
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_653.py b/sources/pyside6/tests/QtWidgets/bug_653.py
new file mode 100644
index 000000000..1cf8390df
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_653.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)
+
+from PySide6.QtWidgets import QApplication, QWizard, QWizardPage
+
+
+class TestBug653(unittest.TestCase):
+ """Crash after calling QWizardPage.wizard()"""
+ def testIt(self):
+ app = QApplication([])
+
+ wizard = QWizard()
+ page = QWizardPage()
+ wizard.addPage(page)
+ page.wizard() # crash here if the bug still exists due to a circular dependency
+ wizard.show()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_662.py b/sources/pyside6/tests/QtWidgets/bug_662.py
new file mode 100644
index 000000000..e3a3130d0
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_662.py
@@ -0,0 +1,42 @@
+# 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 bug 662: http://bugs.openbossa.org/show_bug.cgi?id=662'''
+
+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.QtGui import QTextCharFormat
+from PySide6.QtWidgets import QTextEdit, QApplication
+import sys
+
+
+class testQTextBlock(unittest.TestCase):
+
+ def testIterator(self):
+ edit = QTextEdit()
+ cursor = edit.textCursor()
+ fmt = QTextCharFormat()
+ frags = []
+ for i in range(10):
+ fmt.setFontPointSize(i + 10)
+ frags.append(f"block{i}")
+ cursor.insertText(frags[i], fmt)
+
+ doc = edit.document()
+ block = doc.begin()
+
+ index = 0
+ for i in block:
+ self.assertEqual(i.fragment().text(), frags[index])
+ index += 1
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_667.py b/sources/pyside6/tests/QtWidgets/bug_667.py
new file mode 100644
index 000000000..be6700d83
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_667.py
@@ -0,0 +1,37 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QTimer, QPointF
+from PySide6.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsEllipseItem
+
+
+class Ball(QGraphicsEllipseItem):
+ def __init__(self, d, parent=None):
+ super().__init__(0, 0, d, d, parent)
+ self.vel = QPointF(0, 0) # commenting this out prevents the crash
+
+
+class Foo(QGraphicsView):
+ def __init__(self):
+ super().__init__(None)
+ self.scene = QGraphicsScene(self.rect())
+ self.setScene(self.scene)
+ self.scene.addItem(Ball(10))
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ w = Foo()
+ w.show()
+ w.raise_()
+ QTimer.singleShot(0, w.close)
+ sys.exit(app.exec())
diff --git a/sources/pyside6/tests/QtWidgets/bug_668.py b/sources/pyside6/tests/QtWidgets/bug_668.py
new file mode 100644
index 000000000..0c22436b3
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_668.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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QDir, QModelIndex, QTimer
+from PySide6.QtWidgets import QApplication, QFileSystemModel, QMainWindow, QTreeView
+
+
+class A(QMainWindow):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ a = QFileSystemModel(self)
+ a.setRootPath(QDir.homePath())
+
+ v = QTreeView(self)
+ v.setModel(a)
+ self.setCentralWidget(v)
+ # Test index() method (see PYSIDE-570, PYSIDE-331)
+ index = a.index(0, 0, QModelIndex())
+
+
+app = QApplication([])
+m = A()
+m.show()
+QTimer.singleShot(0, m.close)
+app.exec()
diff --git a/sources/pyside6/tests/QtWidgets/bug_674.py b/sources/pyside6/tests/QtWidgets/bug_674.py
new file mode 100644
index 000000000..901b29275
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_674.py
@@ -0,0 +1,35 @@
+# 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.QtWidgets import QApplication, QGraphicsScene
+
+
+class TestBug679(unittest.TestCase):
+ '''QGraphicsScene::clear() is missing'''
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testIt(self):
+ app = QApplication([])
+
+ scene = QGraphicsScene()
+ hello = scene.addText("Hello")
+ scene.addText("World")
+
+ self.assertEqual(sys.getrefcount(hello), 3)
+ scene.clear()
+ self.assertEqual(sys.getrefcount(hello), 2)
+ self.assertEqual(len(scene.items()), 0)
+ self.assertRaises(RuntimeError, hello.isVisible) # the C++ object was deleted
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_675.py b/sources/pyside6/tests/QtWidgets/bug_675.py
new file mode 100644
index 000000000..221df88b0
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_675.py
@@ -0,0 +1,28 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtWidgets import (QApplication, QGraphicsLinearLayout,
+ QGraphicsScene, QGraphicsView, QTextEdit)
+
+
+app = QApplication([])
+
+scene = QGraphicsScene()
+
+# don't segfault due to lack of keepReferenceCall
+textEdit = scene.addWidget(QTextEdit())
+
+layout = QGraphicsLinearLayout()
+layout.addItem(textEdit)
+
+view = QGraphicsView(scene)
+view.show()
diff --git a/sources/pyside6/tests/QtWidgets/bug_688.py b/sources/pyside6/tests/QtWidgets/bug_688.py
new file mode 100644
index 000000000..3180d08bf
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_688.py
@@ -0,0 +1,98 @@
+# 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 bug 688: http://bugs.openbossa.org/show_bug.cgi?id=688'''
+
+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.QtGui import QTextFrame, QTextCursor, QTextCharFormat, QFont, QTextFrameFormat
+from PySide6.QtWidgets import QTextEdit
+
+
+class BugTest(UsesQApplication):
+ def testCase(self):
+ editor = QTextEdit()
+ cursor = QTextCursor(editor.textCursor())
+ cursor.movePosition(QTextCursor.Start)
+
+ mainFrame = cursor.currentFrame()
+
+ plainCharFormat = QTextCharFormat()
+ boldCharFormat = QTextCharFormat()
+ boldCharFormat.setFontWeight(QFont.Bold)
+ cursor.insertText("""
+ Text documents are represented by the
+ QTextDocument class, rather than by QString objects.
+ Each QTextDocument object contains information about
+ the document's internal representation, its structure,
+ and keeps track of modifications to provide undo/redo
+ facilities. This approach allows features such as the
+ layout management to be delegated to specialized
+ classes, but also provides a focus for the framework.""",
+ plainCharFormat)
+
+ frameFormat = QTextFrameFormat()
+ frameFormat.setMargin(32)
+ frameFormat.setPadding(8)
+ frameFormat.setBorder(4)
+ cursor.insertFrame(frameFormat)
+
+ cursor.insertText("""
+ Documents are either converted from external sources
+ or created from scratch using Qt. The creation process
+ can done by an editor widget, such as QTextEdit, or by
+ explicit calls to the Scribe API.""",
+ boldCharFormat)
+
+ cursor = mainFrame.lastCursorPosition()
+ cursor.insertText("""
+ There are two complementary ways to visualize the
+ contents of a document: as a linear buffer that is
+ used by editors to modify the contents, and as an
+ object hierarchy containing structural information
+ that is useful to layout engines. In the hierarchical
+ model, the objects generally correspond to visual
+ elements such as frames, tables, and lists. At a lower
+ level, these elements describe properties such as the
+ style of text used and its alignment. The linear
+ representation of the document is used for editing and
+ manipulation of the document's contents.""",
+ plainCharFormat)
+
+ frame = cursor.currentFrame()
+
+ items = []
+
+ # test iterator
+ for i in frame:
+ items.append(i)
+
+ # test __iadd__
+ b = frame.begin()
+ i = 0
+ while not b.atEnd():
+ self.assertEqual(b, items[i])
+ self.assertTrue(b.parentFrame(), items[i].parentFrame())
+ b.__iadd__(1)
+ i += 1
+
+ # test __isub__
+ b = frame.end()
+ i = 0
+ while i > 0:
+ self.assertEqual(b, items[i])
+ self.assertTrue(b.parentFrame(), items[i].parentFrame())
+ b.__isub__(1)
+ i -= 1
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_693.py b/sources/pyside6/tests/QtWidgets/bug_693.py
new file mode 100644
index 000000000..95981e272
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_693.py
@@ -0,0 +1,42 @@
+# 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 QAbstractListModel, QLine
+from PySide6.QtWidgets import QApplication, QListView
+
+
+class MyModel (QAbstractListModel):
+
+ stupidLine = QLine(0, 0, 10, 10)
+
+ def rowCount(self, parent):
+ return 1
+
+ def data(self, index, role):
+ return self.stupidLine
+
+
+class TestBug693(unittest.TestCase):
+ def testIt(self):
+ app = QApplication([])
+ model = MyModel()
+ view = QListView()
+ view.setModel(model)
+ view.show()
+
+ # This must NOT throw the exception:
+ # RuntimeError: Internal C++ object (PySide6.QtCore.QLine) already deleted.
+ MyModel.stupidLine.isNull()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_696.py b/sources/pyside6/tests/QtWidgets/bug_696.py
new file mode 100644
index 000000000..19e9978a6
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_696.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env 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 helper.usesqapplication import UsesQApplication
+from PySide6.QtWidgets import QMainWindow, QMenu, QApplication
+
+
+class MainWindow(QMainWindow):
+ def __init__(self, *args):
+ self._menu = QMenu(self.dontexist) # attribute called with invalid C++ object
+
+
+class MainWindow2(QMainWindow):
+ def __init__(self):
+ self.show()
+
+
+class Bug696(UsesQApplication):
+ def testContructorInitialization(self):
+ self.assertRaises(AttributeError, MainWindow)
+
+ def testContructorInitializationAndCPPFunction(self):
+ self.assertRaises(RuntimeError, MainWindow2)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_711.py b/sources/pyside6/tests/QtWidgets/bug_711.py
new file mode 100644
index 000000000..fed330fb9
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_711.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(False)
+
+from PySide6.QtGui import QAction
+from PySide6.QtWidgets import QToolBar, QApplication, QToolButton
+
+
+class TestLabelPixmap(unittest.TestCase):
+ def testReference(self):
+ toolbar = QToolBar()
+
+ for i in range(20):
+ toolbar.addAction(QAction(f"Action {i}"))
+
+ buttons = toolbar.findChildren(QToolButton, "")
+ toolbar.clear()
+
+ for b in buttons:
+ self.assertRaises(RuntimeError, b.objectName)
+
+
+if __name__ == '__main__':
+ app = QApplication([])
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_722.py b/sources/pyside6/tests/QtWidgets/bug_722.py
new file mode 100644
index 000000000..dc20e14cf
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_722.py
@@ -0,0 +1,36 @@
+# 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.QtWidgets import QDoubleSpinBox, QGraphicsBlurEffect
+
+
+class TestSignalConnection(UsesQApplication):
+ def testFloatSignal(self):
+ foo1 = QDoubleSpinBox()
+ foo2 = QDoubleSpinBox()
+ foo1.valueChanged[float].connect(foo2.setValue)
+ foo2.valueChanged[float].connect(foo1.setValue)
+ foo1.setValue(0.42)
+ self.assertEqual(foo1.value(), foo2.value())
+
+ def testQRealSignal(self):
+ foo1 = QDoubleSpinBox()
+ effect = QGraphicsBlurEffect()
+ effect.blurRadiusChanged['qreal'].connect(foo1.setValue) # check if qreal is a valid type
+ effect.setBlurRadius(0.42)
+ self.assertAlmostEqual(foo1.value(), effect.blurRadius())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_728.py b/sources/pyside6/tests/QtWidgets/bug_728.py
new file mode 100644
index 000000000..531adbb25
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_728.py
@@ -0,0 +1,39 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtWidgets import QApplication, QDialog, QFileDialog
+from PySide6.QtCore import QDir, QTimer
+
+
+# Periodically check for the file dialog to appear and close it
+dialog = None
+
+
+def timerHandler():
+ global dialog
+ if dialog is not None:
+ dialog.reject()
+ else:
+ for widget in QApplication.topLevelWidgets():
+ if isinstance(widget, QDialog) and widget.isVisible():
+ dialog = widget
+
+
+app = QApplication([])
+QTimer.singleShot(30000, app.quit) # emergency
+timer = QTimer()
+timer.setInterval(50)
+timer.timeout.connect(timerHandler)
+timer.start()
+
+# This test for a dead lock in QFileDialog.getOpenFileNames, the test fail with a timeout if the dead lock exists.
+QFileDialog.getOpenFileNames(None, "caption", QDir.homePath(), None, "", QFileDialog.DontUseNativeDialog)
diff --git a/sources/pyside6/tests/QtWidgets/bug_736.py b/sources/pyside6/tests/QtWidgets/bug_736.py
new file mode 100644
index 000000000..af4bcbda8
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_736.py
@@ -0,0 +1,30 @@
+# 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 Qt
+from PySide6.QtWidgets import QApplication, QSlider
+
+
+class TestBug736 (unittest.TestCase):
+
+ def testIt(self):
+ app = QApplication([])
+ slider = QSlider(Qt.Horizontal)
+ slider2 = QSlider(Qt.Horizontal)
+
+ slider2.setMaximum(10)
+ slider.valueChanged[int].connect(slider2.setMaximum)
+ slider.valueChanged[int].emit(100)
+ self.assertEqual(slider2.maximum(), 100)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_750.py b/sources/pyside6/tests/QtWidgets/bug_750.py
new file mode 100644
index 000000000..999f6a3db
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_750.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)
+
+from helper.usesqapplication import UsesQApplication
+
+from PySide6.QtCore import QTimer
+from PySide6.QtGui import QPainter, QFont, QFontInfo
+from PySide6.QtWidgets import QWidget
+
+
+class MyWidget(QWidget):
+ def paintEvent(self, e):
+ p = QPainter(self)
+ self._info = p.fontInfo()
+ self._app.quit()
+
+
+class TestQPainter(UsesQApplication):
+ def testFontInfo(self):
+ w = MyWidget()
+ w._app = self.app
+ w._info = None
+ QTimer.singleShot(300, w.show)
+ self.app.exec()
+ self.assertTrue(w._info)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_778.py b/sources/pyside6/tests/QtWidgets/bug_778.py
new file mode 100644
index 000000000..1a7def6c7
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_778.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(False)
+
+from helper.usesqapplication import UsesQApplication
+
+from PySide6.QtWidgets import QTreeWidget, QTreeWidgetItem, QTreeWidgetItemIterator
+
+
+class QTreeWidgetItemIteratorTest(UsesQApplication):
+ def testWidgetIterator(self):
+ treeWidget = QTreeWidget()
+ treeWidget.setColumnCount(1)
+ items = []
+ for i in range(10):
+ items.append(QTreeWidgetItem(None, [f'item: {i}']))
+ treeWidget.insertTopLevelItems(0, items)
+
+ index = 0
+ for it in QTreeWidgetItemIterator(treeWidget):
+ self.assertEqual(it.value().text(0), f'item: {index}')
+ index += 1
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_793.py b/sources/pyside6/tests/QtWidgets/bug_793.py
new file mode 100644
index 000000000..94f42a5d3
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_793.py
@@ -0,0 +1,45 @@
+# 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 QTimer
+from PySide6.QtWidgets import QWidget, QApplication
+
+
+class TestW1(QWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ TestW2(parent, self)
+
+
+class TestW2(QWidget):
+ def __init__(self, ancestor, parent=None):
+ super().__init__(parent)
+ self.ancestor_ref = ancestor
+
+
+class Test(QWidget):
+ def __init__(self):
+ super().__init__()
+ TestW1(self)
+
+
+class TestQApplicationDestrcutor(unittest.TestCase):
+ def testDestructor(self):
+ w = Test()
+ w.show()
+ QTimer.singleShot(0, w.close)
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ unittest.main()
+ sys.exit(app.exec())
diff --git a/sources/pyside6/tests/QtWidgets/bug_811.py b/sources/pyside6/tests/QtWidgets/bug_811.py
new file mode 100644
index 000000000..b3537e1f7
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_811.py
@@ -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
+
+import os
+import sys
+import unittest
+import weakref
+
+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.QtGui import QTextBlockUserData, QTextCursor
+from PySide6.QtWidgets import QTextEdit
+
+
+class TestUserData(QTextBlockUserData):
+ def __init__(self, data):
+ super().__init__()
+ self.data = data
+
+
+class TestUserDataRefCount(UsesQApplication):
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefcount(self):
+ textedit = QTextEdit()
+ textedit.setReadOnly(True)
+ doc = textedit.document()
+ cursor = QTextCursor(doc)
+ cursor.insertText("PySide Rocks")
+ ud = TestUserData({"Life": 42})
+ self.assertEqual(sys.getrefcount(ud), 2)
+ cursor.block().setUserData(ud)
+ self.assertEqual(sys.getrefcount(ud), 3)
+ ud2 = cursor.block().userData()
+ self.assertEqual(sys.getrefcount(ud), 4)
+ self.udata = weakref.ref(ud, None)
+ del ud, ud2
+ self.assertEqual(sys.getrefcount(self.udata()), 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_834.py b/sources/pyside6/tests/QtWidgets/bug_834.py
new file mode 100644
index 000000000..685f17e56
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_834.py
@@ -0,0 +1,33 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QTimer, Qt
+from PySide6.QtWidgets import QApplication, QDockWidget, QMainWindow
+
+
+class Window(QMainWindow):
+ def childEvent(self, event):
+ super(Window, self).childEvent(event)
+
+
+app = QApplication([])
+window = Window()
+
+dock1 = QDockWidget()
+dock2 = QDockWidget()
+window.addDockWidget(Qt.LeftDockWidgetArea, dock1)
+window.addDockWidget(Qt.LeftDockWidgetArea, dock2)
+window.tabifyDockWidget(dock1, dock2)
+
+window.show()
+QTimer.singleShot(0, window.close)
+app.exec()
diff --git a/sources/pyside6/tests/QtWidgets/bug_836.py b/sources/pyside6/tests/QtWidgets/bug_836.py
new file mode 100644
index 000000000..c2d3d5609
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_836.py
@@ -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
+
+import os
+import sys
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QTimer
+from PySide6.QtWidgets import QApplication, QFrame
+
+
+class Mixin1(object):
+ pass
+
+
+class Mixin2(object):
+ pass
+
+
+class Mixin3(object):
+ pass
+
+
+class MainWindow(Mixin1, Mixin2, Mixin3, QFrame):
+ def __init__(self):
+ super().__init__()
+
+
+def main():
+ app = QApplication([])
+ # if it doesn't crash it should pass
+ w = MainWindow()
+ w.show()
+ QTimer.singleShot(0, w.close)
+ app.exec()
+
+
+if __name__ == "__main__":
+ main()
+
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_844.py b/sources/pyside6/tests/QtWidgets/bug_844.py
new file mode 100644
index 000000000..913b4235c
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_844.py
@@ -0,0 +1,31 @@
+# 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 sys
+import os
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtWidgets import QApplication, QLabel
+from PySide6.QtCore import QObject, QTimer
+
+
+class QtKeyPressListener(QObject):
+ def __init__(self, obj):
+ super().__init__()
+ obj.installEventFilter(self)
+
+ def eventFilter(self, obj, event):
+ # This used to crash here due to a misbehaviour of type discovery!
+ return QObject.eventFilter(self, obj, event)
+
+
+app = QApplication([])
+key_listener = QtKeyPressListener(app)
+w = QLabel('Hello')
+w.show()
+QTimer.singleShot(0, w.close)
+app.exec()
diff --git a/sources/pyside6/tests/QtWidgets/bug_854.py b/sources/pyside6/tests/QtWidgets/bug_854.py
new file mode 100644
index 000000000..1dbfd4b3a
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_854.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 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.QtWidgets import QTableView, QApplication
+from PySide6.QtCore import QAbstractItemModel, QModelIndex
+
+from helper.usesqapplication import UsesQApplication
+
+
+class VirtualList(QAbstractItemModel):
+ def __getitem__(self, index):
+ self._getItemCalled = True
+ pass
+
+ def rowCount(self, parent):
+ return 5000
+
+ def columnCount(self, parent):
+ return 3
+
+ def index(self, row, column, parent):
+ return self.createIndex(row, column)
+
+ def parent(self, index):
+ return QModelIndex()
+
+ def data(self, index, role):
+ row = index.row()
+ col = index.column()
+ return f"({row}, {col})"
+
+
+class TestQAbstractItemModel(UsesQApplication):
+ def testSetModel(self):
+ model = VirtualList()
+ model._getItemCalled = False
+ table = QTableView()
+ table.setModel(model)
+ table.show()
+ self.assertFalse(model._getItemCalled)
+
+
+if __name__ == "__main__":
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_860.py b/sources/pyside6/tests/QtWidgets/bug_860.py
new file mode 100644
index 000000000..779feaa14
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_860.py
@@ -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
+
+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 QSignalMapper
+from PySide6.QtWidgets import QCheckBox
+
+from helper.usesqapplication import UsesQApplication
+
+
+class MultipleSlotTest(UsesQApplication):
+ def cb_changed(self, i):
+ self._changed = True
+
+ def cb_changedVoid(self):
+ self._changed = True
+
+ def testSignalMapper(self):
+ checkboxMapper = QSignalMapper()
+ box = QCheckBox('check me')
+ box.stateChanged.connect(checkboxMapper.map)
+
+ checkboxMapper.setMapping(box, box.text())
+ checkboxMapper.mappedString[str].connect(self.cb_changed)
+ self._changed = False
+ box.setChecked(True)
+ self.assertTrue(self._changed)
+
+ def testSimpleSignal(self):
+ box = QCheckBox('check me')
+ box.stateChanged[int].connect(self.cb_changedVoid)
+ self._changed = False
+ box.setChecked(True)
+ self.assertTrue(self._changed)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_862.py b/sources/pyside6/tests/QtWidgets/bug_862.py
new file mode 100644
index 000000000..49d9e24b2
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_862.py
@@ -0,0 +1,78 @@
+# 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 bug 862, original description was:
+#
+# print seems to be broken at least for QGraphicsItems-derived objects. The
+# attached code shows:
+#
+# <__main__.MyQObject object at 0xf99f38>
+# <__main__.MyQWidget object at 0xf99f38>
+# <PySide.QtGui.MyQGraphicsObject (this = 0x11c0d60 , parent = 0x0 , pos =
+# QPointF(0, 0) , z = 0 , flags = ( ) ) at 0xf99f38>
+# <PySide.QtGui.QGraphicsItem (this = 0x11c2e60 , parent = 0x0 , pos = QPointF(0,
+# 0) , z = 0 , flags = ( ) ) at 0xf99f38>
+#
+# Where it should be showing something like:
+#
+# <__main__.MyQObject object at 0x7f55cf226c20>
+# <__main__.MyQWidget object at 0x7f55cf226c20>
+# <__main__.MyQGraphicsObject object at 0x7f55cf226c20>
+# <__main__.MyQGraphicsItem object at 0x7f55cf226c20>
+#
+
+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
+from PySide6.QtWidgets import QApplication, QGraphicsItem, QGraphicsWidget, QGraphicsObject, QWidget
+import PySide6.QtCore
+
+
+class MyQObject(QObject):
+ def __init__(self):
+ super().__init__()
+
+
+class MyQWidget(QWidget):
+ def __init__(self):
+ super().__init__()
+
+
+class MyQGraphicsObject(QGraphicsObject):
+ def __init__(self):
+ super().__init__()
+
+
+class MyQGraphicsItem(QGraphicsItem):
+ def __init__(self):
+ super().__init__()
+
+
+class TestRepr (unittest.TestCase):
+
+ def testIt(self):
+
+ app = QApplication([])
+
+ self.assertEqual("<__main__.MyQObject(0x", repr(MyQObject())[:22])
+ self.assertEqual("<__main__.MyQWidget(0x", repr(MyQWidget())[:22])
+ self.assertEqual("<__main__.MyQGraphicsObject(0x", repr(MyQGraphicsObject())[:30])
+ self.assertEqual("<__main__.MyQGraphicsItem(0x", repr(MyQGraphicsItem())[:28])
+
+ self.assertEqual("<PySide6.QtCore.QObject(0x", repr(QObject())[:26])
+ self.assertEqual("<PySide6.QtCore.QObject(0x", repr(PySide6.QtCore.QObject())[:26])
+ self.assertEqual("<PySide6.QtWidgets.QWidget(0x", repr(QWidget())[:29])
+ self.assertEqual("<PySide6.QtWidgets.QGraphicsWidget(0x", repr(QGraphicsWidget())[:37])
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_871.py b/sources/pyside6/tests/QtWidgets/bug_871.py
new file mode 100644
index 000000000..4ee9b575a
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_871.py
@@ -0,0 +1,53 @@
+# 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.QtGui import QValidator, QIntValidator
+from PySide6.QtWidgets import QLineEdit
+
+'''Bug #871 - http://bugs.pyside.org/show_bug.cgi?id=871'''
+
+
+class BlankIntValidator(QIntValidator):
+ def validate(self, input, pos):
+ if input == '':
+ return QValidator.Acceptable, input, pos
+ else:
+ return QIntValidator.validate(self, input, pos)
+
+
+class Bug871Test(UsesQApplication):
+ def testWithoutValidator(self):
+ edit = QLineEdit()
+ self.assertEqual(edit.text(), '')
+ edit.insert('1')
+ self.assertEqual(edit.text(), '1')
+ edit.insert('a')
+ self.assertEqual(edit.text(), '1a')
+ edit.insert('2')
+ self.assertEqual(edit.text(), '1a2')
+
+ def testWithIntValidator(self):
+ edit = QLineEdit()
+ edit.setValidator(BlankIntValidator(edit))
+ self.assertEqual(edit.text(), '')
+ edit.insert('1')
+ self.assertEqual(edit.text(), '1')
+ edit.insert('a')
+ self.assertEqual(edit.text(), '1')
+ edit.insert('2')
+ self.assertEqual(edit.text(), '12')
+
+
+if __name__ == "__main__":
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/bug_879.py b/sources/pyside6/tests/QtWidgets/bug_879.py
new file mode 100644
index 000000000..31c656543
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_879.py
@@ -0,0 +1,43 @@
+# 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 QCoreApplication, QTimer, QEvent, Qt
+from PySide6.QtWidgets import QApplication, QSpinBox
+from PySide6.QtGui import QKeyEvent
+
+
+class MySpinBox(QSpinBox):
+
+ def validate(self, text, pos):
+ return QSpinBox.validate(self, text, pos)
+
+
+class TestBug879 (unittest.TestCase):
+
+ def testIt(self):
+ app = QApplication([])
+ self.box = MySpinBox()
+ self.box.show()
+
+ QTimer.singleShot(0, self.sendKbdEvent)
+ QTimer.singleShot(100, app.quit)
+ app.exec()
+
+ self.assertEqual(self.box.text(), '0')
+
+ def sendKbdEvent(self):
+ ev = QKeyEvent(QEvent.KeyPress, Qt.Key_A, Qt.NoModifier, 'a')
+ QCoreApplication.sendEvent(self.box, ev)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_919.py b/sources/pyside6/tests/QtWidgets/bug_919.py
new file mode 100644
index 000000000..67387ed26
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_919.py
@@ -0,0 +1,51 @@
+# 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.timedqapplication import TimedQApplication
+from PySide6.QtCore import Signal, QTimer
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import QPushButton, QStyleOptionButton, QApplication, QStyle
+
+
+class MyWidget(QPushButton):
+ def __init__(self, parent=None):
+ QPushButton.__init__(self, parent)
+ self._painted = False
+
+ def _emitPainted(self):
+ self.paintReceived.emit()
+
+ def paintEvent(self, e):
+ p = QPainter(self)
+ style = QApplication.style()
+ option = QStyleOptionButton()
+ style.drawControl(QStyle.CE_PushButton, option, p)
+ self._painted = True
+ QTimer.singleShot(0, self._emitPainted)
+
+ paintReceived = Signal()
+
+
+class TestBug919(TimedQApplication):
+ def setUp(self):
+ TimedQApplication.setUp(self, 2000)
+
+ def testFontInfo(self):
+ w = MyWidget()
+ w.paintReceived.connect(self.app.quit)
+ w.show()
+ self.app.exec()
+ self.assertTrue(w._painted)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_921.py b/sources/pyside6/tests/QtWidgets/bug_921.py
new file mode 100644
index 000000000..dafc1faef
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_921.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env 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(False)
+
+from PySide6.QtCore import QObject, Signal, Qt
+from PySide6.QtWidgets import QMainWindow
+from helper.timedqapplication import TimedQApplication
+
+
+class Signaller(QObject):
+ s1 = Signal()
+ s2 = Signal()
+ s3 = Signal()
+
+
+class Window(object):
+
+ def __init__(self, s):
+ self._window = QMainWindow()
+ self._window.setAttribute(Qt.WA_DeleteOnClose, True)
+ self._window.setWindowTitle("Demo!")
+
+ self._s = s
+ self._s.s1.connect(self._on_signal)
+ self._s.s2.connect(self._on_signal)
+
+ def show(self):
+ self._window.show()
+
+ def _on_signal(self):
+ self._window.setWindowTitle("Signaled!")
+
+
+class TestTimedApp(TimedQApplication):
+ def testSignals(self):
+ s = Signaller()
+ w = Window(s)
+ w.show()
+
+ def midleFunction():
+ def internalFunction():
+ pass
+ s.s3.connect(internalFunction)
+
+ midleFunction()
+ self.app.exec()
+ del w
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ s.s1.emit()
+ s.s2.emit()
+ s.s3.emit()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_941.py b/sources/pyside6/tests/QtWidgets/bug_941.py
new file mode 100644
index 000000000..336aa2f58
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_941.py
@@ -0,0 +1,31 @@
+# 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 Qt
+from PySide6.QtWidgets import QApplication, QHeaderView
+
+
+def foo(a, b):
+ pass
+
+
+class TestBug941 (unittest.TestCase):
+
+ def testIt(self):
+ app = QApplication([])
+ view = QHeaderView(Qt.Horizontal)
+ self.assertTrue(view.sortIndicatorChanged.connect(foo))
+ view.sortIndicatorChanged.emit(0, Qt.Vertical) # this can't raise an exception!
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_964.py b/sources/pyside6/tests/QtWidgets/bug_964.py
new file mode 100644
index 000000000..86bbddf16
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_964.py
@@ -0,0 +1,31 @@
+# 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 QStringListModel, Qt
+from PySide6.QtWidgets import QAbstractItemView, QApplication, QListView
+
+
+class TestBug964 (unittest.TestCase):
+
+ def testIt(self):
+ app = QApplication([])
+ model = QStringListModel(["1", "2"])
+ view = QListView()
+ view.setModel(model)
+ view.setCurrentIndex(model.index(0, 0))
+ newCursor = view.moveCursor(QAbstractItemView.MoveDown, Qt.NoModifier)
+ self.assertEqual(newCursor.row(), 1)
+ self.assertEqual(newCursor.column(), 0)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_967.py b/sources/pyside6/tests/QtWidgets/bug_967.py
new file mode 100644
index 000000000..03af030ca
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_967.py
@@ -0,0 +1,31 @@
+# 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.QtWidgets import QApplication, QComboBox
+
+
+class TestBug967 (unittest.TestCase):
+
+ def callback(self, arg):
+ self.arg = arg
+
+ def testIt(self):
+ self.arg = None
+ app = QApplication([])
+ obj = QComboBox()
+ obj.currentIndexChanged.connect(self.callback)
+ obj.currentIndexChanged.emit(5)
+ self.assertEqual(self.arg, 5)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_972.py b/sources/pyside6/tests/QtWidgets/bug_972.py
new file mode 100644
index 000000000..895cea128
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_972.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(False)
+
+from PySide6.QtCore import QSizeF
+from PySide6.QtWidgets import QGraphicsProxyWidget, QSizePolicy, QPushButton, QGraphicsScene, QGraphicsView
+
+from helper.timedqapplication import TimedQApplication
+
+
+def createItem(minimum, preferred, maximum, name):
+ w = QGraphicsProxyWidget()
+
+ w.setWidget(QPushButton(name))
+ w.setMinimumSize(minimum)
+ w.setPreferredSize(preferred)
+ w.setMaximumSize(maximum)
+ w.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
+
+ return w
+
+
+class TestBug972 (TimedQApplication):
+
+ # Test if the function QGraphicsProxyWidget.setWidget have the correct behavior
+ def testIt(self):
+ scene = QGraphicsScene()
+
+ minSize = QSizeF(30, 100)
+ prefSize = QSizeF(210, 100)
+ maxSize = QSizeF(300, 100)
+
+ a = createItem(minSize, prefSize, maxSize, "A")
+ b = createItem(minSize, prefSize, maxSize, "B")
+ c = createItem(minSize, prefSize, maxSize, "C")
+ d = createItem(minSize, prefSize, maxSize, "D")
+
+ view = QGraphicsView(scene)
+ view.show()
+ self.app.exec()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_979.py b/sources/pyside6/tests/QtWidgets/bug_979.py
new file mode 100644
index 000000000..a6c17385e
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_979.py
@@ -0,0 +1,21 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtWidgets import QDialog
+from import_test import PysideImportTest2
+
+
+class PysideImportTest1(QDialog, PysideImportTest2):
+ pass
+
+
+if __name__ == '__main__':
+ quit()
diff --git a/sources/pyside6/tests/QtWidgets/bug_988.py b/sources/pyside6/tests/QtWidgets/bug_988.py
new file mode 100644
index 000000000..f82ba6d27
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_988.py
@@ -0,0 +1,31 @@
+# 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.QtWidgets import QApplication, QTabWidget
+
+
+class TestBug988 (unittest.TestCase):
+
+ def callback(self, arg):
+ self.arg = arg
+
+ def testIt(self):
+ self.arg = None
+ app = QApplication([])
+ obj = QTabWidget()
+ obj.currentChanged.connect(self.callback)
+ obj.currentChanged.emit(5)
+ self.assertEqual(self.arg, 5)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/bug_998.py b/sources/pyside6/tests/QtWidgets/bug_998.py
new file mode 100644
index 000000000..0f6311515
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/bug_998.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)
+
+from PySide6.QtWidgets import QApplication
+
+
+class TestBug998 (unittest.TestCase):
+ def testNoFocusWindow(self):
+ widget = QApplication.focusWidget()
+ self.assertTrue(widget == None)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/customproxywidget_test.py b/sources/pyside6/tests/QtWidgets/customproxywidget_test.py
new file mode 100644
index 000000000..f7a1a1b1d
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/customproxywidget_test.py
@@ -0,0 +1,47 @@
+# 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 Qt, QTimer
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import QLabel
+from PySide6.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsItem, QGraphicsProxyWidget
+
+
+class CustomProxy(QGraphicsProxyWidget):
+ def __init__(self, parent=None, wFlags=0):
+ QGraphicsProxyWidget.__init__(self, parent, wFlags)
+
+
+class CustomProxyWidgetTest(UsesQApplication):
+ def testCustomProxyWidget(self):
+ scene = QGraphicsScene()
+
+ proxy = CustomProxy(None, Qt.Window)
+ widget = QLabel('Widget')
+ proxy.setWidget(widget)
+ proxy.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
+ scene.addItem(proxy)
+ scene.setSceneRect(scene.itemsBoundingRect())
+
+ view = QGraphicsView(scene)
+ view.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
+ view.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate)
+ view.show()
+
+ timer = QTimer.singleShot(100, self.app.quit)
+ self.app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/grandparent_method_test.py b/sources/pyside6/tests/QtWidgets/grandparent_method_test.py
new file mode 100644
index 000000000..ef848e22d
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/grandparent_method_test.py
@@ -0,0 +1,35 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Tests for calling methods further than the direct parent'''
+
+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.QtWidgets import QPushButton, QWidget
+
+from helper.usesqapplication import UsesQApplication
+
+
+class Dummy(QPushButton):
+
+ def show(self):
+ QWidget.show(self)
+ self.called = True
+
+
+class GrandParentMethod(UsesQApplication):
+ def testMethod(self):
+ obj = Dummy()
+ obj.show()
+ self.assertTrue(obj.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/hashabletype_test.py b/sources/pyside6/tests/QtWidgets/hashabletype_test.py
new file mode 100644
index 000000000..f12cceb5a
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/hashabletype_test.py
@@ -0,0 +1,30 @@
+# 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 cases for __hash__'''
+
+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.QtWidgets import QTreeWidgetItem
+from helper.usesqapplication import UsesQApplication
+
+
+class HashableTest(UsesQApplication):
+
+ def testQTreeWidgetItemHash(self):
+ h = {}
+ obj = QTreeWidgetItem()
+ h[obj] = 2
+ self.assertTrue(h.get(obj), 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/import_test.py b/sources/pyside6/tests/QtWidgets/import_test.py
new file mode 100644
index 000000000..0b60241f0
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/import_test.py
@@ -0,0 +1,2 @@
+class PysideImportTest2(object):
+ pass
diff --git a/sources/pyside6/tests/QtWidgets/keep_reference_test.py b/sources/pyside6/tests/QtWidgets/keep_reference_test.py
new file mode 100644
index 000000000..9d21c4580
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/keep_reference_test.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env 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 helper.usesqapplication import UsesQApplication
+from PySide6.QtCore import QAbstractTableModel
+from PySide6.QtWidgets import QTableView
+
+
+class TestModel(QAbstractTableModel):
+ def __init__(self, parent=None):
+ QAbstractTableModel.__init__(self, parent)
+
+ def rowCount(self, parent):
+ return 0
+
+ def columnCount(self, parent):
+ return 0
+
+ def data(self, index, role):
+ return None
+
+
+class KeepReferenceTest(UsesQApplication):
+
+ def testModelWithoutParent(self):
+ view = QTableView()
+ model = TestModel()
+ view.setModel(model)
+ samemodel = view.model()
+ self.assertEqual(model, samemodel)
+
+ def testModelWithParent(self):
+ view = QTableView()
+ model = TestModel(None)
+ view.setModel(model)
+ samemodel = view.model()
+ self.assertEqual(model, samemodel)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testReferenceCounting(self):
+ '''Tests reference count of model object referred by view objects.'''
+ model1 = TestModel()
+ refcount1 = sys.getrefcount(model1)
+ view1 = QTableView()
+ view1.setModel(model1)
+ self.assertEqual(sys.getrefcount(view1.model()), refcount1 + 1)
+
+ view2 = QTableView()
+ view2.setModel(model1)
+ self.assertEqual(sys.getrefcount(view2.model()), refcount1 + 2)
+
+ model2 = TestModel()
+ view2.setModel(model2)
+ self.assertEqual(sys.getrefcount(view1.model()), refcount1 + 1)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testReferenceCountingWhenDeletingReferrer(self):
+ '''Tests reference count of model object referred by deceased view object.'''
+ model = TestModel()
+ refcount1 = sys.getrefcount(model)
+ view = QTableView()
+ view.setModel(model)
+ self.assertEqual(sys.getrefcount(view.model()), refcount1 + 1)
+
+ del view
+ self.assertEqual(sys.getrefcount(model), refcount1)
+
+ def testReferreedObjectSurvivalAfterContextEnd(self):
+ '''Model object assigned to a view object must survive after getting out of context.'''
+ def createModelAndSetToView(view):
+ model = TestModel()
+ model.setObjectName('created model')
+ view.setModel(model)
+ view = QTableView()
+ createModelAndSetToView(view)
+ model = view.model()
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/missing_symbols_test.py b/sources/pyside6/tests/QtWidgets/missing_symbols_test.py
new file mode 100644
index 000000000..076c9e7e1
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/missing_symbols_test.py
@@ -0,0 +1,43 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''(Very) Simple test case for missing names from QtGui and QtWidgets'''
+
+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 QtGui
+from PySide6 import QtWidgets
+
+
+class MissingClasses(unittest.TestCase):
+ def testQDrag(self): # Bug 222
+ getattr(QtGui, 'QDrag')
+
+ def testQDropEvent(self): # Bug 255
+ getattr(QtGui, 'QDropEvent')
+
+
+class MissingMembers(unittest.TestCase):
+
+ def testQFontMetricsSize(self): # Bug 223
+ QtGui.QFontMetrics.size
+
+ def testQLayoutSetSpacing(self): # Bug 231
+ QtWidgets.QLayout.setSpacing
+
+ def testQImageLoad(self): # Bug 257
+ QtGui.QImage.load
+
+ def testQStandardItemModelinsertRow(self): # Bug 227
+ QtGui.QStandardItemModel.insertRow
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/paint_event_test.py b/sources/pyside6/tests/QtWidgets/paint_event_test.py
new file mode 100644
index 000000000..d995c2a37
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/paint_event_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
+
+'''Test paint event override in python'''
+
+import gc
+import os
+import sys
+import unittest
+
+from textwrap import dedent
+
+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 QTimer
+from PySide6.QtWidgets import QApplication, QWidget
+
+from helper.usesqapplication import UsesQApplication
+
+
+class MyWidget(QWidget):
+ '''Sample widget'''
+
+ def __init__(self, app):
+ # Creates a new widget
+ assert (app)
+
+ super().__init__()
+ self.app = app
+ self.paint_event_called = False
+
+ def paintEvent(self, event):
+ # Empty paint event method
+ super().paintEvent(event)
+ self.paint_event_called = True
+ QTimer.singleShot(20, self.close)
+
+
+class PaintEventOverride(UsesQApplication):
+ '''Test case for overriding QWidget.paintEvent'''
+
+ qapplication = True
+
+ def setUp(self):
+ # Acquire resources
+ super(PaintEventOverride, self).setUp()
+ self.widget = MyWidget(self.app)
+
+ def tearDown(self):
+ # Release resources
+ del self.widget
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(PaintEventOverride, self).tearDown()
+
+ def testPaintEvent(self):
+ # Test QWidget.paintEvent override
+ self.widget.show()
+ self.widget.setWindowTitle("paint_event_test")
+ self.app.exec()
+ self.assertTrue(self.widget.paint_event_called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/parent_method_test.py b/sources/pyside6/tests/QtWidgets/parent_method_test.py
new file mode 100644
index 000000000..0ab09eead
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/parent_method_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)
+
+from PySide6.QtCore import QObject, QTimer, QThread
+from PySide6.QtWidgets import QTableView, QWidget
+
+
+class Foo(QTableView):
+ def __init__(self, parent=None):
+ QTableView.__init__(self, parent)
+
+
+from helper.usesqapplication import UsesQApplication
+
+
+class TestParentType(UsesQApplication):
+
+ def testParentType(self):
+ # Test the problem with calling QObject.parent from a QWidget
+ # when the parent is a python class derived from a QWidget-derived
+ # class. The method was returning the last C++ class in the hierarchy
+ parent = Foo()
+ w2 = QWidget(parent)
+ self.assertTrue(isinstance(w2.parentWidget(), Foo))
+ self.assertTrue(isinstance(w2.parent(), Foo))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/private_mangle_test.py b/sources/pyside6/tests/QtWidgets/private_mangle_test.py
new file mode 100644
index 000000000..67ad14d68
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/private_mangle_test.py
@@ -0,0 +1,94 @@
+# 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
+
+"""
+This is the example from https://bugreports.qt.io/browse/PYSIDE-772
+with no interaction as a unittest.
+"""
+
+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 Signal
+from PySide6.QtWidgets import QApplication, QWidget
+from PySide6 import QtWidgets
+
+
+class Harness(QWidget):
+ clicked = Signal()
+
+ def __init__(self):
+ super().__init__()
+ self.clicked.connect(self.method)
+ self.clicked.connect(self._method)
+ self.clicked.connect(self.__method)
+
+ def method(self): # Public method
+ self.method_result = self.sender()
+
+ def _method(self): # Private method
+ self.method__result = self.sender()
+
+ def __method(self): # Name mangled method
+ self.method___result = self.sender()
+
+
+class _Under(QWidget):
+ clicked = Signal()
+
+ def __init__(self):
+ super().__init__()
+ self.clicked.connect(self.method)
+ self.clicked.connect(self._method)
+ self.clicked.connect(self.__method)
+
+ def method(self): # Public method
+ self.method_result = self.sender()
+
+ def _method(self): # Private method
+ self.method__result = self.sender()
+
+ def __method(self): # Name mangled method
+ self.method___result = self.sender()
+
+
+class TestMangle(unittest.TestCase):
+
+ def setUp(self):
+ QApplication()
+
+ def tearDown(self):
+ qApp.shutdown()
+
+ def testPrivateMangle(self):
+ harness = Harness()
+ harness.clicked.emit()
+ self.assertEqual(harness.method_result, harness)
+ self.assertEqual(harness.method__result, harness)
+ self.assertEqual(harness.method___result, harness)
+ self.assertTrue("method" in type(harness).__dict__)
+ self.assertTrue("_method" in type(harness).__dict__)
+ self.assertFalse("__method" in type(harness).__dict__)
+ self.assertTrue("_Harness__method" in type(harness).__dict__)
+
+ def testPrivateMangleUnder(self):
+ harness = _Under()
+ harness.clicked.emit()
+ self.assertEqual(harness.method_result, harness)
+ self.assertEqual(harness.method__result, harness)
+ self.assertEqual(harness.method___result, harness)
+ # make sure that we skipped over the underscore in "_Under"
+ self.assertTrue("method" in type(harness).__dict__)
+ self.assertTrue("_method" in type(harness).__dict__)
+ self.assertFalse("__method" in type(harness).__dict__)
+ self.assertTrue("_Under__method" in type(harness).__dict__)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/python_properties_test.py b/sources/pyside6/tests/QtWidgets/python_properties_test.py
new file mode 100644
index 000000000..ee8a38014
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/python_properties_test.py
@@ -0,0 +1,31 @@
+# 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 QLocale
+from PySide6.QtWidgets import QGraphicsItem, QStyleOptionViewItem
+
+
+class Properties(unittest.TestCase):
+
+ def testStaticProperty(self):
+ self.assertEqual(QGraphicsItem.UserType, 65536)
+
+ def testInstanceProperty(self):
+ p = QStyleOptionViewItem()
+ self.assertTrue(isinstance(p.locale, QLocale))
+
+ # PSYIDE-304, can assign to a "const QWidget *" field
+ p.widget = None
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qabstracttextdocumentlayout_test.py b/sources/pyside6/tests/QtWidgets/qabstracttextdocumentlayout_test.py
new file mode 100644
index 000000000..1ae3b0a35
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qabstracttextdocumentlayout_test.py
@@ -0,0 +1,59 @@
+# 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 QSizeF, QTimer
+from PySide6.QtGui import QTextFormat, QTextCharFormat, QPyTextObject
+from PySide6.QtWidgets import QTextEdit
+from helper.usesqapplication import UsesQApplication
+
+
+class Foo(QPyTextObject):
+ called = False
+
+ def intrinsicSize(self, doc, posInDocument, format):
+ Foo.called = True
+ return QSizeF(10, 10)
+
+ def drawObject(self, painter, rect, doc, posInDocument, format):
+ pass
+
+
+class QAbstractTextDocumentLayoutTest(UsesQApplication):
+
+ objectType = QTextFormat.UserObject + 1
+
+ def foo(self):
+ fmt = QTextCharFormat()
+ fmt.setObjectType(QAbstractTextDocumentLayoutTest.objectType)
+
+ cursor = self.textEdit.textCursor()
+ cursor.insertText(chr(0xfffc), fmt)
+ self.textEdit.setTextCursor(cursor)
+ self.textEdit.close()
+
+ def testIt(self):
+
+ self.textEdit = QTextEdit()
+ self.textEdit.show()
+
+ interface = Foo()
+ self.textEdit.document().documentLayout().registerHandler(QAbstractTextDocumentLayoutTest.objectType, interface)
+
+ QTimer.singleShot(0, self.foo)
+ self.app.exec()
+
+ self.assertTrue(Foo.called)
+
+
+if __name__ == "__main__":
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qaccessible_test.py b/sources/pyside6/tests/QtWidgets/qaccessible_test.py
new file mode 100644
index 000000000..021cf9c6b
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qaccessible_test.py
@@ -0,0 +1,138 @@
+# 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 cases for QAccessible::installFactory().'''
+
+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 QCoreApplication, Qt
+from PySide6.QtGui import QAccessible, QAccessibleInterface, QColor
+from PySide6.QtWidgets import QWidget, QLineEdit, QVBoxLayout
+
+from helper.usesqapplication import UsesQApplication
+
+
+class LineEditAccessible(QAccessibleInterface):
+ """Mimick a QAccessibleInterface implementation for QLineEdit."""
+
+ instance_count = 0
+
+ def __init__(self, widget):
+ super().__init__()
+ LineEditAccessible.instance_count += 1
+ self._widget = widget
+ self._name = self._widget.objectName()
+ print('LineEditAccessible', self._name)
+
+ def __del__(self):
+ LineEditAccessible.instance_count -= 1
+ print('~LineEditAccessible', self._name)
+
+ def actionInterface(self):
+ return None
+
+ def backgroundColor(self):
+ return QColor(Qt.white)
+
+ def child(self, index):
+ return None
+
+ def childAt(self, x, y):
+ return None
+
+ def childCount(self):
+ return 0
+
+ def focusChild(self):
+ return None
+
+ def foregroundColor(self):
+ return QColor(Qt.black)
+
+ def indexOfChild(self, child):
+ return -1
+
+ def isValid(self):
+ return True
+
+ def object(self):
+ return self._widget
+
+ def parent(self):
+ return None
+
+ def rect(self):
+ return self._widget.geometry()
+
+ def role(self):
+ return QAccessible.EditableText
+
+ def setText(self, t, text):
+ pass
+
+ def state(self):
+ return QAccessible.State()
+
+ def tableCellInterface(self):
+ return None
+
+ def tableInterface(self):
+ return None
+
+ def text(self, t):
+ return self._widget.text() if t == QAccessible.Value else ''
+
+ def textInterface(self):
+ return None
+
+ def valueInterface(self):
+ return None
+
+ def window(self):
+ return self._widget.window().windowHandle()
+
+
+def accessible_factory(key, obj):
+ """Factory function for QAccessibleInterface for QLineEdit's."""
+ if obj.metaObject().className() == 'QLineEdit':
+ return LineEditAccessible(obj)
+ return None
+
+
+class Window(QWidget):
+ """Test window with 2 QLineEdit's."""
+ def __init__(self):
+ super().__init__()
+ self.setObjectName('top')
+ layout = QVBoxLayout(self)
+ self.m_line_edit1 = QLineEdit("bla")
+ layout.addWidget(self.m_line_edit1)
+ self.m_line_edit2 = QLineEdit("bla")
+ layout.addWidget(self.m_line_edit2)
+
+
+class QAccessibleTest(UsesQApplication):
+ """Test that LineEditAccessible instances are created for QLineEdit's."""
+
+ def setUp(self):
+ super().setUp()
+ QAccessible.installFactory(accessible_factory)
+ window = Window()
+
+ def testLineEdits(self):
+ window = Window()
+ window.show()
+ while not window.windowHandle().isExposed():
+ QCoreApplication.processEvents()
+ self.assertEqual(LineEditAccessible.instance_count, 2)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qaction_test.py b/sources/pyside6/tests/QtWidgets/qaction_test.py
new file mode 100644
index 000000000..a0049421f
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qaction_test.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 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.QtGui import QAction
+from PySide6.QtWidgets import QWidget, QMenu
+from helper.usesqapplication import UsesQApplication
+
+
+class QPainterDrawText(UsesQApplication):
+
+ def _cb(self):
+ self._called = True
+
+ def testSignal(self):
+ o = QWidget()
+ act = QAction(o)
+ self._called = False
+ act.triggered.connect(self._cb)
+ act.trigger()
+ self.assertTrue(self._called)
+
+ def testNewCtor(self):
+ o = QWidget()
+ self._called = False
+ myAction = QAction("&Quit", o, triggered=self._cb)
+ myAction.trigger()
+ self.assertTrue(self._called)
+
+
+class SetShortcutTest(UsesQApplication):
+
+ def testSetShortcut(self):
+ # Somehow an exception was leaking from the constructor
+ # and appearing in setShortcut.
+ o = QWidget()
+ action = QAction('aaaa', o)
+ shortcut = 'Ctrl+N'
+ action.setShortcut(shortcut)
+ s2 = action.shortcut()
+ self.assertEqual(s2, shortcut)
+
+ def testMenu(self):
+ # Test the setMenu()/menu() old functionality removed in Qt6
+ # that was added via helper functions.
+ menu = QMenu("menu")
+ action = QAction("action")
+
+ # Using QAction::setMenu(QObject*)
+ action.setMenu(menu)
+
+ self.assertEqual(action.menu(), menu)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qapp_issue_585.py b/sources/pyside6/tests/QtWidgets/qapp_issue_585.py
new file mode 100644
index 000000000..0b5453af5
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qapp_issue_585.py
@@ -0,0 +1,53 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+"""
+The bug was caused by this commit:
+"Support the qApp macro correctly, final version incl. debug"
+e30e0c161b2b4d50484314bf006e9e5e8ff6b380
+2017-10-27
+
+The bug was first solved by this commit:
+"Fix qApp macro refcount"
+b811c874dedd14fd8b072bc73761d39255216073
+2018-03-21
+
+This test triggers the refcounting bug of qApp, issue PYSIDE-585.
+Finally, the real patch included more changes, because another error
+was in the ordering of shutdown calls. It was found using the following
+Python configuration:
+
+ In Python 3.6 create a directory 'debug' and cd into it.
+
+ ../configure --with-pydebug --prefix=$HOME/pydebug/ --enable-shared
+
+Then a lot more refcounting errors show up, which are due to a bug in
+the code position of the shutdown procedure.
+The reason for the initial refcount bug was that the shutdown code is once
+more often called than the creation of the qApp wrapper.
+Finally, it was easiest and more intuitive to simply make the refcount of
+qApp_content equal to that of Py_None, which is also not supposed to be
+garbage-collected.
+
+For some reason, the test does not work as a unittest because it creates
+no crash. We leave it this way.
+"""
+
+import os
+import sys
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtCore import QTimer
+from PySide6.QtWidgets import QApplication
+
+
+app_instance = QApplication([])
+# If the following line is commented, application doesn't crash on exit anymore.
+app_instance2 = app_instance
+QTimer.singleShot(0, qApp.quit)
+app_instance.exec_()
diff --git a/sources/pyside6/tests/QtWidgets/qapp_test.py b/sources/pyside6/tests/QtWidgets/qapp_test.py
new file mode 100644
index 000000000..5a66b8e33
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qapp_test.py
@@ -0,0 +1,31 @@
+# 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 the presence of qApp Macro'''
+
+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.QtWidgets import QApplication
+
+
+class QAppPresence(unittest.TestCase):
+
+ def testQApp(self):
+ # QtGui.qApp variable is instance of QApplication
+ self.assertTrue(isinstance(qApp, QApplication))
+
+
+def main():
+ app = QApplication([])
+ unittest.main()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/sources/pyside6/tests/QtWidgets/qapplication_exit_segfault_test.py b/sources/pyside6/tests/QtWidgets/qapplication_exit_segfault_test.py
new file mode 100644
index 000000000..8bb47bc1c
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qapplication_exit_segfault_test.py
@@ -0,0 +1,30 @@
+# 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.QtWidgets import QApplication, QPushButton, QWidget, QSpinBox
+
+
+class QApplicationDelete(unittest.TestCase):
+ '''Test for segfault when deleting a QApplication before a QWidget'''
+
+ def testQPushButton(self):
+ # QApplication deleted before QPushButton
+ a = QApplication([])
+ b = QPushButton('aaaa')
+ del a
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qapplication_test.py b/sources/pyside6/tests/QtWidgets/qapplication_test.py
new file mode 100644
index 000000000..7c5b61fd9
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qapplication_test.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)
+
+from PySide6.QtWidgets import QApplication
+
+
+class TestQApplication(unittest.TestCase):
+ def testNoArguments(self):
+ app = QApplication()
+ self.assertIsInstance(app, QApplication)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qcolormap_test.py b/sources/pyside6/tests/QtWidgets/qcolormap_test.py
new file mode 100644
index 000000000..f63a9486f
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qcolormap_test.py
@@ -0,0 +1,25 @@
+# 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.QtWidgets import QColormap
+from helper.usesqapplication import UsesQApplication
+
+
+class QColormapTest(UsesQApplication):
+
+ def testQColormap(self):
+ qc = QColormap.instance()
+ self.assertEqual(qc.size(), -1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qdialog_test.py b/sources/pyside6/tests/QtWidgets/qdialog_test.py
new file mode 100644
index 000000000..cb85ce7e2
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qdialog_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
+import weakref
+
+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 Slot, QTimer
+from PySide6.QtWidgets import QDialog, QMainWindow
+from helper.timedqapplication import TimedQApplication
+
+
+class Window(QMainWindow):
+ def __init__(self):
+ super().__init__()
+ self.setWindowTitle("Main")
+ self.dialog = None
+
+ @Slot()
+ def execDialog(self):
+ dialog = QDialog(self)
+ self.dialog = weakref.ref(dialog)
+ dialog.setWindowTitle("Dialog")
+ dialog.setMinimumWidth(200)
+ QTimer.singleShot(500, dialog.reject)
+ dialog.exec()
+ self.close()
+
+
+class DialogExecTest(TimedQApplication):
+ """Test whether the parent-child relationship (dialog/main window) is removed when
+ using QDialog.exec() (instead show()), preventing the dialog from leaking."""
+
+ def setUp(self):
+ super().setUp(10000)
+ self._window = Window()
+
+ def testExec(self):
+ self._window.show()
+ QTimer.singleShot(500, self._window.execDialog)
+ self.app.exec()
+ self.assertTrue(self._window.dialog() is None)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qdynamic_signal.py b/sources/pyside6/tests/QtWidgets/qdynamic_signal.py
new file mode 100644
index 000000000..83d6af383
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qdynamic_signal.py
@@ -0,0 +1,41 @@
+# 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
+from PySide6.QtWidgets import QInputDialog
+
+from helper.usesqapplication import UsesQApplication
+
+
+class DynamicSignalTest(UsesQApplication):
+
+ def cb(self, obj):
+ self._called = True
+
+ def testQDialog(self):
+ dlg = QInputDialog()
+ dlg.setInputMode(QInputDialog.TextInput)
+ lst = dlg.children()
+ self.assertTrue(len(lst))
+ obj = lst[0]
+ self._called = False
+ obj.destroyed[QObject].connect(self.cb)
+ obj = None
+ del dlg
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertTrue(self._called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qfontdialog_test.py b/sources/pyside6/tests/QtWidgets/qfontdialog_test.py
new file mode 100644
index 000000000..764329732
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qfontdialog_test.py
@@ -0,0 +1,31 @@
+# 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.QtGui import QFont
+from PySide6.QtWidgets import QFontDialog
+from helper.timedqapplication import TimedQApplication
+
+
+class TestFontDialog(TimedQApplication):
+
+ def testGetFont(self):
+ QFontDialog.getFont()
+
+ def testGetFontQDialog(self):
+ QFontDialog.getFont(QFont("FreeSans", 10))
+
+ def testGetFontQDialogQString(self):
+ QFontDialog.getFont(QFont("FreeSans", 10), None, "Select font")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qformlayout_test.py b/sources/pyside6/tests/QtWidgets/qformlayout_test.py
new file mode 100644
index 000000000..f87ea6935
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qformlayout_test.py
@@ -0,0 +1,99 @@
+# 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.QtWidgets import QFormLayout, QWidget, QLabel, QMainWindow
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QFormLayoutTest(UsesQApplication):
+
+ def testGetItemPosition(self):
+ formlayout = QFormLayout()
+
+ row, role = formlayout.getItemPosition(0)
+ self.assertTrue(isinstance(row, int))
+ self.assertTrue(isinstance(role, QFormLayout.ItemRole))
+ self.assertEqual(row, -1)
+
+ widget = QWidget()
+ formlayout.addRow(widget)
+ row, role = formlayout.getItemPosition(0)
+ self.assertTrue(isinstance(row, int))
+ self.assertTrue(isinstance(role, QFormLayout.ItemRole))
+ self.assertEqual(row, 0)
+ self.assertEqual(role, QFormLayout.SpanningRole)
+
+ def testGetWidgetPosition(self):
+ formlayout = QFormLayout()
+ widget = QWidget()
+
+ row, role = formlayout.getWidgetPosition(widget)
+ self.assertTrue(isinstance(row, int))
+ self.assertTrue(isinstance(role, QFormLayout.ItemRole))
+ self.assertEqual(row, -1)
+
+ formlayout.addRow(widget)
+ row, role = formlayout.getWidgetPosition(widget)
+ self.assertTrue(isinstance(row, int))
+ self.assertTrue(isinstance(role, QFormLayout.ItemRole))
+ self.assertEqual(row, 0)
+ self.assertEqual(role, QFormLayout.SpanningRole)
+
+ def testGetLayoutPosition(self):
+ formlayout = QFormLayout()
+ layout = QFormLayout()
+
+ row, role = formlayout.getLayoutPosition(layout)
+ self.assertTrue(isinstance(row, int))
+ self.assertTrue(isinstance(role, QFormLayout.ItemRole))
+ self.assertEqual(row, -1)
+
+ formlayout.addRow(layout)
+ row, role = formlayout.getLayoutPosition(layout)
+ self.assertTrue(isinstance(row, int))
+ self.assertTrue(isinstance(role, QFormLayout.ItemRole))
+ self.assertEqual(row, 0)
+ self.assertEqual(role, QFormLayout.SpanningRole)
+
+ def testTakeRow(self):
+ window = QMainWindow()
+ window.setCentralWidget(QWidget())
+ formlayout = QFormLayout(window.centralWidget())
+
+ widget_label = "blub"
+ widget = QLabel(widget_label)
+
+ self.assertEqual(formlayout.count(), 0)
+ formlayout.addRow(widget)
+ self.assertEqual(formlayout.count(), 1)
+ self.assertEqual(formlayout.itemAt(0).widget(), widget)
+
+ widget_id = id(widget)
+
+ # Now there are no more references to the original widget on the
+ # Python side. Assert that this does not break the references to
+ # the widget on the C++ side so that "taking" the row will work.
+ del widget
+
+ takeRowResult = formlayout.takeRow(0)
+ self.assertEqual(formlayout.count(), 0)
+
+ widget = takeRowResult.fieldItem.widget()
+
+ self.assertIsNotNone(widget)
+ self.assertEqual(widget_id, id(widget))
+ self.assertEqual(widget.text(), widget_label)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qgraphicsitem_isblocked_test.py b/sources/pyside6/tests/QtWidgets/qgraphicsitem_isblocked_test.py
new file mode 100644
index 000000000..cb4115b55
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qgraphicsitem_isblocked_test.py
@@ -0,0 +1,41 @@
+#!/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.QtCore import QRectF
+from PySide6.QtWidgets import QGraphicsItem
+from PySide6.QtGui import QColor
+from helper.usesqapplication import UsesQApplication
+
+
+class Item(QGraphicsItem):
+
+ def __init__(self):
+ super().__init__()
+
+ def boundingRect(self):
+ return QRectF(0, 0, 100, 100)
+
+ def paint(self, painter, option, widget):
+ painter.setBrush(QColor(255, 255, 255))
+ painter.drawRect(0, 0, 100, 100)
+
+
+class QGraphicsViewIsBlockedTest(UsesQApplication):
+
+ def testIsBlockedByModalPanel(self):
+ (first, second) = Item().isBlockedByModalPanel()
+ self.assertFalse(first)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qgraphicsitem_test.py b/sources/pyside6/tests/QtWidgets/qgraphicsitem_test.py
new file mode 100644
index 000000000..1114ad4fe
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qgraphicsitem_test.py
@@ -0,0 +1,50 @@
+# 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 cases related to QGraphicsItem and subclasses'''
+
+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.QtGui import QPolygonF, QColor, QBrush
+from PySide6.QtWidgets import QGraphicsScene
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QColorOnSetBrush(UsesQApplication):
+ '''Test case for passing a QColor directly to setBrush'''
+
+ def setUp(self):
+ # Acquire resources
+ super(QColorOnSetBrush, self).setUp()
+
+ self.scene = QGraphicsScene()
+ poly = QPolygonF()
+ self.item = self.scene.addPolygon(poly)
+ self.color = QColor('black')
+
+ def tearDown(self):
+ # Release resources
+ del self.color
+ del self.item
+ del self.scene
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(QColorOnSetBrush, self).tearDown()
+
+ def testQColor(self):
+ # QGraphicsAbstractShapeItem.setBrush(QColor)
+ self.item.setBrush(self.color)
+ self.assertEqual(QBrush(self.color), self.item.brush())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py b/sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py
new file mode 100644
index 000000000..a3d28b4d3
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py
@@ -0,0 +1,62 @@
+# 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 cases related to QGraphicsItem and subclasses'''
+
+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.QtWidgets import QGraphicsObject, QGraphicsWidget
+from PySide6.QtCore import QRectF
+
+from helper.usesqapplication import UsesQApplication
+
+
+class GObjA(QGraphicsObject):
+ def paint(self, *args):
+ pass
+
+ def boundingRect(self):
+ return QRectF()
+
+ def itemChange(self, *args):
+ return QGraphicsObject.itemChange(self, *args)
+
+
+class GObjB(QGraphicsObject):
+ def paint(self, *args):
+ pass
+
+ def boundingRect(self):
+ return QRectF()
+
+
+class QGraphicsObjectReimpl(UsesQApplication):
+ '''Test case for reimplementing QGraphicsObject'''
+
+ def testReimplementationTypes(self):
+ w = QGraphicsWidget()
+
+ # PYSIDE-86:
+ # This case failed because GObjA was reimplementing
+ # the method itemChange() from QGraphicsItem,
+ # and then the QVariant was not associated with
+ # a QGraphicsItem but a QObjectItem because the base
+ # class was a QObject.
+ gobjA = GObjA()
+ gobjA.setParentItem(w)
+ self.assertIs(type(w), type(gobjA.parentItem()))
+
+ gobjB = GObjB()
+ gobjB.setParentItem(w)
+ self.assertIs(type(w), type(gobjB.parentItem()))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qgraphicsproxywidget_test.py b/sources/pyside6/tests/QtWidgets/qgraphicsproxywidget_test.py
new file mode 100644
index 000000000..dee616bbe
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qgraphicsproxywidget_test.py
@@ -0,0 +1,42 @@
+# 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 Qt, QTimer
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import QLabel
+from PySide6.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsItem, QGraphicsProxyWidget
+
+
+class QGraphicsProxyWidgetTest(UsesQApplication):
+ def testQGraphicsProxyWidget(self):
+ scene = QGraphicsScene()
+
+ proxy = QGraphicsProxyWidget(None, Qt.Window)
+ widget = QLabel('Widget')
+ proxy.setWidget(widget)
+ proxy.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
+ scene.addItem(proxy)
+ scene.setSceneRect(scene.itemsBoundingRect())
+
+ view = QGraphicsView(scene)
+ view.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
+ view.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate)
+ view.show()
+
+ timer = QTimer.singleShot(100, self.app.quit)
+ self.app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qgraphicsscene_test.py b/sources/pyside6/tests/QtWidgets/qgraphicsscene_test.py
new file mode 100644
index 000000000..86604f27b
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qgraphicsscene_test.py
@@ -0,0 +1,213 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Basic test cases for QGraphicsScene'''
+
+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 QPointF
+from PySide6.QtGui import QPolygonF, QPixmap, QPainterPath, QTransform, QWindow
+from PySide6.QtWidgets import QApplication, QPushButton
+from PySide6.QtWidgets import QGraphicsScene
+from PySide6.QtWidgets import QGraphicsEllipseItem, QGraphicsLineItem
+from PySide6.QtWidgets import QGraphicsPathItem, QGraphicsPixmapItem
+from PySide6.QtWidgets import QGraphicsPolygonItem, QGraphicsRectItem
+from PySide6.QtWidgets import QGraphicsSimpleTextItem, QGraphicsTextItem
+from PySide6.QtWidgets import QGraphicsProxyWidget, QGraphicsView
+
+from helper.usesqapplication import UsesQApplication
+
+
+class Constructor(unittest.TestCase):
+ '''QGraphicsScene constructor'''
+
+ def testConstructor(self):
+ # QGraphicsScene constructor
+ obj = QGraphicsScene()
+ self.assertTrue(isinstance(obj, QGraphicsScene))
+
+# Test for PYSIDE-868: Test whether painter.device() can be accessed
+# correctly. This was crashing when the underlying QPaintDevice was a
+# QWidget due to handling multiple inheritance incorrectly.
+
+
+class CustomScene(QGraphicsScene):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.dpi = 0
+
+ def drawBackground(self, painter, rect):
+ self.dpi = painter.device().physicalDpiX()
+
+ def drawForeground(self, painter, rect):
+ self.dpi = painter.device().physicalDpiX()
+
+
+class ConstructorWithRect(unittest.TestCase):
+ '''QGraphicsScene qrect constructor and related sizes'''
+
+ def setUp(self):
+ # Acquire resources
+ # PyQt4 doesn't accept a QRect as argument to constructor
+ self.scene = QGraphicsScene(0, 200, 150, 175)
+
+ def tearDown(self):
+ # Release resources
+ del self.scene
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testHeight(self):
+ # QGraphicsScene.height()
+ self.assertEqual(self.scene.height(), 175)
+
+ def testWidth(self):
+ # QGraphicsScene.width()
+ self.assertEqual(self.scene.width(), 150)
+
+
+class AddItem(UsesQApplication):
+ '''Tests for QGraphicsScene.add*'''
+
+ qapplication = True
+
+ def setUp(self):
+ # Acquire resources
+ super(AddItem, self).setUp()
+ self.scene = QGraphicsScene()
+ # While the scene does not inherits from QWidget, requires
+ # an application to make the internals work.
+
+ def tearDown(self):
+ # Release resources
+ del self.scene
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(AddItem, self).tearDown()
+
+ def testEllipse(self):
+ # QGraphicsScene.addEllipse
+ item = self.scene.addEllipse(100, 100, 100, 100)
+ self.assertTrue(isinstance(item, QGraphicsEllipseItem))
+
+ def testLine(self):
+ # QGraphicsScene.addLine
+ item = self.scene.addLine(100, 100, 200, 200)
+ self.assertTrue(isinstance(item, QGraphicsLineItem))
+
+ def testPath(self):
+ # QGraphicsScene.addPath
+ item = self.scene.addPath(QPainterPath())
+ self.assertTrue(isinstance(item, QGraphicsPathItem))
+
+ def testPixmap(self):
+ # QGraphicsScene.addPixmap
+ item = self.scene.addPixmap(QPixmap())
+ self.assertTrue(isinstance(item, QGraphicsPixmapItem))
+
+ def testPolygon(self):
+ # QGraphicsScene.addPolygon
+ points = [QPointF(0, 0), QPointF(100, 100), QPointF(0, 100)]
+ item = self.scene.addPolygon(QPolygonF(points))
+ self.assertTrue(isinstance(item, QGraphicsPolygonItem))
+
+ def testRect(self):
+ # QGraphicsScene.addRect
+ item = self.scene.addRect(100, 100, 100, 100)
+ self.assertTrue(isinstance(item, QGraphicsRectItem))
+
+ def testSimpleText(self):
+ # QGraphicsScene.addSimpleText
+ item = self.scene.addSimpleText('Monty Python 42')
+ self.assertTrue(isinstance(item, QGraphicsSimpleTextItem))
+
+ def testText(self):
+ # QGraphicsScene.addText
+ item = self.scene.addText('Monty Python 42')
+ self.assertTrue(isinstance(item, QGraphicsTextItem))
+
+ def testWidget(self):
+ # QGraphicsScene.addWidget
+ # XXX: printing some X11 error when using under PyQt4
+ item = self.scene.addWidget(QPushButton())
+ self.assertTrue(isinstance(item, QGraphicsProxyWidget))
+
+
+class ItemRetrieve(UsesQApplication):
+ '''Tests for QGraphicsScene item retrieval methods'''
+
+ qapplication = True
+
+ def setUp(self):
+ # Acquire resources
+ super(ItemRetrieve, self).setUp()
+ self.scene = QGraphicsScene()
+
+ self.topleft = QGraphicsRectItem(0, 0, 100, 100)
+ self.topright = QGraphicsRectItem(100, 0, 100, 100)
+ self.bottomleft = QGraphicsRectItem(0, 100, 100, 100)
+ self.bottomright = QGraphicsRectItem(100, 100, 100, 100)
+
+ self.items = [self.topleft, self.topright, self.bottomleft,
+ self.bottomright]
+
+ for item in self.items:
+ self.scene.addItem(item)
+
+ def tearDown(self):
+ # Release resources
+ del self.scene
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(ItemRetrieve, self).tearDown()
+
+ def testItems(self):
+ # QGraphicsScene.items()
+ items = self.scene.items()
+ for i in items:
+ self.assertTrue(i in self.items)
+
+ def testItemAt(self):
+ # QGraphicsScene.itemAt()
+ self.assertEqual(self.scene.itemAt(50, 50, QTransform()), self.topleft)
+ self.assertEqual(self.scene.itemAt(150, 50, QTransform()), self.topright)
+ self.assertEqual(self.scene.itemAt(50, 150, QTransform()), self.bottomleft)
+ self.assertEqual(self.scene.itemAt(150, 150, QTransform()), self.bottomright)
+
+
+class TestGraphicsGroup(UsesQApplication):
+ def testIt(self):
+ scene = QGraphicsScene()
+ i1 = QGraphicsRectItem()
+ scene.addItem(i1)
+ i2 = QGraphicsRectItem(i1)
+ i3 = QGraphicsRectItem()
+ i4 = QGraphicsRectItem()
+ group = scene.createItemGroup((i2, i3, i4))
+ scene.removeItem(i1)
+ del i1 # this shouldn't delete i2
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertEqual(i2.scene(), scene)
+ scene.destroyItemGroup(group)
+ self.assertRaises(RuntimeError, group.type)
+
+ def testCustomScene(self): # For PYSIDE-868, see above
+ scene = CustomScene()
+ view = QGraphicsView(scene)
+ view.show()
+ while scene.dpi == 0:
+ QApplication.processEvents()
+ view.hide()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qinputdialog_get_test.py b/sources/pyside6/tests/QtWidgets/qinputdialog_get_test.py
new file mode 100644
index 000000000..260653ae7
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qinputdialog_get_test.py
@@ -0,0 +1,47 @@
+# 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 QTimer
+from PySide6.QtWidgets import QApplication, QInputDialog, QDialog
+from helper.usesqapplication import UsesQApplication
+
+
+def close_dialog():
+ for w in QApplication.topLevelWidgets():
+ if isinstance(w, QDialog):
+ w.reject()
+
+
+class TestInputDialog(UsesQApplication):
+
+ def testGetDouble(self):
+ QTimer.singleShot(500, close_dialog)
+ self.assertEqual(QInputDialog.getDouble(None, "title", "label"), (0.0, False))
+
+ def testGetInt(self):
+ QTimer.singleShot(500, close_dialog)
+ self.assertEqual(QInputDialog.getInt(None, "title", "label"), (0, False))
+
+ def testGetItem(self):
+ QTimer.singleShot(500, close_dialog)
+ (item, bool) = QInputDialog.getItem(None, "title", "label", ["1", "2", "3"])
+ self.assertEqual(str(item), "1")
+
+ def testGetText(self):
+ QTimer.singleShot(500, close_dialog)
+ (text, bool) = QInputDialog.getText(None, "title", "label")
+ self.assertEqual(str(text), "")
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qkeysequenceedit_test.py b/sources/pyside6/tests/QtWidgets/qkeysequenceedit_test.py
new file mode 100644
index 000000000..bcb4c7a61
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qkeysequenceedit_test.py
@@ -0,0 +1,31 @@
+# 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 cases for QKeySequenceEdit.'''
+
+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 QTimer
+from PySide6.QtWidgets import QKeySequenceEdit
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QKeySequenceEditTest(UsesQApplication):
+ def testKeySequence(self):
+ keySequenceEdit = QKeySequenceEdit()
+ keySequenceEdit.show()
+ QTimer.singleShot(0, keySequenceEdit.close)
+ self.app.exec()
+ print(keySequenceEdit.keySequence())
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qlabel_test.py b/sources/pyside6/tests/QtWidgets/qlabel_test.py
new file mode 100644
index 000000000..aba90b7b8
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qlabel_test.py
@@ -0,0 +1,77 @@
+# 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 cases for QLabel'''
+
+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 Qt
+from PySide6.QtGui import QPixmap
+from PySide6.QtWidgets import QLabel
+from shiboken6 import Shiboken
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QLabelTest(UsesQApplication):
+ '''Test case for calling QLabel.setPixmap'''
+
+ def setUp(self):
+ super(QLabelTest, self).setUp()
+ self.label = QLabel()
+
+ def tearDown(self):
+ del self.label
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(QLabelTest, self).tearDown()
+
+ def testSetPixmap(self):
+
+ p1 = QPixmap(5, 5)
+ p2 = QPixmap(10, 10)
+
+ self.label.setPixmap(p1)
+ self.assertIsNotNone(self.label.pixmap())
+
+ # PYSIDE-150:
+ # When a new QPixmap is assigned to a QLabel,
+ # the previous one needs to be cleared.
+ # This means we should not keep a copy of the QPixmap
+ # on Python-side.
+
+ # Getting pointer to the QPixmap
+ ret_p = self.label.pixmap()
+ self.assertIsNot(p1, ret_p)
+ # Save the address of the pointer
+ ret_p_addr = Shiboken.getCppPointer(ret_p)
+ # Remove the QPixmap
+ del ret_p
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ # Set new QPixmap
+ self.label.setPixmap(p2)
+
+ # There should be no pointers remaining with the same
+ # address that our QPixmap p1 because it was deleted
+ # using `del ret_p`
+ self.assertTrue(all(Shiboken.getCppPointer(o) != ret_p_addr
+ for o in Shiboken.getAllValidWrappers()))
+
+ # Test for PYSIDE-1673, QObject.property() returning a QFlags<> property.
+ def testQObjectProperty(self):
+ a = self.label.property("alignment")
+ self.assertEqual(type(a), Qt.Alignment)
+ print("alignment=", a)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qlayout_ref_test.py b/sources/pyside6/tests/QtWidgets/qlayout_ref_test.py
new file mode 100644
index 000000000..df9bd7f90
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qlayout_ref_test.py
@@ -0,0 +1,171 @@
+# 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 cases for QLayout handling of child widgets references'''
+
+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.QtWidgets import QHBoxLayout, QVBoxLayout, QGridLayout, QWidget
+from PySide6.QtWidgets import QStackedLayout, QFormLayout
+from PySide6.QtWidgets import QApplication, QPushButton, QLabel
+
+from helper.usesqapplication import UsesQApplication
+
+
+class SaveReference(UsesQApplication):
+ '''Test case to check if QLayout-derived classes increment the refcount
+ of widgets passed to addWidget()'''
+
+ # Adding here as nose can't see the qapplication attrib we inherit
+ qapplication = True
+
+ def setUp(self):
+ # Acquire resources
+ super(SaveReference, self).setUp()
+ self.widget1 = QPushButton('click me')
+ self.widget2 = QLabel('aaa')
+
+ def tearDown(self):
+ # Release resources
+ del self.widget2
+ del self.widget1
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(SaveReference, self).tearDown()
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def checkLayoutReference(self, layout):
+ # Checks the reference cound handling of layout.addWidget
+ self.assertEqual(sys.getrefcount(self.widget1), 2)
+ layout.addWidget(self.widget1)
+ self.assertEqual(sys.getrefcount(self.widget1), 3)
+
+ self.assertEqual(sys.getrefcount(self.widget2), 2)
+ layout.addWidget(self.widget2)
+ self.assertEqual(sys.getrefcount(self.widget2), 3)
+
+ # Check if doesn't mess around with previous widget refcount
+ self.assertEqual(sys.getrefcount(self.widget1), 3)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testMoveLayout(self):
+ l = QHBoxLayout()
+ self.assertEqual(sys.getrefcount(self.widget1), 2)
+ l.addWidget(self.widget1)
+ self.assertEqual(sys.getrefcount(self.widget1), 3)
+
+ w = QWidget()
+ w.setLayout(l)
+ self.assertEqual(sys.getrefcount(self.widget1), 3)
+
+ def testHBoxReference(self):
+ # QHBoxLayout.addWidget reference count
+ w = QWidget()
+ self.checkLayoutReference(QHBoxLayout(w))
+
+ def testVBoxReference(self):
+ # QVBoxLayout.addWidget reference count
+ w = QWidget()
+ self.checkLayoutReference(QVBoxLayout(w))
+
+ def testGridReference(self):
+ # QGridLayout.addWidget reference count
+ w = QWidget()
+ self.checkLayoutReference(QGridLayout(w))
+
+ def testFormReference(self):
+ # QFormLayout.addWidget reference count
+ w = QWidget()
+ self.checkLayoutReference(QFormLayout(w))
+
+ def testStackedReference(self):
+ # QStackedLayout.addWidget reference count
+ w = QWidget()
+ self.checkLayoutReference(QStackedLayout(w))
+
+
+class MultipleAdd(UsesQApplication):
+ '''Test case to check if refcount is incremented only once when multiple
+ calls to addWidget are made with the same widget'''
+
+ qapplication = True
+
+ def setUp(self):
+ # Acquire resources
+ super(MultipleAdd, self).setUp()
+ self.widget = QPushButton('click me')
+ self.win = QWidget()
+ self.layout = QHBoxLayout(self.win)
+
+ def tearDown(self):
+ # Release resources
+ del self.widget
+ del self.layout
+ del self.win
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(MultipleAdd, self).tearDown()
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefCount(self):
+ # Multiple QLayout.addWidget calls on the same widget
+ self.assertEqual(sys.getrefcount(self.widget), 2)
+ self.layout.addWidget(self.widget)
+ self.assertEqual(sys.getrefcount(self.widget), 3)
+ self.layout.addWidget(self.widget)
+ self.assertEqual(sys.getrefcount(self.widget), 3)
+ self.layout.addWidget(self.widget)
+ self.assertEqual(sys.getrefcount(self.widget), 3)
+
+
+class InternalAdd(UsesQApplication):
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testInternalRef(self):
+ mw = QWidget()
+ w = QWidget()
+ ow = QWidget()
+
+ topLayout = QGridLayout()
+
+ # unique reference
+ self.assertEqual(sys.getrefcount(w), 2)
+ self.assertEqual(sys.getrefcount(ow), 2)
+
+ topLayout.addWidget(w, 0, 0)
+ topLayout.addWidget(ow, 1, 0)
+
+ # layout keep the referemce
+ self.assertEqual(sys.getrefcount(w), 3)
+ self.assertEqual(sys.getrefcount(ow), 3)
+
+ mainLayout = QGridLayout()
+
+ mainLayout.addLayout(topLayout, 1, 0, 1, 4)
+
+ # the same reference
+ self.assertEqual(sys.getrefcount(w), 3)
+ self.assertEqual(sys.getrefcount(ow), 3)
+
+ mw.setLayout(mainLayout)
+
+ # now trasfer the ownership to mw
+ self.assertEqual(sys.getrefcount(w), 3)
+ self.assertEqual(sys.getrefcount(ow), 3)
+
+ del mw
+
+ # remove the ref and invalidate the widget
+ self.assertEqual(sys.getrefcount(w), 2)
+ self.assertEqual(sys.getrefcount(ow), 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qlayout_test.py b/sources/pyside6/tests/QtWidgets/qlayout_test.py
new file mode 100644
index 000000000..cc41f78b1
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qlayout_test.py
@@ -0,0 +1,139 @@
+# 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 helper.usesqapplication import UsesQApplication
+from PySide6.QtCore import QTimer
+from PySide6.QtWidgets import (QFormLayout, QHBoxLayout, QLayout, QPushButton,
+ QSpacerItem, QWidget, QWidgetItem)
+
+
+class MyLayout(QLayout):
+ def __init__(self, parent=None):
+ QLayout.__init__(self, parent)
+ self._list = []
+
+ def addItem(self, item):
+ self.add(item)
+
+ def addWidget(self, widget):
+ self.add(QWidgetItem(widget))
+
+ def itemAt(self, index):
+ if index < len(self._list):
+ return self._list[index]
+
+ return None
+
+ def count(self):
+ return len(self._list)
+
+ def add(self, item):
+ self._list.append(item)
+
+
+class MissingItemAtLayout(QLayout):
+ def __init__(self, parent=None):
+ QLayout.__init__(self, parent)
+ self._list = []
+
+ def addItem(self, item):
+ self.add(item)
+
+ def addWidget(self, widget):
+ self.add(QWidgetItem(widget))
+
+ def count(self):
+ return len(self._list)
+
+ def add(self, item):
+ self._list.append(item)
+
+# Test if a layout implemented in python, the QWidget.setLayout works
+# fine because this implement som layout functions used in glue code of
+# QWidget, then in c++ when call a virtual function this need call the QLayout
+# function implemented in python
+
+
+class QLayoutTest(UsesQApplication):
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testOwnershipTransfer(self):
+ b = QPushButton("teste")
+ l = MyLayout()
+
+ l.addWidget(b)
+
+ self.assertEqual(sys.getrefcount(b), 2)
+
+ w = QWidget()
+
+ # transfer ref
+ w.setLayout(l)
+
+ self.assertEqual(sys.getrefcount(b), 3)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testReferenceTransfer(self):
+ b = QPushButton("teste")
+ l = QHBoxLayout()
+
+ # keep ref
+ l.addWidget(b)
+ self.assertEqual(sys.getrefcount(b), 3)
+
+ w = QWidget()
+
+ # transfer ref
+ w.setLayout(l)
+
+ self.assertEqual(sys.getrefcount(b), 3)
+
+ # release ref
+ del w
+
+ self.assertEqual(sys.getrefcount(b), 2)
+
+ def testMissingFunctions(self):
+ w = QWidget()
+ b = QPushButton("test")
+ l = MissingItemAtLayout()
+
+ l.addWidget(b)
+
+ self.assertRaises(RuntimeError, w.setLayout, l)
+
+ def testQFormLayout(self):
+ w = QWidget()
+ formLayout = QFormLayout()
+ spacer = QSpacerItem(100, 30)
+ formLayout.setItem(0, QFormLayout.SpanningRole, spacer)
+ w.setLayout(formLayout)
+ w.show()
+ QTimer.singleShot(10, w.close)
+ self.app.exec()
+ del w
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ # PYSIDE-535: Why do I need to do it twice, here?
+ gc.collect()
+ self.assertRaises(RuntimeError, spacer.isEmpty)
+
+ def testConstructorProperties(self):
+ """PYSIDE-1986, test passing properties to the constructor of
+ QHBoxLayout, which does not have default arguments."""
+ layout = QHBoxLayout(objectName="layout", spacing=30)
+ self.assertEqual(layout.spacing(), 30)
+ self.assertEqual(layout.objectName(), "layout")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qlcdnumber_test.py b/sources/pyside6/tests/QtWidgets/qlcdnumber_test.py
new file mode 100644
index 000000000..bc186f755
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qlcdnumber_test.py
@@ -0,0 +1,33 @@
+# 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.QtWidgets import QApplication, QLCDNumber
+
+
+class QLCDNumberOverflow(unittest.TestCase):
+ '''Test case for unhandled overflow on QLCDNumber() numDigits argument (see bug #215).'''
+
+ def assertRaises(self, *args, **kwds):
+ if not hasattr(sys, "pypy_version_info"):
+ # PYSIDE-535: PyPy complains "Fatal RPython error: NotImplementedError"
+ return super().assertRaises(*args, **kwds)
+
+ def setUp(self):
+ self.app = QApplication([])
+
+ def testnumDigitsOverflow(self):
+ # NOTE: PyQt4 raises TypeError, but boost.python raises OverflowError
+ self.assertRaises(OverflowError, QLCDNumber, 840835495615213080)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qlistwidget_test.py b/sources/pyside6/tests/QtWidgets/qlistwidget_test.py
new file mode 100644
index 000000000..377e63ffb
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qlistwidget_test.py
@@ -0,0 +1,77 @@
+# 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, QTimer, Qt
+from PySide6.QtWidgets import QListWidget, QListWidgetItem
+from helper.usesqapplication import UsesQApplication
+
+
+class QListWidgetTest(UsesQApplication):
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def populateList(self, lst):
+ o = QObject()
+ o.setObjectName("obj")
+
+ item = QListWidgetItem("item0")
+ item.setData(Qt.UserRole, o)
+ # item._data = o
+ self.assertTrue(sys.getrefcount(o), 3)
+ self.assertTrue(sys.getrefcount(item), 2)
+ lst.addItem(item)
+ self.assertTrue(sys.getrefcount(item), 3)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def checkCurrentItem(self, lst):
+ item = lst.currentItem()
+ self.assertTrue(sys.getrefcount(item), 3)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def checkItemData(self, lst):
+ item = lst.currentItem()
+ o = item.data(Qt.UserRole)
+ self.assertTrue(sys.getrefcount(o), 4)
+ self.assertEqual(o, item._data)
+ self.assertTrue(sys.getrefcount(o), 2)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testConstructorWithParent(self):
+ lst = QListWidget()
+ self.populateList(lst)
+ self.checkCurrentItem(lst)
+ i = lst.item(0)
+ self.assertTrue(sys.getrefcount(i), 3)
+
+ del lst
+ self.assertTrue(sys.getrefcount(i), 2)
+ del i
+
+ def testIt(self):
+ lst = QListWidget()
+ lst.show()
+ slot = lambda: lst.removeItemWidget(lst.currentItem())
+ lst.addItem(QListWidgetItem("foo"))
+ QTimer.singleShot(0, slot)
+ QTimer.singleShot(0, lst.close)
+ self.app.exec()
+ self.assertEqual(lst.count(), 1)
+
+ def testClear(self):
+ lst = QListWidget()
+ lst.addItem("foo")
+ item = lst.item(0)
+ self.assertIsNone(lst.clear())
+ self.assertRaises(RuntimeError, lambda: item.text())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qlistwidgetitem_test.py b/sources/pyside6/tests/QtWidgets/qlistwidgetitem_test.py
new file mode 100644
index 000000000..a85c1b48f
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qlistwidgetitem_test.py
@@ -0,0 +1,42 @@
+# 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.QtWidgets import QListWidget, QListWidgetItem
+from helper.usesqapplication import UsesQApplication
+
+
+class QListWidgetItemConstructor(UsesQApplication):
+
+ def setUp(self):
+ super(QListWidgetItemConstructor, self).setUp()
+ self.widgetList = QListWidget()
+
+ def tearDown(self):
+ del self.widgetList
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(QListWidgetItemConstructor, self).tearDown()
+
+ def testConstructorWithParent(self):
+ # Bug 235 - QListWidgetItem constructor not saving ownership
+ QListWidgetItem(self.widgetList)
+ item = self.widgetList.item(0)
+ self.assertEqual(item.listWidget(), self.widgetList)
+
+ def testConstructorWithNone(self):
+ # Bug 452 - QListWidgetItem() not casting NoneType to null correctly.
+ item = QListWidgetItem(None, 123)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qmainwindow_test.py b/sources/pyside6/tests/QtWidgets/qmainwindow_test.py
new file mode 100644
index 000000000..2f245c8ff
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qmainwindow_test.py
@@ -0,0 +1,97 @@
+# 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
+import weakref
+
+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 QTimer
+from PySide6.QtWidgets import QMainWindow, QPushButton, QToolButton, QWidget
+from helper.usesqapplication import UsesQApplication
+
+
+class MainWindow(QMainWindow):
+ def __init__(self):
+ super().__init__()
+
+ self.createToolbar()
+
+ def createToolbar(self):
+ pointerButton = QToolButton()
+ pointerToolbar = self.addToolBar("Pointer type")
+ pointerToolbar.addWidget(pointerButton)
+
+
+class MyButton(QPushButton):
+ def __init__(self, parent=None):
+ super().__init__()
+ self._called = False
+
+ def myCallback(self):
+ self._called = True
+
+
+class TestMainWindow(UsesQApplication):
+
+ def testCreateToolbar(self):
+ w = MainWindow()
+ w.show()
+ QTimer.singleShot(1000, self.app.quit)
+ self.app.exec()
+
+ def objDel(self, obj):
+ self.app.quit()
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefCountToNull(self):
+ w = QMainWindow()
+ c = QWidget()
+ self.assertEqual(sys.getrefcount(c), 2)
+ w.setCentralWidget(c)
+ self.assertEqual(sys.getrefcount(c), 3)
+ wr = weakref.ref(c, self.objDel)
+ w.setCentralWidget(None)
+ c = None
+ self.app.exec()
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefCountToAnother(self):
+ w = QMainWindow()
+ c = QWidget()
+ self.assertEqual(sys.getrefcount(c), 2)
+ w.setCentralWidget(c)
+ self.assertEqual(sys.getrefcount(c), 3)
+
+ c2 = QWidget()
+ w.setCentralWidget(c2)
+ self.assertEqual(sys.getrefcount(c2), 3)
+
+ wr = weakref.ref(c, self.objDel)
+ w.setCentralWidget(None)
+ c = None
+
+ self.app.exec()
+
+ def testSignalDisconect(self):
+ w = QMainWindow()
+ b = MyButton("button")
+ b.clicked.connect(b.myCallback)
+ w.setCentralWidget(b)
+
+ b = MyButton("button")
+ b.clicked.connect(b.myCallback)
+ w.setCentralWidget(b)
+
+ b.click()
+ self.assertEqual(b._called, True)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qmenu_test.py b/sources/pyside6/tests/QtWidgets/qmenu_test.py
new file mode 100644
index 000000000..a6976a637
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qmenu_test.py
@@ -0,0 +1,76 @@
+# 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.QtWidgets import QMenu
+from PySide6.QtGui import QKeySequence, QIcon
+from PySide6.QtCore import SLOT
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QMenuAddAction(UsesQApplication):
+
+ def setUp(self):
+ super(QMenuAddAction, self).setUp()
+ self.menu = QMenu()
+
+ def tearDown(self):
+ del self.menu
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(QMenuAddAction, self).tearDown()
+
+ def testAddActionWithoutKeySequenceCallable(self):
+ # bug #280
+ action = self.menu.addAction(self.app.tr('aaa'), lambda: 1)
+
+ def testAddActionKeySequenceCallable(self):
+ # bug #228
+ action = self.menu.addAction(self.app.tr('aaa'), lambda: 1,
+ QKeySequence(self.app.tr('Ctrl+O')))
+
+ def testAddActionKeySequenceSlot(self):
+ action = self.menu.addAction('Quit', self.app, SLOT('quit()'),
+ QKeySequence('Ctrl+O'))
+
+
+class QMenuAddActionWithIcon(UsesQApplication):
+
+ def setUp(self):
+ super(QMenuAddActionWithIcon, self).setUp()
+ self.menu = QMenu()
+ self.icon = QIcon()
+
+ def tearDown(self):
+ del self.menu
+ del self.icon
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(QMenuAddActionWithIcon, self).tearDown()
+
+ def testAddActionWithoutKeySequenceCallable(self):
+ # bug #280
+ action = self.menu.addAction(self.icon, self.app.tr('aaa'), lambda: 1)
+
+ def testAddActionKeySequenceCallable(self):
+ # bug #228
+ action = self.menu.addAction(self.icon, self.app.tr('aaa'), lambda: 1,
+ QKeySequence(self.app.tr('Ctrl+O')))
+
+ def testAddActionKeySequenceSlot(self):
+ action = self.menu.addAction(self.icon, 'Quit', self.app, SLOT('quit()'),
+ QKeySequence('Ctrl+O'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qmenuadd_test.py b/sources/pyside6/tests/QtWidgets/qmenuadd_test.py
new file mode 100644
index 000000000..5b42e755f
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qmenuadd_test.py
@@ -0,0 +1,33 @@
+# 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 the QMenu.addAction() method'''
+
+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.QtWidgets import QMenu
+from helper.usesqapplication import UsesQApplication
+
+
+class QMenuAddAction(UsesQApplication):
+
+ def openFile(self, *args):
+ self.arg = args
+
+ def testQMenuAddAction(self):
+ fileMenu = QMenu("&File")
+
+ addNewAction = fileMenu.addAction("&Open...", self.openFile)
+ addNewAction.trigger()
+ self.assertEqual(self.arg, ())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qobject_mi_test.py b/sources/pyside6/tests/QtWidgets/qobject_mi_test.py
new file mode 100644
index 000000000..d90961495
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qobject_mi_test.py
@@ -0,0 +1,51 @@
+# 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 cases for multiple inheritance from 2 QObjects'''
+
+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
+from PySide6.QtGui import QIntValidator, QValidator
+from PySide6.QtWidgets import QWidget
+
+from helper.usesqapplication import UsesQApplication
+
+
+class WidgetValidator(QWidget, QIntValidator):
+ def __init__(self, parent=None):
+ QWidget.__init__(self, parent)
+ QIntValidator.__init__(self, parent)
+
+
+class DoubleQObjectInheritanceTest(UsesQApplication):
+
+ def testDouble(self):
+ '''Double inheritance from QObject classes'''
+
+ obj = WidgetValidator()
+
+ # QObject methods
+ obj.setObjectName('aaaa')
+ self.assertEqual(obj.objectName(), 'aaaa')
+
+ # QWidget methods
+ obj.setVisible(False)
+ self.assertFalse(obj.isVisible())
+
+ # QIntValidator methods
+ state, string, number = obj.validate('aaaa', 0)
+ self.assertEqual(state, QValidator.Invalid)
+ state, string, number = obj.validate('33', 0)
+ self.assertEqual(state, QValidator.Acceptable)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qpicture_test.py b/sources/pyside6/tests/QtWidgets/qpicture_test.py
new file mode 100644
index 000000000..b81713b57
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qpicture_test.py
@@ -0,0 +1,48 @@
+# 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 QTimer
+from PySide6.QtGui import QPicture, QPainter
+from PySide6.QtWidgets import QWidget
+
+
+class MyWidget(QWidget):
+ def paintEvent(self, e):
+ with QPainter(self) as p:
+ p.drawPicture(0, 0, self._picture)
+ self._app.quit()
+
+
+class QPictureTest(UsesQApplication):
+ def testFromData(self):
+ picture = QPicture()
+ with QPainter(picture) as painter:
+ painter.drawEllipse(10, 20, 80, 70)
+
+ data = picture.data()
+ picture2 = QPicture()
+ picture2.setData(data)
+
+ self.assertEqual(picture2.data(), picture.data())
+
+ w = MyWidget()
+ w._picture = picture2
+ w._app = self.app
+
+ QTimer.singleShot(300, w.show)
+ self.app.exec()
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qpushbutton_test.py b/sources/pyside6/tests/QtWidgets/qpushbutton_test.py
new file mode 100644
index 000000000..bfc04130e
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qpushbutton_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 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.QtWidgets import QPushButton, QMenu, QWidget
+from PySide6.QtCore import QTimer, Qt
+
+
+class MyWidget(QWidget):
+ def __init__(self):
+ super().__init__()
+
+ m = QMenu(self)
+ b = QPushButton("Hello", self)
+ b.setMenu(m)
+
+
+class QPushButtonTest(UsesQApplication):
+ def createMenu(self, button):
+ m = QMenu()
+ button.setMenu(m)
+
+ def testSetMenu(self):
+ w = MyWidget()
+ w.show()
+
+ timer = QTimer.singleShot(100, self.app.quit)
+ self.app.exec()
+
+ def buttonCb(self, checked):
+ self._clicked = True
+
+ def testBoolinSignal(self):
+ b = QPushButton()
+ b.setCheckable(True)
+ b.setShortcut(Qt.Key_A)
+ self._clicked = False
+ b.toggled[bool].connect(self.buttonCb)
+ b.toggle()
+ self.assertTrue(self._clicked)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qsplitter_test.py b/sources/pyside6/tests/QtWidgets/qsplitter_test.py
new file mode 100644
index 000000000..ae383f425
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qsplitter_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)
+
+from PySide6.QtWidgets import QSplitter
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QSplitterTest(UsesQApplication):
+
+ def testGetRange(self):
+ splitter = QSplitter()
+ _min, _max = splitter.getRange(0)
+ self.assertTrue(isinstance(_min, int))
+ self.assertTrue(isinstance(_max, int))
+
+
+if __name__ == "__main__":
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qstyle_test.py b/sources/pyside6/tests/QtWidgets/qstyle_test.py
new file mode 100644
index 000000000..5a9b29dc6
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qstyle_test.py
@@ -0,0 +1,76 @@
+# 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 sys
+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.QtGui import QWindow
+from PySide6.QtWidgets import (QApplication, QFontComboBox, QLabel, QProxyStyle,
+ QStyleFactory, QWidget)
+
+
+class ProxyStyle(QProxyStyle):
+
+ def __init__(self, style):
+ QProxyStyle.__init__(self, style)
+ self.polished = 0
+
+ def polish(self, widget):
+ self.polished = self.polished + 1
+ super(ProxyStyle, self).polish(widget)
+
+
+class SetStyleTest(UsesQApplication):
+ '''Tests setting the same QStyle for all objects in a UI hierarchy.'''
+
+ def testSetStyle(self):
+ '''All this test have to do is not break with some invalid Python wrapper.'''
+
+ def setStyleHelper(widget, style):
+ widget.setStyle(style)
+ widget.setPalette(style.standardPalette())
+ for child in widget.children():
+ if isinstance(child, QWidget):
+ setStyleHelper(child, style)
+
+ container = QWidget()
+ # QFontComboBox is used because it has an QLineEdit created in C++ inside it,
+ # and if the QWidget.setStyle(style) steals the ownership of the style
+ # for the C++ originated widget everything will break.
+ fontComboBox = QFontComboBox(container)
+ label = QLabel(container)
+ label.setText('Label')
+ style = QStyleFactory.create(QStyleFactory.keys()[0])
+ setStyleHelper(container, style)
+
+ def testSetProxyStyle(self):
+ label = QLabel("QtWidgets/ProxyStyle test")
+ baseStyle = QStyleFactory.create(QApplication.instance().style().objectName())
+ self.assertTrue(baseStyle)
+ proxyStyle = ProxyStyle(baseStyle)
+ label.setStyle(proxyStyle)
+ label.show()
+ while not label.windowHandle().isExposed():
+ QApplication.instance().processEvents()
+ self.assertTrue(proxyStyle.polished > 0)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testSetStyleOwnership(self):
+ style = QStyleFactory.create(QStyleFactory.keys()[0])
+ self.assertEqual(sys.getrefcount(style), 2)
+ QApplication.instance().setStyle(style)
+ self.assertEqual(sys.getrefcount(style), 3)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qstyleoption_test.py b/sources/pyside6/tests/QtWidgets/qstyleoption_test.py
new file mode 100644
index 000000000..06798b9e9
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qstyleoption_test.py
@@ -0,0 +1,43 @@
+# 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 sys
+import os
+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.QtWidgets import (QApplication, QCommonStyle, QPushButton)
+
+
+text = ''
+
+
+class Style(QCommonStyle):
+
+ def drawControl(self, element, option, painter, widget=None):
+ # This should be a QStyleOptionButton with a "text" field
+ global text
+ text = option.text
+
+
+class StyleOptionTest(UsesQApplication):
+ '''PYSIDE-1909: Test cast to derived style option classes.'''
+
+ def testStyle(self):
+ global text
+ button = QPushButton("Hello World")
+ button.setStyle(Style())
+ button.show()
+ while not text:
+ QApplication.processEvents()
+ self.assertEqual(text, button.text())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qtableview_test.py b/sources/pyside6/tests/QtWidgets/qtableview_test.py
new file mode 100644
index 000000000..c43666f23
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qtableview_test.py
@@ -0,0 +1,28 @@
+# 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 QAbstractTableModel
+from PySide6.QtWidgets import QTableWidget
+from helper.usesqapplication import UsesQApplication
+
+
+class QPenTest(UsesQApplication):
+
+ def testItemModel(self):
+ tv = QTableWidget()
+
+ self.assertEqual(type(tv.model()), QAbstractTableModel)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qtabwidget_test.py b/sources/pyside6/tests/QtWidgets/qtabwidget_test.py
new file mode 100644
index 000000000..8db45f24b
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qtabwidget_test.py
@@ -0,0 +1,43 @@
+# 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.QtWidgets import QPushButton, QTabWidget
+from helper.timedqapplication import TimedQApplication
+
+
+def makeBug643(tab):
+ button = QPushButton('Foo')
+ tab.insertTab(0, button, 'Foo')
+
+
+class RemoveTabMethod(TimedQApplication):
+ def setUp(self):
+ TimedQApplication.setUp(self)
+ self.tab = QTabWidget()
+
+ def tearDown(self):
+ del self.tab
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ TimedQApplication.tearDown(self)
+
+ def testRemoveTabPresence(self):
+ self.assertTrue(getattr(self.tab, 'removeTab'))
+
+ def testInsertTab(self):
+ makeBug643(self.tab)
+ self.assertEqual(self.tab.count(), 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qtabwidgetclear_test.py b/sources/pyside6/tests/QtWidgets/qtabwidgetclear_test.py
new file mode 100644
index 000000000..49e16e8d2
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qtabwidgetclear_test.py
@@ -0,0 +1,48 @@
+# 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.QtWidgets import QMainWindow, QTabWidget, QTextEdit, QSplitter
+from helper.usesqapplication import UsesQApplication
+
+
+class TabWidgetClear(QMainWindow):
+ def __init__(self):
+ super().__init__()
+ self.tabWidget = QTabWidget(self)
+ self.setCentralWidget(self.tabWidget)
+ self.editBox = QTextEdit(self)
+ self.tabWidget.addTab(self.getSplitter(), 'Test')
+
+ def getSplitter(self):
+ splitter = QSplitter()
+ splitter.addWidget(self.editBox)
+ return splitter
+
+ def toggle(self):
+ self.tabWidget.clear()
+ self.getSplitter()
+
+
+class TestTabWidgetClear(UsesQApplication):
+
+ def testClear(self):
+ self.window = TabWidgetClear()
+ self.window.show()
+ try:
+ self.window.toggle()
+ except RuntimeError as e:
+ # This should never happened, PYSIDE-213
+ raise e
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qtextedit_signal_test.py b/sources/pyside6/tests/QtWidgets/qtextedit_signal_test.py
new file mode 100644
index 000000000..16929f0f2
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qtextedit_signal_test.py
@@ -0,0 +1,50 @@
+# 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 Signal, Slot
+from PySide6.QtWidgets import QMainWindow, QPushButton, QTextEdit
+from helper.usesqapplication import UsesQApplication
+
+
+class MyWindow(QMainWindow):
+ appendText = Signal(str)
+
+ @Slot()
+ def onButtonPressed(self):
+ self.appendText.emit("PySide")
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ self.textEdit = QTextEdit()
+ self.btn = QPushButton("ClickMe")
+ self.btn.clicked.connect(self.onButtonPressed)
+ self.appendText.connect(self.textEdit.append)
+
+ def start(self):
+ self.btn.click()
+
+ def text(self):
+ return self.textEdit.toPlainText()
+
+
+class testSignalWithCPPSlot(UsesQApplication):
+
+ def testEmission(self):
+ w = MyWindow()
+ w.start()
+ self.assertEqual(w.text(), "PySide")
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qtextedit_test.py b/sources/pyside6/tests/QtWidgets/qtextedit_test.py
new file mode 100644
index 000000000..b82350293
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qtextedit_test.py
@@ -0,0 +1,45 @@
+# 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 cases for QTextEdit and ownership problems.'''
+
+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.QtWidgets import QTextEdit
+
+from helper.usesqapplication import UsesQApplication
+
+
+class DontTouchReference(UsesQApplication):
+ '''Check if the QTextTable returned by QTextCursor.insertTable() is not
+ referenced by the QTextCursor that returns it.'''
+
+ def setUp(self):
+ super(DontTouchReference, self).setUp()
+ self.editor = QTextEdit()
+ self.cursor = self.editor.textCursor()
+ self.table = self.cursor.insertTable(1, 1)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testQTextTable(self):
+ # methods which return QTextTable should not increment its reference
+ self.assertEqual(sys.getrefcount(self.table), 2)
+ f = self.cursor.currentFrame()
+ del f
+ self.assertEqual(sys.getrefcount(self.table), 2)
+ # destroying the cursor should not raise any "RuntimeError: internal
+ # C++ object already deleted." when accessing the QTextTable
+ del self.cursor
+ self.assertEqual(sys.getrefcount(self.table), 2)
+ cell = self.table.cellAt(0, 0)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qtoolbar_test.py b/sources/pyside6/tests/QtWidgets/qtoolbar_test.py
new file mode 100644
index 000000000..6fa5865cf
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qtoolbar_test.py
@@ -0,0 +1,50 @@
+# 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 cases for QToolbar'''
+
+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.QtGui import QAction
+from PySide6.QtWidgets import QToolBar, QMainWindow
+
+from helper.usesqapplication import UsesQApplication
+
+
+class AddActionText(UsesQApplication):
+ '''Test case for calling QToolbar.addAction passing a text'''
+
+ def setUp(self):
+ # Acquire resources
+ super(AddActionText, self).setUp()
+ self.window = QMainWindow()
+ self.toolbar = QToolBar()
+ self.window.addToolBar(self.toolbar)
+
+ def tearDown(self):
+ # Release resources
+ super(AddActionText, self).tearDown()
+ del self.toolbar
+ del self.window
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testText(self):
+ # QToolBar.addAction(text) - add a QToolButton
+ self.toolbar.addAction('aaaa')
+ self.assertEqual(len(self.toolbar.actions()), 1)
+ action = self.toolbar.actions()[0]
+ self.assertTrue(isinstance(action, QAction))
+ self.assertEqual(action.text(), 'aaaa')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qtoolbox_test.py b/sources/pyside6/tests/QtWidgets/qtoolbox_test.py
new file mode 100644
index 000000000..d069416b7
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qtoolbox_test.py
@@ -0,0 +1,45 @@
+# 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.QtGui import QIcon
+from PySide6.QtWidgets import QToolBox, QWidget
+
+from helper.usesqapplication import UsesQApplication
+
+
+class OwnershipControl(UsesQApplication):
+
+ def setUp(self):
+ super(OwnershipControl, self).setUp()
+ self.toolbox = QToolBox()
+
+ def tearDown(self):
+ del self.toolbox
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(OwnershipControl, self).tearDown()
+
+ def testAddItem(self):
+ # Was losing ownership of the widget.
+ index = self.toolbox.addItem(QWidget(), 'item')
+ item = self.toolbox.widget(index)
+ self.assertTrue(isinstance(item, QWidget))
+
+ def testAddItemWithIcon(self):
+ index = self.toolbox.addItem(QWidget(), QIcon(), 'item')
+ item = self.toolbox.widget(index)
+ self.assertTrue(isinstance(item, QWidget))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qtreeview_test.py b/sources/pyside6/tests/QtWidgets/qtreeview_test.py
new file mode 100644
index 000000000..fd535bfad
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qtreeview_test.py
@@ -0,0 +1,84 @@
+# 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.QtGui import QStandardItemModel
+from PySide6.QtWidgets import (QWidget, QTreeView, QVBoxLayout,
+ QStyledItemDelegate, QHeaderView)
+from PySide6.QtCore import Qt
+from helper.usesqapplication import UsesQApplication
+
+
+class Widget(QWidget):
+ def __init__(self, parent=None):
+ QWidget.__init__(self, parent)
+ self.treeView = QTreeView(self)
+ layout = QVBoxLayout()
+ layout.addWidget(self.treeView)
+ self.setLayout(layout)
+ self.treeView.setModel(QStandardItemModel())
+
+ self.treeView.model().setHorizontalHeaderLabels(('3', '1', '5'))
+
+
+class QWidgetTest(UsesQApplication):
+
+ def testDelegates(self):
+ widget = Widget()
+ t = widget.treeView
+
+ # When calling setItemDelegateForColumn using a separate variable
+ # for the second argument (QAbstractItemDelegate), there was no problem
+ # on keeping the reference to this object, since the variable was kept
+ # alive (case A)
+ # Contrary, when instantiating this argument on the function call
+ # Using QStyledItemDelegate inside the call the reference of the
+ # object was lost, causing a segfault. (case B)
+
+ # Case A
+ d = QStyledItemDelegate()
+ # Using QStyledItemDelegate from a variable so we keep the reference alive
+ # and we encounter no segfault.
+ t.setItemDelegateForColumn(0, d)
+ # This raised the Segmentation Fault too, because manually destroying
+ # the object caused a missing refrence.
+ del d
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ # Getting the delegates
+ a = t.itemDelegateForColumn(0)
+ self.assertIsInstance(a, QStyledItemDelegate)
+
+ # Case B
+ t.setItemDelegateForColumn(1, QStyledItemDelegate())
+
+ # Getting the delegates
+ b = t.itemDelegateForColumn(1)
+ self.assertIsInstance(b, QStyledItemDelegate)
+
+ # Test for Rows
+ t.setItemDelegateForRow(0, QStyledItemDelegate())
+ self.assertIsInstance(t.itemDelegateForRow(0), QStyledItemDelegate)
+
+ # Test for general delegate
+ t.setItemDelegate(QStyledItemDelegate())
+ self.assertIsInstance(t.itemDelegate(), QStyledItemDelegate)
+
+ def testHeader(self):
+ tree = QTreeView()
+ tree.setHeader(QHeaderView(Qt.Horizontal))
+ self.assertIsNotNone(tree.header())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qtreewidget_test.py b/sources/pyside6/tests/QtWidgets/qtreewidget_test.py
new file mode 100644
index 000000000..6c2db32b9
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qtreewidget_test.py
@@ -0,0 +1,48 @@
+# 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.QtWidgets import QTreeWidget, QTreeWidgetItem, QPushButton
+from helper.usesqapplication import UsesQApplication
+
+
+class QTreeWidgetTest(UsesQApplication):
+
+ # PYSIDE-73:
+ # There was a problem when adding items to a QTreeWidget
+ # when the Widget was being build on the method call instead
+ # of as a separate variable.
+ # The problem was there was not ownership transfer, so the
+ # QTreeWidget did not own the QWidget element
+ def testSetItemWidget(self):
+
+ treeWidget = QTreeWidget()
+ treeWidget.setColumnCount(2)
+
+ item = QTreeWidgetItem(['text of column 0', ''])
+ treeWidget.insertTopLevelItem(0, item)
+ # Adding QPushButton inside the method
+ treeWidget.setItemWidget(item, 1,
+ QPushButton('Push button on column 1'))
+
+ # Getting the widget back
+ w = treeWidget.itemWidget(treeWidget.itemAt(0, 1), 1)
+ self.assertIsInstance(w, QPushButton)
+
+ p = QPushButton('New independent button')
+ # Adding QPushButton object from variable
+ treeWidget.setItemWidget(item, 0, p)
+ w = treeWidget.itemWidget(treeWidget.itemAt(0, 0), 0)
+ self.assertIsInstance(w, QPushButton)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qtreewidgetitem_test.py b/sources/pyside6/tests/QtWidgets/qtreewidgetitem_test.py
new file mode 100644
index 000000000..432aba2ed
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qtreewidgetitem_test.py
@@ -0,0 +1,47 @@
+#!/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
+
+"""
+Unit tests for QTreeWidgetItem
+------------------------------
+
+This test is actually meant for all types which provide `tp_richcompare`
+but actually define something without providing `==` or `!=` operators.
+QTreeWidgetItem for instance defines `<` only.
+
+PYSIDE-74: We redirect to type `object`s handling which is anyway the default
+ when `tp_richcompare` is undefined.
+"""
+
+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 QTimer
+from PySide6.QtWidgets import QApplication, QTreeWidget, QTreeWidgetItem
+
+
+class QTreeWidgetItemTest(unittest.TestCase):
+ def testClass(self):
+ app = QApplication([])
+ treewidget = QTreeWidget()
+ item = QTreeWidgetItem(["Words and stuff"])
+ item2 = QTreeWidgetItem(["More words!"])
+ treewidget.insertTopLevelItem(0, item)
+
+ dummy_list = ["Numbers", "Symbols", "Spam"]
+ self.assertFalse(item in dummy_list)
+ self.assertTrue(item not in dummy_list)
+ self.assertFalse(item == item2)
+ self.assertTrue(item != item2)
+
+
+if __name__ == "__main__":
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qvariant_test.py b/sources/pyside6/tests/QtWidgets/qvariant_test.py
new file mode 100644
index 000000000..fe0266309
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qvariant_test.py
@@ -0,0 +1,142 @@
+# 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 Qt, QObject
+from PySide6.QtWidgets import (QComboBox, QGraphicsScene,
+ QGraphicsRectItem)
+
+from helper.usesqapplication import UsesQApplication
+
+
+class MyDiagram(QGraphicsScene):
+ pass
+
+
+class MyItem(QGraphicsRectItem):
+ def itemChange(self, change, value):
+ return value
+
+
+class Sequence(object):
+ # Having the __getitem__ method on a class transform the Python
+ # type to a PySequence.
+ # Before the patch: aa75437f9119d997dd290471ac3e2cc88ca88bf1
+ # "Fix QVariant conversions when using PySequences"
+ # one could not use an object from this class, because internally
+ # we were requiring that the PySequence was finite.
+ def __getitem__(self, key):
+ raise IndexError()
+
+
+class QGraphicsSceneOnQVariantTest(UsesQApplication):
+ """Test storage ot QGraphicsScene into QVariants"""
+ def setUp(self):
+ super(QGraphicsSceneOnQVariantTest, self).setUp()
+ self.s = MyDiagram()
+ self.i = MyItem()
+ self.combo = QComboBox()
+
+ def tearDown(self):
+ del self.s
+ del self.i
+ del self.combo
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(QGraphicsSceneOnQVariantTest, self).tearDown()
+
+ def testIt(self):
+ self.s.addItem(self.i)
+ self.assertEqual(len(self.s.items()), 1)
+
+ def testSequence(self):
+ # PYSIDE-641
+ self.combo.addItem("test", userData=Sequence())
+ self.assertTrue(isinstance(self.combo.itemData(0), Sequence))
+
+
+class QVariantConversionTest(UsesQApplication):
+ """
+ Tests conversion from QVariant to supported type held by QVariant
+ """
+ def setUp(self):
+ super(QVariantConversionTest, self).setUp()
+ self.obj = QObject()
+
+ def tearDown(self):
+ del self.obj
+ super(QVariantConversionTest, self).tearDown()
+
+ def testEnum(self):
+ """
+ PYSIDE-1798: Test enum is obtained correctly when return through QVariant
+ """
+ self.obj.setProperty("test", Qt.SolidLine)
+ self.assertTrue(isinstance(self.obj.property("test"), Qt.PenStyle))
+ self.assertEqual(self.obj.property("test"), Qt.SolidLine)
+
+ def testString(self):
+ self.obj.setProperty("test", "test")
+ self.assertEqual(self.obj.property("test"), "test")
+ self.assertTrue(isinstance(self.obj.property("test"), str))
+
+ def testBytes(self):
+ byte_message = bytes("test", 'utf-8')
+ self.obj.setProperty("test", byte_message)
+ self.assertEqual(self.obj.property("test"), byte_message)
+ self.assertTrue(isinstance(self.obj.property("test"), bytes))
+
+ def testBasicTypes(self):
+ #bool
+ self.obj.setProperty("test", True)
+ self.assertEqual(self.obj.property("test"), True)
+ self.assertTrue(isinstance(self.obj.property("test"), bool))
+ #long
+ self.obj.setProperty("test", 2)
+ self.assertEqual(self.obj.property("test"), 2)
+ self.assertTrue(isinstance(self.obj.property("test"), int))
+ #float
+ self.obj.setProperty("test", 2.5)
+ self.assertEqual(self.obj.property("test"), 2.5)
+ self.assertTrue(isinstance(self.obj.property("test"), float))
+ #None
+ self.obj.setProperty("test", None)
+ self.assertEqual(self.obj.property("test"), None)
+
+ def testContainerTypes(self):
+ #list
+ self.obj.setProperty("test", [1, 2, 3])
+ self.assertEqual(self.obj.property("test"), [1, 2, 3])
+ self.assertTrue(isinstance(self.obj.property("test"), list))
+ #dict
+ self.obj.setProperty("test", {1: "one"})
+ self.assertEqual(self.obj.property("test"), {1: "one"})
+ self.assertTrue(isinstance(self.obj.property("test"), dict))
+
+ def testPyObject(self):
+ class Test:
+ pass
+ test = Test()
+ self.obj.setProperty("test", test)
+ self.assertEqual(self.obj.property("test"), test)
+ self.assertTrue(isinstance(self.obj.property("test"), Test))
+
+ def testQMetaPropertyWrite(self):
+ combo_box = QComboBox()
+ meta_obj = combo_box.metaObject()
+ i = meta_obj.indexOfProperty("sizeAdjustPolicy")
+ success = meta_obj.property(i).write(combo_box, QComboBox.SizeAdjustPolicy.AdjustToContents)
+ self.assertTrue(success)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/qwidget_setlayout_test.py b/sources/pyside6/tests/QtWidgets/qwidget_setlayout_test.py
new file mode 100644
index 000000000..1d9128789
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qwidget_setlayout_test.py
@@ -0,0 +1,44 @@
+#!/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.QtWidgets import QWidget, QVBoxLayout, QPushButton, QApplication, QHBoxLayout
+from helper.usesqapplication import UsesQApplication
+
+
+class QWidgetTest(UsesQApplication):
+
+ def test_setLayout(self):
+ layout = QVBoxLayout()
+ btn1 = QPushButton("button_v1")
+ layout.addWidget(btn1)
+
+ btn2 = QPushButton("button_v2")
+ layout.addWidget(btn2)
+
+ layout2 = QHBoxLayout()
+
+ btn1 = QPushButton("button_h1")
+ layout2.addWidget(btn1)
+
+ btn2 = QPushButton("button_h2")
+ layout2.addWidget(btn2)
+
+ layout.addLayout(layout2)
+
+ widget = QWidget()
+ widget.setLayout(layout)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/qwidget_test.py b/sources/pyside6/tests/QtWidgets/qwidget_test.py
new file mode 100644
index 000000000..2d503f0d4
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/qwidget_test.py
@@ -0,0 +1,61 @@
+# 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 sys
+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.QtWidgets import QWidget, QMainWindow
+from helper.usesqapplication import UsesQApplication
+
+
+class QWidgetInherit(QMainWindow):
+ def __init__(self):
+ QWidget.__init__(self) # Intended: Initialize QWidget instead of base
+
+
+class NativeEventTestWidget(QWidget):
+
+ nativeEventCount = 0
+
+ def __init__(self):
+ super().__init__()
+
+ def nativeEvent(self, eventType, message):
+ self.nativeEventCount = self.nativeEventCount + 1
+ return [False, 0]
+
+
+class QWidgetTest(UsesQApplication):
+
+ def testInheritance(self):
+ self.assertRaises(TypeError, QWidgetInherit)
+
+
+class QWidgetVisible(UsesQApplication):
+
+ def testBasic(self):
+ # Also related to bug #244, on existence of setVisible'''
+ widget = NativeEventTestWidget()
+ self.assertTrue(not widget.isVisible())
+ widget.setVisible(True)
+ self.assertTrue(widget.isVisible())
+ self.assertTrue(widget.winId() != 0)
+ # skip this test on macOS since no native events are received
+ if sys.platform == 'darwin':
+ return
+ for i in range(10):
+ if widget.nativeEventCount > 0:
+ break
+ self.app.processEvents()
+ self.assertTrue(widget.nativeEventCount > 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/reference_count_test.py b/sources/pyside6/tests/QtWidgets/reference_count_test.py
new file mode 100644
index 000000000..b7d3908dd
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/reference_count_test.py
@@ -0,0 +1,84 @@
+# 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 cases for Reference count when the object is created in c++ side'''
+
+import gc
+import os
+import sys
+import unittest
+import weakref
+
+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 Qt, QPointF
+from PySide6.QtGui import QPolygonF
+from PySide6.QtWidgets import QApplication, QGraphicsScene, QGraphicsRectItem, QGraphicsPolygonItem, QGraphicsRectItem
+
+from helper.usesqapplication import UsesQApplication
+
+destroyedRect = False
+destroyedPol = False
+
+
+def rect_del(o):
+ global destroyedRect
+ destroyedRect = True
+
+
+def pol_del(o):
+ global destroyedPol
+ destroyedPol = True
+
+
+class ReferenceCount(UsesQApplication):
+
+ def setUp(self):
+ super(ReferenceCount, self).setUp()
+ self.scene = QGraphicsScene()
+
+ def tearDown(self):
+ super(ReferenceCount, self).tearDown()
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def beforeTest(self):
+ points = [QPointF(0, 0), QPointF(100, 100), QPointF(0, 100)]
+ pol = self.scene.addPolygon(QPolygonF(points))
+ self.assertTrue(isinstance(pol, QGraphicsPolygonItem))
+ self.wrp = weakref.ref(pol, pol_del)
+
+ # refcount need be 3 because one ref for QGraphicsScene, and one to rect obj
+ self.assertEqual(sys.getrefcount(pol), 3)
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testReferenceCount(self):
+ global destroyedRect
+ global destroyedPol
+
+ self.beforeTest()
+
+ rect = self.scene.addRect(10.0, 10.0, 10.0, 10.0)
+ self.assertTrue(isinstance(rect, QGraphicsRectItem))
+
+ self.wrr = weakref.ref(rect, rect_del)
+
+ # refcount need be 3 because one ref for QGraphicsScene, and one to rect obj
+ self.assertEqual(sys.getrefcount(rect), 3)
+
+ del rect
+ # not destroyed because one ref continue in QGraphicsScene
+ self.assertEqual(destroyedRect, False)
+ self.assertEqual(destroyedPol, False)
+
+ del self.scene
+
+ # QGraphicsScene was destroyed and this destroy internal ref to rect
+ self.assertEqual(destroyedRect, True)
+ self.assertEqual(destroyedPol, True)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/sample.png b/sources/pyside6/tests/QtWidgets/sample.png
new file mode 100644
index 000000000..60450f0dc
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/sample.png
Binary files differ
diff --git a/sources/pyside6/tests/QtWidgets/signature_test.py b/sources/pyside6/tests/QtWidgets/signature_test.py
new file mode 100644
index 000000000..f156b6717
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/signature_test.py
@@ -0,0 +1,59 @@
+# 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 inspect
+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.QtCore
+import PySide6.QtWidgets
+from PySide6.support.signature import get_signature
+
+
+class PySideSignatureTest(unittest.TestCase):
+ def testSignatureExist(self):
+ t1 = type(get_signature(PySide6.QtCore.QObject.children))
+ self.assertEqual(t1, inspect.Signature)
+ t2 = type(get_signature(PySide6.QtCore.QObject.__dict__["children"]))
+ self.assertEqual(t2, t1)
+ obj = PySide6.QtWidgets.QApplication.palette
+ t3 = type(get_signature(obj))
+ self.assertEqual(t3, list)
+ self.assertEqual(len(get_signature(obj)), 3)
+ for thing in get_signature(obj):
+ self.assertEqual(type(thing), inspect.Signature)
+ sm = PySide6.QtWidgets.QApplication.__dict__["palette"]
+ # PYSIDE-1436: staticmethod is a callable since Python 3.10
+ # Instead of checking callable(sm), we check the type:
+ self.assertEqual(type(sm), staticmethod)
+ self.assertTrue(get_signature(sm) is not None)
+
+ def testSignatureIsCached(self):
+ # see if we get the same object
+ ob1 = get_signature(PySide6.QtCore.QObject.children)
+ ob2 = get_signature(PySide6.QtCore.QObject.children)
+ self.assertTrue(ob1 is ob2)
+ # same with multi signature
+ ob1 = get_signature(PySide6.QtWidgets.QApplication.palette)
+ ob2 = get_signature(PySide6.QtWidgets.QApplication.palette)
+ self.assertTrue(ob1 is ob2)
+
+ def testModuleIsInitialized(self):
+ self.assertTrue(get_signature(PySide6.QtWidgets.QApplication) is not None)
+
+ def test_NotCalled_is_callable_and_correct(self):
+ # A signature that has a default value with some "Default(...)"
+ # wrapper is callable and creates an object of the right type.
+ sig = get_signature(PySide6.QtCore.QByteArray().toPercentEncoding)
+ called_default = sig.parameters["exclude"].default()
+ self.assertEqual(type(called_default), PySide6.QtCore.QByteArray)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/QtWidgets/standardpixmap_test.py b/sources/pyside6/tests/QtWidgets/standardpixmap_test.py
new file mode 100644
index 000000000..564f3ff2e
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/standardpixmap_test.py
@@ -0,0 +1,27 @@
+# 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.QtGui import QPixmap
+from PySide6.QtWidgets import QStyle
+
+from helper.usesqapplication import UsesQApplication
+
+
+class StandardPixmapTest(UsesQApplication):
+ def testDefaultOptions(self): # Bug 253
+ pixmap = self.app.style().standardPixmap(QStyle.SP_DirClosedIcon)
+ self.assertTrue(isinstance(pixmap, QPixmap))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/test_module_template.py b/sources/pyside6/tests/QtWidgets/test_module_template.py
new file mode 100644
index 000000000..92661cdff
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/test_module_template.py
@@ -0,0 +1,27 @@
+# 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
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1] / "util"))
+from init_paths import init_test_paths
+init_test_paths()
+
+from PySide6.QtWidgets import QWidget
+from PySide6.QtCore import QObject
+
+
+class MyQObject(QObject):
+ pass
+
+
+class MyQWidget(QWidget):
+ pass
+
+
+class Sentinel():
+ value = 10
+
diff --git a/sources/pyside6/tests/QtWidgets/virtual_protected_inheritance_test.py b/sources/pyside6/tests/QtWidgets/virtual_protected_inheritance_test.py
new file mode 100644
index 000000000..911fed475
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/virtual_protected_inheritance_test.py
@@ -0,0 +1,84 @@
+# 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 cases for overriding inherited protected virtual methods'''
+
+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 QTimerEvent
+from PySide6.QtWidgets import QApplication, QSpinBox
+
+from helper.usesqapplication import UsesQApplication
+
+
+class MySpinButton(QSpinBox):
+ '''Simple example class of overriding QObject.timerEvent'''
+
+ def __init__(self, max_runs=5, app=None):
+ # Creates a new spinbox that will run <max_runs> and quit <app>
+ super().__init__()
+
+ if app is None:
+ app = QApplication([])
+
+ self.app = app
+ self.max_runs = max_runs
+ self.runs = 0
+
+ def timerEvent(self, event):
+ # Timer event method
+ self.runs += 1
+
+ self.setValue(self.runs)
+
+ if self.runs == self.max_runs:
+ self.app.quit()
+
+ if not isinstance(event, QTimerEvent):
+ raise TypeError('Invalid event type. Must be TimerEvent')
+
+
+class TimerEventTest(UsesQApplication):
+ '''Test case for running QObject.timerEvent from inherited class'''
+
+ qapplication = True
+
+ def setUp(self):
+ # Acquire resources
+ super(TimerEventTest, self).setUp()
+ self.widget = MySpinButton(app=self.app)
+
+ def tearDown(self):
+ # Release resources
+ del self.widget
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(TimerEventTest, self).tearDown()
+
+ def testMethod(self):
+ # QWidget.timerEvent overrinding (protected inherited)
+ timer_id = self.widget.startTimer(0)
+
+ self.app.exec()
+
+ self.widget.killTimer(timer_id)
+
+ self.assertTrue(self.widget.runs >= self.widget.max_runs)
+
+
+if __name__ == '__main__':
+ unittest.main()
+ #app = QApplication([])
+ #widget = MySpinButton(app=app)
+ #widget.startTimer(500)
+ #widget.show()
+ #app.exec()
+
diff --git a/sources/pyside6/tests/QtWidgets/virtual_pure_override_test.py b/sources/pyside6/tests/QtWidgets/virtual_pure_override_test.py
new file mode 100644
index 000000000..b7d1e4f3f
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/virtual_pure_override_test.py
@@ -0,0 +1,61 @@
+#!/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.QtWidgets import QGraphicsScene, QGraphicsRectItem, QGraphicsView, QApplication
+from PySide6.QtGui import QBrush, QColor
+from PySide6.QtCore import QTimer
+from helper.usesqapplication import UsesQApplication
+
+qgraphics_item_painted = False
+
+
+class RoundRectItem(QGraphicsRectItem):
+
+ def __init__(self, x, y, w, h):
+ QGraphicsRectItem.__init__(self, x, y, w, h)
+
+ def paint(self, painter, qstyleoptiongraphicsitem, qwidget):
+ global qgraphics_item_painted
+ qgraphics_item_painted = True
+ view = self.scene().views()[0]
+ QTimer.singleShot(20, view.close)
+
+
+class QGraphicsItemTest(UsesQApplication):
+
+ def createRoundRect(self, scene):
+ item = RoundRectItem(10, 10, 100, 100)
+ item.setBrush(QBrush(QColor(255, 0, 0)))
+ scene.addItem(item)
+ return item
+
+ def quit_app(self):
+ self.app.quit()
+
+ def test_setParentItem(self):
+ global qgraphics_item_painted
+
+ scene = QGraphicsScene()
+ scene.addText("test")
+ view = QGraphicsView(scene)
+ view.setWindowTitle("virtual_pure_override_test")
+
+ rect = self.createRoundRect(scene)
+ view.show()
+ self.app.exec()
+ self.assertTrue(qgraphics_item_painted)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/QtWidgets/wrong_return_test.py b/sources/pyside6/tests/QtWidgets/wrong_return_test.py
new file mode 100644
index 000000000..009078ac1
--- /dev/null
+++ b/sources/pyside6/tests/QtWidgets/wrong_return_test.py
@@ -0,0 +1,39 @@
+# 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 cases for Virtual functions with wrong return type'''
+
+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)
+
+from PySide6.QtWidgets import QWidget
+from helper.usesqapplication import UsesQApplication
+
+
+warnings.simplefilter('error')
+
+
+class MyWidget(QWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ def sizeHint(self):
+ pass
+
+
+class testCase(UsesQApplication):
+
+ def testVirtualReturn(self):
+ w = MyWidget()
+ self.assertWarns(RuntimeWarning, w.show)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/QtXml/CMakeLists.txt b/sources/pyside6/tests/QtXml/CMakeLists.txt
new file mode 100644
index 000000000..feb230af3
--- /dev/null
+++ b/sources/pyside6/tests/QtXml/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(qdomdocument_test.py)
diff --git a/sources/pyside6/tests/QtXml/QtXml.pyproject b/sources/pyside6/tests/QtXml/QtXml.pyproject
new file mode 100644
index 000000000..a0c8a9630
--- /dev/null
+++ b/sources/pyside6/tests/QtXml/QtXml.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["qdomdocument_test.py"]
+}
diff --git a/sources/pyside6/tests/QtXml/qdomdocument_test.py b/sources/pyside6/tests/QtXml/qdomdocument_test.py
new file mode 100644
index 000000000..cfc1c543d
--- /dev/null
+++ b/sources/pyside6/tests/QtXml/qdomdocument_test.py
@@ -0,0 +1,82 @@
+#!/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(False)
+
+from PySide6.QtCore import QByteArray
+from PySide6.QtXml import QDomDocument, QDomElement
+
+
+class QDomDocumentTest(unittest.TestCase):
+
+ def setUp(self):
+ self.dom = QDomDocument()
+
+ self.goodXmlData = QByteArray(bytes('''
+ <typesystem package="PySide6.QtXml">
+ <value-type name="QDomDocument"/>
+ <value-type name="QDomElement"/>
+ </typesystem>
+ ''', "UTF-8"))
+
+ self.badXmlData = QByteArray(bytes('''
+ <typesystem package="PySide6.QtXml">
+ <value-type name="QDomDocument">
+ </typesystem>
+ ''', "UTF-8"))
+
+ def tearDown(self):
+ del self.dom
+ del self.goodXmlData
+ del self.badXmlData
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testQDomDocumentSetContentWithBadXmlData(self):
+ '''Sets invalid xml as the QDomDocument contents.'''
+ ok, errorStr, errorLine, errorColumn = self.dom.setContent(self.badXmlData, True)
+ self.assertFalse(ok)
+ self.assertEqual(errorStr, 'Opening and ending tag mismatch.')
+ self.assertEqual(errorLine, 4)
+
+ def testQDomDocumentSetContentWithGoodXmlData(self):
+ '''Sets valid xml as the QDomDocument contents.'''
+ ok, errorStr, errorLine, errorColumn = self.dom.setContent(self.goodXmlData, True)
+ self.assertTrue(ok)
+ self.assertEqual(errorStr, '')
+ self.assertEqual(errorLine, 0)
+ self.assertEqual(errorColumn, 0)
+
+ def testQDomDocumentData(self):
+ '''Checks the QDomDocument elements for the valid xml contents.'''
+
+ def checkAttribute(element, attribute, value):
+ self.assertTrue(isinstance(root, QDomElement))
+ self.assertFalse(element.isNull())
+ self.assertTrue(element.hasAttribute(attribute))
+ self.assertEqual(element.attribute(attribute), value)
+
+ ok, errorStr, errorLine, errorColumn = self.dom.setContent(self.goodXmlData, True)
+ root = self.dom.documentElement()
+ self.assertEqual(root.tagName(), 'typesystem')
+ checkAttribute(root, 'package', 'PySide6.QtXml')
+
+ child = root.firstChildElement('value-type')
+ checkAttribute(child, 'name', 'QDomDocument')
+
+ child = child.nextSiblingElement('value-type')
+ checkAttribute(child, 'name', 'QDomElement')
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/pyside6/tests/init_paths.py b/sources/pyside6/tests/init_paths.py
new file mode 100644
index 000000000..e69ec1c15
--- /dev/null
+++ b/sources/pyside6/tests/init_paths.py
@@ -0,0 +1,78 @@
+# 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
+
+SRC_DIR = os.path.dirname(os.path.abspath(__file__))
+sys.path.append(os.path.join(os.path.dirname(os.path.dirname(SRC_DIR)),
+ 'shiboken6', 'tests'))
+from shiboken_paths import (get_dir_env_var, get_build_dir, add_python_dirs,
+ add_lib_dirs, shiboken_paths)
+
+
+def _get_qt_dir():
+ """Retrieve the location of Qt."""
+ result = None
+ try:
+ result = get_dir_env_var('QT_DIR')
+ except Exception:
+ # This is just a convenience for command line invocation independent
+ # of ctest. Normally, QT_DIR should be set to avoid repetitive patch
+ # searches.
+ print('The environment variable QT_DIR is not set; falling back to path search',
+ file=sys.stderr)
+ qmake = 'qmake.exe' if sys.platform == 'win32' else 'qmake'
+ for path in os.environ.get('PATH').split(os.pathsep):
+ if path and os.path.isfile(os.path.join(path, qmake)):
+ result = os.path.dirname(path)
+ break
+ if not result:
+ raise ValueError('Unable to locate Qt. Please set the environment variable QT_DIR')
+ print(f"Qt as determined by path search: {result}", file=sys.stderr)
+ return result
+
+
+def _get_qt_lib_dir():
+ """Retrieve the location of the Qt library directory."""
+ sub_dir = 'bin' if sys.platform == 'win32' else 'lib'
+ return os.path.join(_get_qt_dir(), sub_dir) # For testbinding
+
+
+def _init_test_paths(shiboken_tests=False, testbindings_module=False):
+ """Sets the correct import paths (Python modules and C++ library paths)
+ for PySide tests and shiboken6 tests using depending on the environment
+ variables BUILD_DIR and QT_DIR pointing to the build directory and
+ Qt directory, respectively."""
+ src_dir = os.path.dirname(os.path.abspath(__file__))
+
+ python_dirs = [os.path.join(src_dir, 'util')] # Helper module
+
+ pyside_build_dir = os.path.join(get_build_dir(), 'pyside6')
+ python_dirs.append(pyside_build_dir) # for PySide6
+ lib_dirs = [os.path.join(pyside_build_dir, 'libpyside'),
+ os.path.join(pyside_build_dir, 'libpysideqml')]
+
+ if testbindings_module:
+ python_dirs.append(os.path.join(pyside_build_dir,
+ 'tests', 'pysidetest'))
+ lib_dirs.append(_get_qt_lib_dir())
+
+ shiboken_path_tuple = shiboken_paths(shiboken_tests)
+ python_dirs.extend(shiboken_path_tuple[0])
+ lib_dirs.extend(shiboken_path_tuple[1])
+
+ add_python_dirs(python_dirs)
+ add_lib_dirs(lib_dirs)
+
+
+def init_test_paths(testbindings_module=False):
+ """Sets the correct import paths for PySide6 tests, optionally including
+ testbindings."""
+ _init_test_paths(False, testbindings_module)
+
+
+def init_all_test_paths():
+ """Sets the correct import paths for PySide6 and shiboken6 tests
+ (for registry checking only)."""
+ _init_test_paths(True, True)
diff --git a/sources/pyside6/tests/mac/CMakeLists.txt b/sources/pyside6/tests/mac/CMakeLists.txt
new file mode 100644
index 000000000..e1eb1a2fd
--- /dev/null
+++ b/sources/pyside6/tests/mac/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(qmacstyle_test.py)
diff --git a/sources/pyside6/tests/mac/qmacstyle_test.py b/sources/pyside6/tests/mac/qmacstyle_test.py
new file mode 100644
index 000000000..18fc64286
--- /dev/null
+++ b/sources/pyside6/tests/mac/qmacstyle_test.py
@@ -0,0 +1,32 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+# Qt5: this is gone: from PySide6.QtGui import QMacStyle
+
+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.QtWidgets import QApplication, QLabel, QStyleFactory
+from PySide6.QtCore import QObject
+
+from helper.usesqapplication import UsesQApplication
+
+
+class QMacStyleTest(UsesQApplication):
+ def setUp(self):
+ UsesQApplication.setUp(self)
+ self.QMacStyle = type(QStyleFactory.create('Macintosh'))
+
+ def testWidgetStyle(self):
+ w = QLabel('Hello')
+ self.assertTrue(isinstance(w.style(), self.QMacStyle))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/manually/README.txt b/sources/pyside6/tests/manually/README.txt
new file mode 100644
index 000000000..da20e3824
--- /dev/null
+++ b/sources/pyside6/tests/manually/README.txt
@@ -0,0 +1,5 @@
+To run these tests is necessary some manuall input (most of then not supported by QTest[1]),
+because of that this is not part of automatic test context.
+
+
+[1]http://bugreports.qt.nokia.com/browse/QTBUG-13397
diff --git a/sources/pyside6/tests/manually/bug_841.py b/sources/pyside6/tests/manually/bug_841.py
new file mode 100644
index 000000000..3911244ce
--- /dev/null
+++ b/sources/pyside6/tests/manually/bug_841.py
@@ -0,0 +1,57 @@
+# 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 sys
+
+from PySide6.QtGui import QStandardItem, QStandardItemModel
+from PySide6.QtWidgets import QMainWindow, QTreeView, QAbstractItemView, QApplication, QMessageBox
+
+
+class Item(QStandardItem):
+ def __init__(self, text):
+ super().__init__()
+ self.setText(text)
+ self.setDragEnabled(True)
+ self.setDropEnabled(True)
+
+ def clone(self):
+ ret = Item(self.text())
+ return ret
+
+
+class Project(QStandardItemModel):
+ def __init__(self):
+ super().__init__()
+ self.setItemPrototype(Item("Prototype"))
+ # add some items so we have stuff to move around
+ self.appendRow(Item("ABC"))
+ self.appendRow(Item("DEF"))
+ self.appendRow(Item("GHI"))
+
+
+class MainWindow(QMainWindow):
+ def __init__(self):
+ super().__init__()
+
+ self.model = Project()
+ self.view = QTreeView(self)
+ self.view.setModel(self.model)
+ self.view.setDragEnabled(True)
+ self.view.setDragDropMode(QAbstractItemView.InternalMove)
+ self.setCentralWidget(self.view)
+
+ def mousePressEvent(self, e):
+ print(e.x(), e.y())
+ return QMainWindow.mousePressEvent(self, e)
+
+
+def main():
+ app = QApplication(sys.argv)
+ w = MainWindow()
+ w.show()
+ QMessageBox.information(None, "Info", "Just drag and drop the items.")
+ sys.exit(app.exec())
+
+
+if __name__ == "__main__":
+ main()
diff --git a/sources/pyside6/tests/manually/lazytiming.py b/sources/pyside6/tests/manually/lazytiming.py
new file mode 100644
index 000000000..59f75bc46
--- /dev/null
+++ b/sources/pyside6/tests/manually/lazytiming.py
@@ -0,0 +1,38 @@
+# Copyright (C) 2024 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
+
+"""
+Time a repeated Python run
+--------------------------
+
+Usage: python3 lazytiming.py # uses PySide6
+ python3 lazytiming.py <any arg> # uses PyQt6
+
+It runs the same python for the testing.
+
+Actually comparing PySide6 and PyQt6 in action:
+
+ PYSIDE6_OPTION_LAZY=0 python3 sources/pyside6/tests/manually/lazytiming.py # normal
+ PYSIDE6_OPTION_LAZY=1 python3 sources/pyside6/tests/manually/lazytiming.py # faster
+ python3 sources/pyside6/tests/manually/lazytiming.py xxx # PyQt
+"""
+import subprocess
+import sys
+
+from timeit import default_timer as timer
+
+repeats = 100
+test1 = "PySide6"
+test2 = "PyQt6"
+
+test = test2 if sys.argv[1:] else test1
+cmd = [sys.executable, "-c", f"from {test} import QtCore, QtGui, QtWidgets"]
+
+print(f"{repeats} * {test}")
+
+subprocess.call(cmd) # warmup
+start_time = timer()
+for idx in range(repeats):
+ subprocess.call(cmd)
+stop_time = timer()
+print(f"time per run = {(stop_time - start_time) / repeats}")
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()
+
diff --git a/sources/pyside6/tests/registry/CMakeLists.txt b/sources/pyside6/tests/registry/CMakeLists.txt
new file mode 100644
index 000000000..02622109a
--- /dev/null
+++ b/sources/pyside6/tests/registry/CMakeLists.txt
@@ -0,0 +1,4 @@
+# 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
+
+PYSIDE_TEST(existence_test.py)
diff --git a/sources/pyside6/tests/registry/existence_test.py b/sources/pyside6/tests/registry/existence_test.py
new file mode 100644
index 000000000..5540b6e04
--- /dev/null
+++ b/sources/pyside6/tests/registry/existence_test.py
@@ -0,0 +1,229 @@
+# 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
+
+"""
+existence_test.py
+-----------------
+
+A test that checks all function signatures if they still exist.
+
+Definition of the rules used:
+=============================
+
+Any entry
+---------
+
+ Exists in file Exists in Binary Result
+ + + ok
+ + - error
+ - + ok
+
+List entry
+----------
+
+ Arity in file Arity in Binary Result
+ n n ok
+ n < n error
+ n > n ok
+
+"""
+
+import os
+import re
+import sys
+from textwrap import dedent
+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 init_platform import enum_all, generate_all
+from util import (isolate_warnings, check_warnings, suppress_warnings, warn,
+ is_ci, qt_version, get_script_dir, get_effective_refpath,
+ get_refpath, import_refmodule)
+from PySide6 import *
+
+refPath = get_refpath()
+effectiveRefPath = get_effective_refpath()
+pyc = os.path.splitext(effectiveRefPath)[0] + ".pyc"
+if os.path.exists(pyc) and not os.path.exists(effectiveRefPath):
+ # on Python2 the pyc file would be imported
+ os.unlink(pyc)
+
+if refPath != effectiveRefPath:
+ print("*** Falling back to ", effectiveRefPath, " since expected ",
+ refPath, " does not exist")
+
+script_dir = get_script_dir()
+shortpath = os.path.relpath(effectiveRefPath, script_dir)
+try:
+ sig_exists = import_refmodule()
+ print("found:", shortpath)
+ have_refmodule = True
+except ImportError:
+ print("*** not found:", shortpath)
+ have_refmodule = False
+except SyntaxError:
+ print("*** not a python file, removed:", shortpath)
+ os.unlink(effectiveRefPath)
+ have_refmodule = False
+except NameError as e:
+ if "recreate" in e.args[0]:
+ print("*** explicit request to recreate:", shortpath)
+ else:
+ print("*** unexpected NameError:", e, "- creating", shortpath)
+ os.unlink(effectiveRefPath)
+ have_refmodule = False
+dict_name = "sig_dict"
+if have_refmodule and not hasattr(sig_exists, dict_name):
+ print(f"*** wrong module without '{dict_name}', removed: {shortpath}")
+ os.unlink(effectiveRefPath)
+ have_refmodule = False
+
+
+class TestUnrecognizedOffending(unittest.TestCase):
+ """
+ We run the signature generation on all modules and raise an error
+ if a warning was issued. This is better than turning warnings into
+ errors because that would stop early before we have all warnings.
+ """
+ def test_signatures_recognized(self):
+ with isolate_warnings():
+ found_sigs = enum_all()
+ if check_warnings():
+ raise RuntimeError("There are errors, see above.")
+
+
+@unittest.skipIf(not have_refmodule,
+ "not activated for this platform or version")
+class TestSignaturesExists(unittest.TestCase):
+ """
+ This is the current simple attempt to support a signature self test.
+ You can activate it for your platform by supplying your own reference
+ file. Simply run init_platform.py and add the generated file to the
+ repository.
+ """
+
+ @staticmethod
+ def _do_the_test(found_sigs):
+
+ def multi_signature_msg(key, actual, expect):
+ len_act = len(actual) if type(actual) is list else 1
+ len_exp = len(expect) if type(expect) is list else 1
+ return (f"multi-signature count mismatch for '{key}'. "
+ f"Actual {len_act} {actual} vs. expected {len_exp} {expect}")
+
+ for key, value in sig_exists.sig_dict.items():
+ name = key.rsplit(".", 1)[-1]
+ if name in ("next", "__next__"): # ignore problematic cases
+ continue
+ if "<" in key:
+ # Skip over remaining crap in "<...>"
+ continue
+ if key.startswith("sample.SampleNamespace"):
+ # We cannot work with sample namespaces after the change to __qualname__.
+ continue
+ if (key.startswith("smart.SharedPtr") or
+ re.match(r"PySide6\..*?\.QSharedPointer_", key)):
+ # These mangled names are not supported.
+ # We should fix them.
+ continue
+ if key not in found_sigs:
+ warn(f"missing key: '{key} value={value}'", stacklevel=3)
+ else:
+ found_val = found_sigs[key]
+ if type(value) is list and (
+ type(found_val) is tuple or
+ len(found_val) < len(value)):
+ # We check that nothing got lost. But it is ok when an older
+ # registry file does not know all variants, yet!
+ warn(multi_signature_msg(key, found_val, value), stacklevel=3)
+
+ def test_signatures(self):
+ found_sigs = enum_all()
+ with isolate_warnings():
+ self._do_the_test(found_sigs)
+ if is_ci and check_warnings():
+ raise RuntimeError("There are errors, see above.")
+
+ def test_error_is_raised(self):
+ found_sigs = enum_all()
+ # Make sure that errors are actually raised.
+ search = list(found_sigs.keys())
+ pos = 42 # arbitrary and historycal, could be 0 as well
+
+ # We try all variants:
+ while type(found_sigs[search[pos]]) is not tuple:
+ pos += 1
+ tuple_key = search[pos]
+ while type(found_sigs[search[pos]]) is not list:
+ pos += 1
+ list_key = search[pos]
+
+ test_sigs = found_sigs.copy()
+ test_sigs.pop(tuple_key)
+ with isolate_warnings(), suppress_warnings():
+ self._do_the_test(test_sigs)
+ self.assertTrue(check_warnings(), "you warn about too few entries")
+
+ test_sigs = found_sigs.copy()
+ test_sigs["whatnot"] = ("nothing", "real")
+ with isolate_warnings(), suppress_warnings():
+ self._do_the_test(test_sigs)
+ self.assertFalse(check_warnings(), "you ignore too many entries")
+
+ test_sigs = found_sigs.copy()
+ repl = test_sigs[list_key]
+ repl.pop(0)
+ test_sigs[list_key] = repl
+ with isolate_warnings(), suppress_warnings():
+ self._do_the_test(test_sigs)
+ # An arity that is now missing is an error.
+ self.assertTrue(check_warnings(), "you warn when arity got smaller")
+
+ test_sigs = found_sigs.copy()
+ repl = test_sigs[list_key]
+ repl = repl[0]
+ assert type(repl) is tuple
+ test_sigs[list_key] = repl
+ with isolate_warnings(), suppress_warnings():
+ self._do_the_test(test_sigs)
+ # An arity that is now missing is an error.
+ self.assertTrue(check_warnings(), "you warn when list degraded to tuple")
+
+ test_sigs = found_sigs.copy()
+ repl = test_sigs[list_key]
+ repl = repl + repl
+ test_sigs[list_key] = repl
+ with isolate_warnings(), suppress_warnings():
+ self._do_the_test(test_sigs)
+ # More arities are ignored, because we might test an older version.
+ self.assertFalse(check_warnings(), "you ignore when arity got bigger")
+
+
+tested_versions = (5, 6), (5, 9), (5, 11), (5, 12), (5, 14)
+
+if not have_refmodule and is_ci and qt_version()[:2] in tested_versions:
+ class TestFor_CI_Init(unittest.TestCase):
+ """
+ This helper class generates the reference file for CI.
+ It creates an output listing that can be used to check
+ the result back in.
+ """
+ generate_all()
+ sys.stderr.flush()
+ print("BEGIN_FILE", shortpath, file=sys.stderr)
+ with open(refPath) as f:
+ print(f.read(), file=sys.stderr)
+ print("END_FILE", shortpath, file=sys.stderr)
+ sys.stderr.flush()
+ raise RuntimeError(dedent("""
+ {line}
+ ** This is the initial call. You should check this file in:
+ ** {}
+ **""").format(shortpath, line=79 * "*"))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/registry/init_platform.py b/sources/pyside6/tests/registry/init_platform.py
new file mode 100644
index 000000000..8abf30216
--- /dev/null
+++ b/sources/pyside6/tests/registry/init_platform.py
@@ -0,0 +1,210 @@
+# 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
+
+"""
+init_platform.py
+
+Existence registry
+==================
+
+This is a registry for all existing function signatures.
+One file is generated with all signatures of a platform and version.
+
+The scope has been extended to generate all signatures from the
+shiboken and pysidetest projects.
+"""
+
+import sys
+import os
+from contextlib import contextmanager
+from textwrap import dedent
+from util import get_refpath, get_script_dir
+
+
+def qt_build():
+ result = '<Unknown build of Qt>'
+ try:
+ from PySide6.QtCore import QLibraryInfo
+ result = QLibraryInfo.build()
+ except:
+ pass
+ return result
+
+
+script_dir = get_script_dir()
+history_dir = os.path.join(script_dir, 'build_history')
+
+# Find out if we have the build dir, already. Then use it.
+look_for = os.path.join("pyside6", "tests", "pysidetest")
+have_build_dir = [x for x in sys.path if x.endswith(look_for)]
+if have_build_dir:
+ all_build_dir = os.path.normpath(os.path.join(have_build_dir[0], "..", "..", ".."))
+elif os.path.exists(history_dir):
+ # Using the last build to find the build dir.
+ # Note: This is not reliable when building in parallel!
+ last_build = max(x for x in os.listdir(history_dir) if x.startswith("20"))
+ fpath = os.path.join(history_dir, last_build, "build_dir.txt")
+ if os.path.exists(fpath):
+ with open(fpath) as f:
+ f_contents = f.read().strip()
+ f_contents_split = f_contents.splitlines()
+ try:
+ all_build_dir = f_contents_split[0]
+ except IndexError:
+ print(f"Error: can't find the build dir in the given file '{fpath}'")
+ sys.exit(1)
+else:
+ print(dedent("""
+ Can't find the build dir in the history.
+ Compile again and don't forget to specify "--build-tests".
+ """))
+ sys.exit(1)
+
+if not os.path.exists(os.path.join(all_build_dir, look_for)):
+ print(dedent("""
+ PySide has not been built with tests enabled.
+ Compile again and don't forget to specify "--build-tests".
+ """))
+ sys.exit(1)
+
+pyside_build_dir = os.path.join(all_build_dir, "pyside6")
+shiboken_build_dir = os.path.join(all_build_dir, "shiboken6")
+
+# now we compute all paths:
+
+
+def set_ospaths(build_dir):
+ ps = os.pathsep
+ ospath_var = "PATH" if sys.platform == "win32" else "LD_LIBRARY_PATH"
+ old_val = os.environ.get(ospath_var, "")
+ lib_path = [os.path.join(build_dir, "pyside6", "tests", "pysidetest"),]
+ ospath = ps.join(lib_path + old_val.split(ps))
+ os.environ[ospath_var] = ospath
+
+
+set_ospaths(all_build_dir)
+
+import PySide6
+
+all_modules = list("PySide6." + _ for _ in PySide6.__all__)
+
+# now we should be able to do all imports:
+if not have_build_dir:
+ sys.path.insert(0, os.path.join(pyside_build_dir, "tests", "pysidetest"))
+import testbinding
+all_modules.append("testbinding")
+
+from shiboken6 import Shiboken
+all_modules.append("shiboken6.Shiboken")
+
+from shibokensupport.signature.lib.enum_sig import SimplifyingEnumerator
+
+# Make sure not to get .pyc in Python2.
+sourcepath = os.path.splitext(__file__)[0] + ".py"
+
+
+class Formatter(object):
+ """
+ Formatter is formatting the signature listing of an enumerator.
+
+ It is written as context managers in order to avoid many callbacks.
+ The separation in formatter and enumerator is done to keep the
+ unrelated tasks of enumeration and formatting apart.
+ """
+ def __init__(self, outfile):
+ self.outfile = outfile
+ self.last_level = 0
+
+ def print(self, *args, **kw):
+ print(*args, file=self.outfile, **kw) if self.outfile else None
+
+ @contextmanager
+ def module(self, mod_name):
+ self.print(f"")
+ self.print(f"# Module {mod_name}")
+ self.print(f"sig_dict.update({{")
+ yield
+ self.print(f' }}) if "{mod_name}" in sys.modules else None')
+
+ @contextmanager
+ def klass(self, class_name, class_str):
+ self.print()
+ self.print(f"# class {self.mod_name}.{class_name}:")
+ yield
+
+ @contextmanager
+ def function(self, func_name, signature):
+ if self.last_level > self.level:
+ self.print()
+ self.last_level = self.level
+ class_name = self.class_name
+ if class_name is None:
+ key = viskey = f"{self.mod_name}.{func_name}"
+ else:
+ key = viskey = f"{self.mod_name}.{class_name}.{func_name}"
+ if key.endswith("lY"):
+ # Some classes like PySide6.QtGui.QContextMenuEvent have functions
+ # globalX and the same with Y. The gerrit robot thinks that this
+ # is a badly written "globally". Convince it by hiding this word.
+ viskey = viskey[:-1] + '""Y'
+ self.print(f' "{viskey}": {signature},')
+ yield key
+
+
+def enum_all():
+ fmt = Formatter(None)
+ enu = SimplifyingEnumerator(fmt)
+ ret = enu.result_type()
+ for mod_name in all_modules:
+ ret.update(enu.module(mod_name))
+ return ret
+
+
+LICENSE_TEXT = """
+# 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
+"""
+
+
+def generate_all():
+ refPath = get_refpath()
+ module = os.path.basename(os.path.splitext(refPath)[0])
+ with open(refPath, "w") as outfile, open(sourcepath) as f:
+ fmt = Formatter(outfile)
+ enu = SimplifyingEnumerator(fmt)
+ lines = f.readlines()
+ license_line = next((lno for lno, line in enumerate(lines)
+ if "$QT_END_LICENSE$" in line))
+ fmt.print("#recreate # uncomment this to enforce generation")
+ fmt.print(LICENSE_TEXT)
+ version = sys.version.replace('\n', ' ')
+ build = qt_build()
+ fmt.print(dedent(f'''\
+ """
+ This file contains the simplified signatures for all functions in PySide
+ for module '{module}' using
+ Python {version}
+ {build}
+
+ There are no default values, no variable names and no self
+ parameter. Only types are present after simplification. The
+ functions 'next' resp. '__next__' are removed to make the output
+ identical for Python 2 and 3. '__div__' is also removed,
+ since it exists in Python 2, only.
+ """
+ '''))
+ fmt.print("import sys")
+ fmt.print("")
+ fmt.print("sig_dict = {}")
+ for mod_name in all_modules:
+ enu.module(mod_name)
+ fmt.print("# eof")
+
+
+def __main__():
+ print(f"+++ generating {get_refpath()}. You should probably check this file in.")
+ generate_all()
+
+
+if __name__ == "__main__":
+ __main__()
diff --git a/sources/pyside6/tests/registry/scrape_testresults.py b/sources/pyside6/tests/registry/scrape_testresults.py
new file mode 100644
index 000000000..b7b6b58aa
--- /dev/null
+++ b/sources/pyside6/tests/registry/scrape_testresults.py
@@ -0,0 +1,338 @@
+# 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
+
+"""
+scrape_testresults.py
+
+Read the testresults website of COIN and find the pages that contain an
+embedded exists_{platform}_{version}_ci.py .
+
+The found pages will then be sorted by date/time and put into the registry.
+
+This program utilizes the multiprocessing package for speedy access to
+the web pages. The program works well in typically less than half an hour.
+
+After the cache has been created, the runtime is substantially smaller.
+
+"""
+
+import sys
+if sys.version_info[:2] < (3, 6):
+ print("This program is written for Python 3.6 or higher.")
+ sys.exit(1)
+
+DEMO_URL = ("https://testresults.qt.io/coin/api/results/pyside/pyside-setup/"
+ # The above URL part is fixed.
+ "30c1193ec56a86b8d0920c325185b9870f96941e/"
+ "MacOSMacOS_10_12x86_64MacOSMacOS_10_12x86_64Clangqtci-macos-"
+ "10.12-x86_64-8-425364DebugAndRelease_Release/"
+ "d80c5d4547ea2b3d74188bd458955aae39cb32b4/"
+ "test_1535865484/"
+ "log.txt.gz")
+
+from bs4 import BeautifulSoup
+from datetime import datetime
+from multiprocessing import Pool
+from textwrap import dedent
+import requests
+import os
+import time
+import re
+import json
+import argparse
+
+my_name = __file__ if __file__.endswith(".py") else __file__[:-1]
+test_path = os.path.join(os.path.dirname(__file__), "testresults", "embedded")
+if not os.path.exists(test_path):
+ os.makedirs(test_path)
+cache_path = os.path.dirname(test_path)
+target_path = os.path.dirname(__file__)
+start_time = time.time()
+
+
+def get_name(url):
+ """
+ Return the last piece of an url, including trailing slash.
+
+ In effect, this undoes the accumulation of URL pieces.
+ """
+ name = url.rstrip("/").rsplit("/", 1)[-1]
+ if url.endswith("/"):
+ name += "/"
+ return name
+
+
+def rel_url(url):
+ """
+ throw the top URL away
+ """
+ return url[len(top_url):]
+
+
+stop_all = False
+
+
+def find_all_links(text, url, ignore=()):
+ """
+ Find all links in a page.
+
+ Only simple links are allowed. That means safe characters and
+ at most one "/" at the end for directories.
+ """
+ global stop_all
+ soup = BeautifulSoup(text, "html.parser")
+ lis = soup.find_all("a")
+ names = list(row["href"] for row in lis)
+ names = list(name for name in names if name not in ignore)
+ for name in names:
+ if not re.match(r"^[A-Za-z0-9_\-.]+/?$", name):
+ print("Unexpected character in link:", name)
+ # Not clear how to terminate the pool quick and clean.
+ # We crash badly in handle_suburl_tup, ugly but works.
+ stop_all = True
+ return []
+ urls = list(url + name for name in names)
+ return urls
+
+
+def read_url(url):
+ # We intentionally let things fail, because we re-run things on failure.
+ try:
+ response = requests.get(url)
+ except requests.exceptions.ContentDecodingError as e:
+ # This is a permanent error which is in the data. We ignore that.
+ print(os.getpid(), "Decoding Error:", e)
+ print(os.getpid(), "Cannot fix this, ignored.")
+ return None
+ except requests.exceptions.RequestException as e:
+ print("Read error:", e)
+ raise
+ else:
+ return response
+
+
+def get_timestamp(text):
+ # agent:2018/06/29 15:02:15
+ global stop_all
+ prefix = "\nagent:"
+ try:
+ startpos = text.index(prefix)
+ except ValueError:
+ print("this is not the usual format of COIN log files")
+ stop_all = True
+ raise
+ startpos += len(prefix)
+ text = text[startpos : startpos + 80]
+ ts = text[:19]
+ ts = re.sub(r'[^0-9]', '_', ts)
+ # check that it is a valid time stamp
+ try:
+ datetime.strptime(ts, "%Y_%m_%d_%H_%M_%S")
+ except ValueError as e:
+ print("Unexpected time stamp", e)
+ stop_all = True
+ raise
+ return ts
+
+
+def write_data(name, text):
+ try:
+ ts = get_timestamp(text)
+ except ValueError:
+ print()
+ print(name)
+ print()
+ print(text)
+ raise
+ lines = text.split("\n")
+ for idx, line in enumerate(lines):
+ if "BEGIN_FILE" in line:
+ start = idx + 1
+ offset = line.index("BEGIN_FILE")
+ if "END_FILE" in line:
+ stop = idx
+ lines = lines[start : stop]
+ if offset:
+ lines = list(line[offset:] for line in lines)
+ # fix the lines - the original has no empty line after "# eof"
+ while lines[-1] == "":
+ lines.pop()
+ text = "\n".join(lines) + "\n"
+ modname = re.search(r"'(..*?)'", text).group(1)
+ fn = os.path.join(test_path, f"{ts}-{name}-{modname}.py")
+ if os.path.exists(fn):
+ # do not change the file, we want to skip it
+ return
+ with open(fn, "w") as f:
+ f.write(text)
+
+
+def eval_data(force=False):
+ """
+ Read all found files, sort them and keep the latest version.
+ """
+ files = []
+ for entry in os.scandir(test_path):
+ if "exists_" in entry.name and entry.name.endswith(".py"):
+ if force or os.path.getmtime(entry.path) >= start_time:
+ # this file is newly created
+ files.append(entry.path)
+ files.sort()
+ # read the files and update in chronological order
+ results = {}
+ for fn in files:
+ with open(fn) as f:
+ text = f.read()
+ modname = re.search("'(..*?)'", text).group(1)
+ results[modname] = text
+ for fn in results:
+ name = os.path.join(target_path, fn + ".py")
+ with open(name, "w") as f:
+ f.write(results[fn])
+ print("+++ generated:", name)
+ return len(results)
+
+
+def handle_suburl(idx, n, url, level):
+ if level == 1:
+ print(os.getpid(), "Reading", idx + 1, "of", n, rel_url(url))
+ response = read_url(url)
+ urls = find_all_links(response.text, url)
+ for sub_url in urls:
+ name = get_name(sub_url)
+ if name.endswith("/"):
+ if name.startswith("build_"):
+ continue
+ if name == "tasks/":
+ continue
+ handle_suburl(0, 0, sub_url, level + 1)
+ else:
+ if name.startswith("log.txt"):
+ test_name = sub_url.split("/")[-2]
+ print(os.getpid(), test_name)
+ response = read_url(sub_url)
+ txt = response.text if response else ''
+ if "BEGIN_FILE" in txt and "'BEGIN_FILE'" not in txt:
+ # find the text, but not a traceback with that text
+ print(os.getpid(), test_name, "FOUND!")
+ write_data(test_name, response.text)
+ else:
+ print(os.getpid(), test_name)
+
+
+def handle_suburl_tup(idx_n_url_level):
+ if stop_all:
+ return # bad solution, but it stops fast
+ idx, n, url, level = idx_n_url_level
+ try:
+ ret = handle_suburl(idx, n, url, level)
+ return url, None
+ except requests.exceptions.RequestException as e:
+ return url, e
+
+
+def handle_batch(urls, level):
+ n = len(urls)
+ args = ((idx, n, url, level) for (idx, url) in enumerate(urls))
+ with Pool(10) as p:
+ records = list(p.imap_unordered(handle_suburl_tup, args))
+ # re-read the failed ones
+ runs = [n]
+ for idx in range(10):
+ urls = list(x[0] for x in records if x[-1])
+ if not urls:
+ break
+ print("Pausing 5 seconds")
+ time.sleep(5)
+ n = len(urls)
+ runs.append(n)
+ args = ((idx, n, url, level) for (idx, url) in enumerate(urls))
+ with Pool(10) as p:
+ records = list(p.imap_unordered(handle_suburl_tup, args))
+ # Return success when the remaining URLs are empty.
+ print("Runs:", ", ".join(map(str, runs)))
+ return not urls
+
+
+def handle_topurl(url):
+ """
+ Find all links to directories.
+
+ We maintain a cache of these links. The cache is only updated
+ when all URLs have been successfully processed.
+ """
+ try:
+ response = requests.get(url)
+ except requests.exceptions.RequestException as e:
+ print("Skipped", e)
+ return
+ global top_url
+ top_url = url
+ urls = find_all_links(response.text, url, ignore=("tasks/",))
+ work_urls = set(urls)
+ cache_file = os.path.join(cache_path, "known_urls.json")
+ if os.path.exists(cache_file):
+ with open(cache_file, 'r') as fp:
+ known_urls = json.load(fp)
+ work_urls -= set(known_urls)
+ level = 1
+ for sub_url in work_urls:
+ name = get_name(sub_url)
+ if name.endswith("/"):
+ if name.startswith("build_"):
+ continue
+ work_urls.add(sub_url)
+ success = handle_batch(work_urls, 1)
+ if success:
+ with open(cache_file, 'w') as fp:
+ json.dump(urls, fp, sort_keys=True, indent=4)
+ return success
+
+
+def get_test_results(starturl):
+ ok = handle_topurl(starturl)
+ stop_time = time.time()
+ runtime = stop_time - start_time
+ hours, remainder = divmod(runtime, 3600)
+ minutes, seconds = divmod(remainder, 60)
+
+ runtime_formatted = f'{hours}:{minutes:%02d}:{seconds:%06.3f}'
+ print(f"Run time: {runtime_formatted}s")
+ if ok:
+ found = eval_data()
+ print(f"Successful scan, {found} new files.")
+ if found:
+ print("Please check if a git push is necessary.")
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ usage=dedent(f"""\
+ {os.path.basename(my_name)} [-h] scan
+
+ Scan the COIN testresults website for embedded exists_{{platf}}_{{version}}_ci.py files.
+
+ Warning: On the first call, this script may take almost 30 minutes to run.
+ Subsequent calls are *much* faster due to caching.
+
+ {os.path.basename(my_name)} [-h] eval
+
+ Enforces evaluation when a scan did not complete yet.
+
+ For more information, see the file
+ sources/shiboken6/libshiboken/signature_doc.rst
+ """))
+ subparsers = parser.add_subparsers(dest="command", metavar="", title="required argument")
+ # create the parser for the "scan" command
+ parser_scan = subparsers.add_parser("scan", help="run the scan")
+ parser_eval = subparsers.add_parser("eval", help="force evaluation")
+ args = parser.parse_args()
+ if not args.command:
+ parser.print_usage()
+ exit(1)
+ if args.command == "scan":
+ # Using this from the intranet require an internal URL
+ get_test_results("https://testresults.qt.io/coin/api/results/pyside/pyside-setup/")
+ elif args.command == "eval":
+ eval_data(force=True)
diff --git a/sources/pyside6/tests/registry/util.py b/sources/pyside6/tests/registry/util.py
new file mode 100644
index 000000000..5d81926a1
--- /dev/null
+++ b/sources/pyside6/tests/registry/util.py
@@ -0,0 +1,149 @@
+# 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
+
+"""
+Supporting isolation of warnings
+
+Warnings in unittests are not isolated.
+We sometimes use warnings to conveniently accumulate error messages
+and eventually report them afterwards as error.
+"""
+
+import sys
+import os
+import warnings
+import re
+from contextlib import contextmanager
+
+warn_name = "__warningregistry__"
+ignore_re = 'Not importing directory .*'
+
+
+@contextmanager
+def isolate_warnings():
+ save_warnings = {}
+ for name, mod in sys.modules.items():
+ if mod and hasattr(mod, warn_name):
+ save_warnings[name] = mod.__dict__[warn_name]
+ delattr(mod, warn_name)
+ yield
+ for name, warn in save_warnings.items():
+ mod = sys.modules[name]
+ if mod:
+ setattr(mod, warn_name, warn)
+ if warn is None:
+ delattr(mod, warn_name)
+
+
+@contextmanager
+def suppress_warnings():
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ yield
+
+
+def check_warnings():
+ for name, mod in sys.modules.items():
+ if mod:
+ reg = getattr(mod, warn_name, None)
+ if reg:
+ # XXX We need to filter warnings for Python 2.
+ # This should be avoided by renaming the duplicate folders.
+ for k in reg:
+ if type(k) is tuple and re.match(ignore_re, k[0]):
+ continue
+ return True
+ return False
+
+
+def warn(message, category=None, stacklevel=2):
+ """Issue a warning with the default 'RuntimeWarning'"""
+ if category is None:
+ category = UserWarning
+ warnings.warn(message, category, stacklevel)
+
+
+def linux_distribution():
+ """Returns the Linux distribution"""
+ # We have to be more specific because we had differences between
+ # RHEL 6.6 and RHEL 7.4 .
+ # Note: The platform module is deprecated. We need to switch to the
+ # distro package, ASAP! The distro has been extracted from Python,
+ # because it changes more often than the Python version.
+ distribution = []
+ import distro
+ distribution = distro.linux_distribution()
+ if distribution:
+ return "".join(distribution[:2]).lower()
+ warnings.warn('Cannot determine Linux distribution, please install distro',
+ UserWarning)
+ return ""
+
+
+# Python2 legacy: Correct 'linux2' to 'linux', recommended way.
+if sys.platform.startswith('linux'):
+ platform_name = linux_distribution()
+ # this currently happens on opensuse in 5.14:
+ if not platform_name:
+ # We intentionally crash when that last resort is also absent:
+ platform_name = os.environ["MACHTYPE"]
+ platform_name = re.sub('[^0-9a-z]', '_', platform_name)
+else:
+ platform_name = sys.platform
+# In the linux case, we need more information.
+
+is_py3 = sys.version_info[0] == 3
+is_ci = os.environ.get("QTEST_ENVIRONMENT", "") == "ci"
+
+
+def get_script_dir():
+ script_dir = os.path.normpath(os.path.dirname(__file__))
+ while "sources" not in os.listdir(script_dir):
+ script_dir = os.path.dirname(script_dir)
+ return script_dir
+
+
+def qt_version():
+ from PySide6.QtCore import __version__
+ return tuple(map(int, __version__.split(".")))
+
+# Format a registry file name for version.
+
+
+def _registry_filename(version, use_ci_module):
+ ext_ci = "_ci" if use_ci_module else ""
+ name = f"exists_{platform_name}_{version[0]}_{version[1]}_{version[2]}{ext_ci}.py"
+ return os.path.join(os.path.dirname(__file__), name)
+
+# Return the expected registry file name.
+
+
+def get_refpath(use_ci_module=is_ci):
+ return _registry_filename(qt_version(), use_ci_module)
+
+# Return the registry file name, either that of the current
+# version or fall back to a previous patch release.
+
+
+def get_effective_refpath(use_ci_module=is_ci):
+ refpath = get_refpath(use_ci_module)
+ if os.path.exists(refpath):
+ return refpath
+ version = qt_version()
+ major, minor, patch = version[:3]
+ while patch >= 0:
+ file = _registry_filename((major, minor, patch), use_ci_module)
+ if os.path.exists(file):
+ return file
+ patch -= 1
+ return refpath
+
+# Import the CI version of the platform module
+
+
+def import_refmodule(use_ci_module=is_ci):
+ refpath = get_effective_refpath(use_ci_module)
+ modname = os.path.basename(os.path.splitext(refpath)[0])
+ return __import__(modname)
+
+# eof
diff --git a/sources/pyside6/tests/run_test.sh b/sources/pyside6/tests/run_test.sh
new file mode 100755
index 000000000..2cb3efa69
--- /dev/null
+++ b/sources/pyside6/tests/run_test.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+# This is a nasty workaround of a CTest limitation
+# of setting the environment variables for the test.
+
+# $1: LD_LIBRARY_PATH
+# $2: $PYTHONPATH
+# $3: python executable
+# $4: test file
+
+export LD_LIBRARY_PATH=$1:$LD_LIBRARY_PATH
+export PYTHONPATH=$2:$PYTHONPATH
+$3 $4
diff --git a/sources/pyside6/tests/signals/CMakeLists.txt b/sources/pyside6/tests/signals/CMakeLists.txt
new file mode 100644
index 000000000..ff342adc7
--- /dev/null
+++ b/sources/pyside6/tests/signals/CMakeLists.txt
@@ -0,0 +1,47 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+PYSIDE_TEST(args_dont_match_test.py)
+PYSIDE_TEST(bug_79.py)
+PYSIDE_TEST(bug_189.py)
+PYSIDE_TEST(bug_311.py)
+PYSIDE_TEST(bug_312.py)
+PYSIDE_TEST(bug_319.py)
+PYSIDE_TEST(decorators_test.py)
+PYSIDE_TEST(disconnect_test.py)
+PYSIDE_TEST(invalid_callback_test.py)
+PYSIDE_TEST(lambda_gui_test.py)
+PYSIDE_TEST(lambda_test.py)
+PYSIDE_TEST(leaking_signal_test.py)
+PYSIDE_TEST(multiple_connections_gui_test.py)
+PYSIDE_TEST(multiple_connections_test.py)
+PYSIDE_TEST(pysignal_test.py)
+PYSIDE_TEST(qobject_callable_connect_test.py)
+PYSIDE_TEST(qobject_destroyed_test.py)
+PYSIDE_TEST(qobject_receivers_test.py)
+PYSIDE_TEST(qobject_sender_test.py)
+PYSIDE_TEST(ref01_test.py)
+PYSIDE_TEST(ref02_test.py)
+PYSIDE_TEST(ref03_test.py)
+PYSIDE_TEST(ref04_test.py)
+PYSIDE_TEST(ref05_test.py)
+PYSIDE_TEST(ref06_test.py)
+PYSIDE_TEST(segfault_proxyparent_test.py)
+PYSIDE_TEST(self_connect_test.py)
+PYSIDE_TEST(short_circuit_test.py)
+PYSIDE_TEST(signal2signal_connect_test.py)
+PYSIDE_TEST(signal_across_threads.py)
+PYSIDE_TEST(signal_autoconnect_test.py)
+PYSIDE_TEST(signal_connectiontype_support_test.py)
+PYSIDE_TEST(signal_emission_gui_test.py)
+PYSIDE_TEST(signal_emission_test.py)
+PYSIDE_TEST(signal_enum_test.py)
+PYSIDE_TEST(signal_func_test.py)
+PYSIDE_TEST(signal_manager_refcount_test.py)
+PYSIDE_TEST(signal_newenum_test.py)
+PYSIDE_TEST(signal_number_limit_test.py)
+PYSIDE_TEST(signal_object_test.py)
+PYSIDE_TEST(signal_signature_test.py)
+PYSIDE_TEST(signal_with_primitive_type_test.py)
+PYSIDE_TEST(slot_reference_count_test.py)
+PYSIDE_TEST(static_metaobject_test.py)
diff --git a/sources/pyside6/tests/signals/anonymous_slot_leak_test.py b/sources/pyside6/tests/signals/anonymous_slot_leak_test.py
new file mode 100644
index 000000000..560a08659
--- /dev/null
+++ b/sources/pyside6/tests/signals/anonymous_slot_leak_test.py
@@ -0,0 +1,55 @@
+# 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 functools import partial
+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.QtWidgets import QWidget
+from helper.usesqapplication import UsesQApplication
+
+
+have_debug = hasattr(sys, "gettotalrefcount")
+
+
+class LeakerLambda():
+ def __init__(self, widget):
+ widget.windowIconChanged.connect(lambda *args: None)
+
+
+class LeakerFunctoolsPartial():
+ def __init__(self, widget):
+ widget.windowIconChanged.connect(partial(int, 0))
+
+
+class TestBugPYSIDE2299(UsesQApplication):
+ def leak(self, leaker):
+ widget = QWidget()
+
+ # Warm-up
+ leaker(widget)
+
+ refs_before = sys.gettotalrefcount()
+ for _ in range(1000):
+ leaker(widget)
+ refs_after = sys.gettotalrefcount()
+
+ self.assertAlmostEqual(refs_after - refs_before, 0, delta=10)
+
+ @unittest.skipUnless(have_debug, "You need a debug build")
+ def test_lambda(self):
+ self.leak(LeakerLambda)
+
+ @unittest.skipUnless(have_debug, "You need a debug build")
+ def test_functools_partial(self):
+ self.leak(LeakerFunctoolsPartial)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/args_dont_match_test.py b/sources/pyside6/tests/signals/args_dont_match_test.py
new file mode 100644
index 000000000..4f56be348
--- /dev/null
+++ b/sources/pyside6/tests/signals/args_dont_match_test.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env 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.QtCore import QObject, Signal
+
+
+class Sender(QObject):
+ the_signal = Signal(int, int, int)
+
+
+class ArgsDontMatch(unittest.TestCase):
+
+ def callback(self, arg1):
+ self.ok = True
+
+ def testConnectSignalToSlotWithLessArgs(self):
+ self.ok = False
+ obj1 = Sender()
+ obj1.the_signal.connect(self.callback)
+ obj1.the_signal.emit(1, 2, 3)
+
+ self.assertTrue(self.ok)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/bug_189.py b/sources/pyside6/tests/signals/bug_189.py
new file mode 100644
index 000000000..1c013ddea
--- /dev/null
+++ b/sources/pyside6/tests/signals/bug_189.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)
+
+from PySide6.QtCore import QTimer
+from PySide6.QtWidgets import QSlider
+from helper.usesqapplication import UsesQApplication
+
+
+class TestBugPYSIDE189(UsesQApplication):
+
+ def testDisconnect(self):
+ # Disconnecting from a signal owned by a destroyed object
+ # should raise an exception, not segfault.
+ def onValueChanged(self, value):
+ pass
+
+ sld = QSlider()
+ sld.valueChanged.connect(onValueChanged)
+
+ sld.deleteLater()
+
+ QTimer.singleShot(0, self.app.quit)
+ self.app.exec()
+
+ self.assertRaises(RuntimeError, sld.valueChanged.disconnect, onValueChanged)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/bug_311.py b/sources/pyside6/tests/signals/bug_311.py
new file mode 100644
index 000000000..e27476172
--- /dev/null
+++ b/sources/pyside6/tests/signals/bug_311.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env 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.QtCore import QDate, QObject, Signal
+from helper.usesqapplication import UsesQApplication
+
+
+class DerivedDate(QDate):
+ def __init__(self, y, m, d):
+ super().__init__(y, m, d)
+
+
+class Emitter(QObject):
+ dateSignal1 = Signal(QDate)
+ dateSignal2 = Signal(DerivedDate)
+ tupleSignal = Signal(tuple)
+
+
+class SignaltoSignalTest(UsesQApplication):
+ def myCb(self, dt):
+ self._dt = dt
+
+ def testBug(self):
+ e = Emitter()
+ d = DerivedDate(2010, 8, 24)
+ self._dt = None
+ e.dateSignal1.connect(self.myCb)
+ e.dateSignal1.emit(d)
+ self.assertEqual(self._dt, d)
+
+ self._dt = None
+ e.dateSignal2.connect(self.myCb)
+ e.dateSignal2.emit(d)
+ self.assertEqual(self._dt, d)
+
+ myTuple = (5, 6, 7)
+ self._dt = None
+ e.tupleSignal.connect(self.myCb)
+ e.tupleSignal.emit(myTuple)
+ self.assertEqual(myTuple, self._dt)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/bug_312.py b/sources/pyside6/tests/signals/bug_312.py
new file mode 100644
index 000000000..80d56a020
--- /dev/null
+++ b/sources/pyside6/tests/signals/bug_312.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env 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.QtCore import QObject, Signal
+
+MAX_LOOPS = 5
+MAX_OBJECTS = 200
+
+
+class Sender(QObject):
+ fire = Signal()
+
+
+class MultipleSlots(unittest.TestCase):
+ def myCB(self):
+ self._count += 1
+
+ def testDisconnectCleanup(self):
+ for c in range(MAX_LOOPS):
+ self._count = 0
+ self._senders = []
+ for i in range(MAX_OBJECTS):
+ o = Sender()
+ o.fire.connect(lambda: self.myCB())
+ self._senders.append(o)
+ o.fire.emit()
+
+ self.assertEqual(self._count, MAX_OBJECTS)
+
+ # delete all senders will disconnect the signals
+ self._senders = []
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/bug_319.py b/sources/pyside6/tests/signals/bug_319.py
new file mode 100644
index 000000000..657733afb
--- /dev/null
+++ b/sources/pyside6/tests/signals/bug_319.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env 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.QtCore import QObject, Signal, Slot
+from helper.usesqapplication import UsesQApplication
+
+
+class Listener(QObject):
+ def __init__(self):
+ super().__init__(None)
+ self._phrase = []
+
+ @Slot(tuple)
+ def listen(self, words):
+ for w in words:
+ self._phrase.append(w)
+
+
+class Communicate(QObject):
+ # create a new signal on the fly and name it 'speak'
+ speak = Signal(tuple)
+
+
+class SignaltoSignalTest(UsesQApplication):
+ def testBug(self):
+ someone = Communicate()
+ someone2 = Listener()
+ # connect signal and slot
+ someone.speak.connect(someone2.listen)
+ # emit 'speak' signal
+ talk = ("one", "two", "three")
+ someone.speak.emit(talk)
+ self.assertEqual(someone2._phrase, list(talk))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/bug_79.py b/sources/pyside6/tests/signals/bug_79.py
new file mode 100644
index 000000000..77ac621d5
--- /dev/null
+++ b/sources/pyside6/tests/signals/bug_79.py
@@ -0,0 +1,59 @@
+# 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 gc
+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.QtGui import QStandardItemModel
+from PySide6.QtWidgets import QApplication, QTreeView
+
+
+try:
+ from sys import gettotalrefcount
+ skiptest = False
+except ImportError:
+ skiptest = True
+
+
+class ConnectTest(unittest.TestCase):
+
+ def callback(self, o):
+ print("callback")
+ self._called = o
+
+ def testNoLeaks_ConnectAndDisconnect(self):
+ self._called = None
+ app = QApplication([]) # noqa: F841
+ o = QTreeView()
+ o.setModel(QStandardItemModel())
+ o.selectionModel().destroyed.connect(self.callback)
+ o.selectionModel().destroyed.disconnect(self.callback)
+ gc.collect()
+ # if this is no debug build, then we check at least that
+ # we do not crash any longer.
+ for idx in range(200):
+ # PYSIDE-2230: Warm-up is necessary before measuring, because
+ # the code changes the constant parts after some time.
+ o.selectionModel().destroyed.connect(self.callback)
+ o.selectionModel().destroyed.disconnect(self.callback)
+ if not skiptest:
+ total = gettotalrefcount()
+ for idx in range(1000):
+ o.selectionModel().destroyed.connect(self.callback)
+ o.selectionModel().destroyed.disconnect(self.callback)
+ gc.collect()
+ if not skiptest:
+ delta = gettotalrefcount() - total
+ print("delta total refcount =", delta)
+ self.assertTrue(abs(delta) < 10)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/decorators_test.py b/sources/pyside6/tests/signals/decorators_test.py
new file mode 100644
index 000000000..b29339ee4
--- /dev/null
+++ b/sources/pyside6/tests/signals/decorators_test.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env 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.QtCore import QObject, Slot, Signal
+
+
+class Sender(QObject):
+ mySignal = Signal()
+
+
+class MyObject(QObject):
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+ self._slotCalledCount = 0
+
+ @Slot()
+ def mySlot(self):
+ self._slotCalledCount = self._slotCalledCount + 1
+
+ @Slot(int)
+ @Slot('QString')
+ def mySlot2(self, arg0):
+ self._slotCalledCount = self._slotCalledCount + 1
+
+ @Slot(name='mySlot3')
+ def foo(self):
+ self._slotCalledCount = self._slotCalledCount + 1
+
+ @Slot(str, int)
+ def mySlot4(self, a, b):
+ self._slotCalledCount = self._slotCalledCount + 1
+
+ @Slot(result=int)
+ def mySlot5(self):
+ self._slotCalledCount = self._slotCalledCount + 1
+
+ @Slot(result=QObject)
+ def mySlot6(self):
+ self._slotCalledCount = self._slotCalledCount + 1
+
+
+class StaticMetaObjectTest(unittest.TestCase):
+
+ def testSignalPropagation(self):
+ o = MyObject()
+ m = o.metaObject()
+ self.assertTrue(m.indexOfSlot('mySlot()') > 0)
+ self.assertTrue(m.indexOfSlot('mySlot2(int)') > 0)
+ self.assertTrue(m.indexOfSlot('mySlot2(QString)') > 0)
+ self.assertTrue(m.indexOfSlot('mySlot3()') > 0)
+ self.assertTrue(m.indexOfSlot('mySlot4(QString,int)') > 0)
+
+ def testEmission(self):
+ sender = Sender()
+ o = MyObject()
+ sender.mySignal.connect(o.mySlot)
+ sender.mySignal.emit()
+ self.assertTrue(o._slotCalledCount == 1)
+
+ def testResult(self):
+ o = MyObject()
+ mo = o.metaObject()
+ i = mo.indexOfSlot('mySlot5()')
+ m = mo.method(i)
+ self.assertEqual(m.typeName(), "int")
+
+ def testResultObject(self):
+ o = MyObject()
+ mo = o.metaObject()
+ i = mo.indexOfSlot('mySlot6()')
+ m = mo.method(i)
+ self.assertEqual(m.typeName(), "QObject*")
+
+
+class SlotWithoutArgs(unittest.TestCase):
+
+ def testError(self):
+ # It should be an error to call the slot without the
+ # arguments, as just @Slot would end up in a slot
+ # accepting argument functions
+ self.assertRaises(TypeError, Slot, lambda: 3)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/disconnect_test.py b/sources/pyside6/tests/signals/disconnect_test.py
new file mode 100644
index 000000000..ea3782a91
--- /dev/null
+++ b/sources/pyside6/tests/signals/disconnect_test.py
@@ -0,0 +1,70 @@
+# 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, Signal
+from testbinding import TestObject
+
+
+class Foo(QObject):
+ bar = Signal()
+
+
+class TestDisconnect(unittest.TestCase):
+ def theSlot1(self):
+ self.called1 = True
+
+ def theSlot2(self):
+ self.called2 = True
+
+ def testIt(self):
+ self.called1 = False
+ self.called2 = False
+ f = Foo()
+ f.bar.connect(self.theSlot1)
+ f.bar.connect(self.theSlot2)
+ f.bar.emit()
+ self.assertTrue(self.called1)
+ self.assertTrue(self.called2)
+
+ self.called1 = False
+ self.called2 = False
+ f.bar.disconnect()
+ f.bar.emit()
+ self.assertFalse(self.called1)
+ self.assertFalse(self.called2)
+
+ def testDuringCallback(self):
+ """ Test to see if the C++ object for a connection is accessed after the
+ method returns. This causes a segfault if the memory that was used by the
+ C++ object has been reused. """
+
+ self.called = False
+ obj = TestObject(0)
+
+ def callback():
+ obj.signalWithDefaultValue.disconnect(callback)
+
+ # Connect more callbacks to try to overwrite memory
+ for i in range(1000):
+ obj.signalWithDefaultValue.connect(lambda: None)
+
+ self.called = True
+
+ # A non-None return value is needed
+ return True
+ obj.signalWithDefaultValue.connect(callback)
+ obj.signalWithDefaultValue.emit()
+ self.assertTrue(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/invalid_callback_test.py b/sources/pyside6/tests/signals/invalid_callback_test.py
new file mode 100644
index 000000000..2788c1d1a
--- /dev/null
+++ b/sources/pyside6/tests/signals/invalid_callback_test.py
@@ -0,0 +1,41 @@
+# 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 cases for passing invalid callbacks to QObject.connect'''
+
+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
+
+
+class InvalidCallback(unittest.TestCase):
+ '''Test case for passing an invalid callback to QObject.connect'''
+
+ def setUp(self):
+ # Acquire resources
+ self.obj = QObject()
+
+ def tearDown(self):
+ # Release resources
+ try:
+ del self.obj
+ except AttributeError:
+ pass
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testIntegerCb(self):
+ # Test passing an int as callback to QObject.connect
+ self.assertRaises(TypeError, self.obj.destroyed.connect, 42)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/lambda_gui_test.py b/sources/pyside6/tests/signals/lambda_gui_test.py
new file mode 100644
index 000000000..2123e7206
--- /dev/null
+++ b/sources/pyside6/tests/signals/lambda_gui_test.py
@@ -0,0 +1,50 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Connecting lambda to gui signals'''
+
+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.QtWidgets import QSpinBox, QPushButton
+
+from helper.usesqapplication import UsesQApplication
+
+
+class Control:
+ def __init__(self):
+ self.arg = False
+
+
+class QtWidgetsSigLambda(UsesQApplication):
+
+ def testButton(self):
+ # Connecting a lambda to a QPushButton.clicked()
+ obj = QPushButton('label')
+ ctr = Control()
+ func = lambda: setattr(ctr, 'arg', True) # noqa: E731
+ obj.clicked.connect(func)
+ obj.click()
+ self.assertTrue(ctr.arg)
+ self.assertTrue(obj.clicked.disconnect(func))
+
+ def testSpinButton(self):
+ # Connecting a lambda to a QPushButton.clicked()
+ obj = QSpinBox()
+ ctr = Control()
+ arg = 444
+ func = lambda x: setattr(ctr, 'arg', 444) # noqa: E731
+ obj.valueChanged.connect(func)
+ obj.setValue(444)
+ self.assertEqual(ctr.arg, arg)
+ self.assertTrue(obj.valueChanged.disconnect(func))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/lambda_test.py b/sources/pyside6/tests/signals/lambda_test.py
new file mode 100644
index 000000000..23fcdf5fa
--- /dev/null
+++ b/sources/pyside6/tests/signals/lambda_test.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env 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
+
+'''Connecting lambda to signals'''
+
+import os
+import sys
+import unittest
+import weakref
+
+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 QCoreApplication, QObject, Signal, SIGNAL, QProcess
+
+from helper.usesqapplication import UsesQApplication
+
+
+class Sender(QObject):
+ void_signal = Signal()
+ int_signal = Signal(int)
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._delayed_int = 0
+
+ def emit_void(self):
+ self.void_signal.emit()
+
+ def emit_int(self, v):
+ self.int_signal.emit(v)
+
+
+class Receiver(QObject):
+
+ def __init__(self, *args):
+ super().__init__(*args)
+
+
+class BasicCase(unittest.TestCase):
+
+ def testSimplePythonSignalNoArgs(self):
+ # Connecting a lambda to a simple python signal without arguments
+ receiver = Receiver()
+ sender = Sender()
+ sender.void_signal.connect(lambda: setattr(receiver, 'called', True))
+ sender.emit_void()
+ self.assertTrue(receiver.called)
+
+ def testSimplePythonSignal(self):
+ # Connecting a lambda to a simple python signal witharguments
+ receiver = Receiver()
+ sender = Sender()
+ arg = 42
+ sender.int_signal.connect(lambda x: setattr(receiver, 'arg', arg))
+ sender.emit_int(arg)
+ self.assertEqual(receiver.arg, arg)
+
+ def testSimplePythonSignalNoArgsString(self):
+ # Connecting a lambda to a simple python signal without arguments
+ receiver = Receiver()
+ sender = Sender()
+ QObject.connect(sender, SIGNAL('void_signal()'),
+ lambda: setattr(receiver, 'called', True))
+ sender.emit_void()
+ self.assertTrue(receiver.called)
+
+ def testSimplePythonSignalString(self):
+ # Connecting a lambda to a simple python signal witharguments
+ receiver = Receiver()
+ sender = Sender()
+ arg = 42
+ QObject.connect(sender, SIGNAL('int_signal(int)'),
+ lambda x: setattr(receiver, 'arg', arg))
+ sender.emit_int(arg)
+ self.assertEqual(receiver.arg, arg)
+
+
+class QtSigLambda(UsesQApplication):
+
+ qapplication = True
+
+ def testWithArgs(self):
+ '''Connecting a lambda to a signal with and without arguments'''
+ proc = QProcess()
+ dummy = Receiver()
+ proc.started.connect(lambda: setattr(dummy, 'called', True))
+ proc.finished.connect(lambda x: setattr(dummy, 'exit_code', x))
+
+ proc.start(sys.executable, ['-c', '""'])
+ self.assertTrue(proc.waitForStarted())
+ self.assertTrue(proc.waitForFinished())
+
+ self.assertTrue(dummy.called)
+ self.assertEqual(dummy.exit_code, proc.exitCode())
+
+ def testRelease(self):
+ """PYSIDE-2646: Test whether main thread target slot lambda/methods
+ (and their captured objects) are released by the signal manager
+ after a while."""
+
+ def do_connect(sender):
+ receiver = Receiver()
+ sender.void_signal.connect(lambda: setattr(receiver, 'called', True))
+ return receiver
+
+ sender = Sender()
+ receiver = weakref.ref(do_connect(sender))
+ sender.emit_void()
+ self.assertTrue(receiver().called)
+ del sender
+ for i in range(3):
+ if not receiver():
+ break
+ QCoreApplication.processEvents()
+ self.assertFalse(receiver())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/leaking_signal_test.py b/sources/pyside6/tests/signals/leaking_signal_test.py
new file mode 100644
index 000000000..666ae7a13
--- /dev/null
+++ b/sources/pyside6/tests/signals/leaking_signal_test.py
@@ -0,0 +1,27 @@
+# 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, Signal
+
+
+class LeakingSignal(unittest.TestCase):
+
+ def testLeakingSignal(self):
+ # Was segfaulting when the signal was garbage collected.
+ class Emitter(QObject):
+ my_signal = Signal(object)
+
+ emitter = Emitter() # noqa: F841
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/multiple_connections_gui_test.py b/sources/pyside6/tests/signals/multiple_connections_gui_test.py
new file mode 100644
index 000000000..295369b7d
--- /dev/null
+++ b/sources/pyside6/tests/signals/multiple_connections_gui_test.py
@@ -0,0 +1,60 @@
+# 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.QtWidgets import QPushButton, QSpinBox
+
+from helper.basicpyslotcase import BasicPySlotCase
+from helper.usesqapplication import UsesQApplication
+
+
+class QtGuiMultipleSlots(UsesQApplication):
+ '''Multiple connections to QtGui signals'''
+
+ def run_many(self, signal, emitter, receivers, args=None):
+ """Utility method to connect a list of receivers to a signal.
+ sender - QObject that will emit the signal
+ signal - string with the signal signature
+ emitter - the callable that will trigger the signal
+ receivers - list of BasicPySlotCase instances
+ args - tuple with the arguments to be sent.
+ """
+
+ if args is None:
+ args = tuple()
+
+ for rec in receivers:
+ rec.setUp()
+ signal.connect(rec.cb)
+ rec.args = tuple(args)
+
+ emitter(*args)
+
+ for rec in receivers:
+ self.assertTrue(rec.called)
+
+ def testButtonClick(self):
+ """Multiple connections to QPushButton.clicked()"""
+ sender = QPushButton('button')
+ receivers = [BasicPySlotCase() for x in range(30)]
+ self.run_many(sender.clicked, sender.click, receivers)
+
+ def testSpinBoxValueChanged(self):
+ """Multiple connections to QSpinBox.valueChanged(int)"""
+ sender = QSpinBox()
+ # FIXME if number of receivers if higher than 50, segfaults
+ receivers = [BasicPySlotCase() for x in range(10)]
+ self.run_many(sender.valueChanged, sender.setValue,
+ receivers, (1,))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/multiple_connections_test.py b/sources/pyside6/tests/signals/multiple_connections_test.py
new file mode 100644
index 000000000..233851797
--- /dev/null
+++ b/sources/pyside6/tests/signals/multiple_connections_test.py
@@ -0,0 +1,90 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+from functools import partial
+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, QProcess
+
+from helper.basicpyslotcase import BasicPySlotCase
+from helper.usesqapplication import UsesQApplication
+
+
+class MultipleSignalConnections(unittest.TestCase):
+ '''Base class for multiple signal connection testing'''
+
+ def run_many(self, signal, emitter, receivers, args=None):
+ """Utility method to connect a list of receivers to a signal.
+ sender - QObject that will emit the signal
+ signal - string with the signal signature
+ emitter - the callable that will trigger the signal
+ receivers - list of BasicPySlotCase instances
+ args - tuple with the arguments to be sent.
+ """
+
+ if args is None:
+ args = tuple()
+ for rec in receivers:
+ rec.setUp()
+ self.assertTrue(signal.connect(rec.cb))
+ rec.args = tuple(args)
+
+ emitter(*args)
+
+ for rec in receivers:
+ self.assertTrue(rec.called)
+
+
+class PythonMultipleSlots(UsesQApplication, MultipleSignalConnections):
+ '''Multiple connections to python signals'''
+
+ def testPythonSignal(self):
+ """Multiple connections to a python signal (short-circuit)"""
+
+ class Sender(QObject):
+
+ foobar = Signal(int)
+
+ sender = Sender()
+ receivers = [BasicPySlotCase() for x in range(10)]
+ self.run_many(sender.foobar, partial(sender.foobar.emit),
+ receivers, (0, ))
+
+
+class QProcessMultipleSlots(UsesQApplication, MultipleSignalConnections):
+ '''Multiple connections to QProcess signals'''
+
+ def testQProcessStarted(self):
+ '''Multiple connections to QProcess.started()'''
+ sender = QProcess()
+ receivers = [BasicPySlotCase() for x in range(10)]
+
+ def start_proc(*args):
+ sender.start(sys.executable, ['-c', '""'])
+ self.assertTrue(sender.waitForStarted())
+ self.assertTrue(sender.waitForFinished())
+
+ self.run_many(sender.started, start_proc, receivers)
+
+ def testQProcessFinished(self):
+ '''Multiple connections to QProcess.finished(int)'''
+ sender = QProcess()
+ receivers = [BasicPySlotCase() for x in range(10)]
+
+ def start_proc(*args):
+ sender.start(sys.executable, ['-c', '""'])
+ self.assertTrue(sender.waitForStarted())
+ self.assertTrue(sender.waitForFinished())
+
+ self.run_many(sender.finished, start_proc, receivers, (0, QProcess.ExitStatus.NormalExit))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/pysignal_test.py b/sources/pyside6/tests/signals/pysignal_test.py
new file mode 100644
index 000000000..d6f44edf8
--- /dev/null
+++ b/sources/pyside6/tests/signals/pysignal_test.py
@@ -0,0 +1,203 @@
+# 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, Qt
+from PySide6.QtWidgets import QSpinBox, QApplication, QWidget # noqa: F401
+
+from helper.usesqapplication import UsesQApplication
+
+
+TEST_LIST = ["item1", "item2", "item3"]
+
+
+class Sender(QObject):
+ """Sender class used in this test."""
+
+ foo = Signal()
+ foo_int = Signal(int)
+ dummy = Signal(str)
+ dummy2 = Signal(str, list)
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ def callDummy(self):
+ self.dummy.emit("PyObject")
+
+ def callDummy2(self):
+ self.dummy2.emit("PyObject0", TEST_LIST)
+
+
+class PyObjectType(UsesQApplication):
+ def mySlot(self, arg):
+ self.assertEqual(arg, "PyObject")
+ self.called = True
+ self.callCount += 1
+
+ def mySlot2(self, arg0, arg1):
+ self.assertEqual(arg0, "PyObject0")
+ self.assertEqual(arg1, TEST_LIST)
+ self.callCount += 1
+ if self.running:
+ self.app.quit()
+
+ def setUp(self):
+ super().setUp()
+ self.callCount = 0
+ self.running = False
+
+ def testWithOneArg(self):
+ o = Sender()
+ o.dummy.connect(self.mySlot)
+ o.callDummy()
+ self.assertEqual(self.callCount, 1)
+
+ def testWithTwoArg(self):
+ o = Sender()
+ o.dummy2.connect(self.mySlot2)
+ o.callDummy2()
+ self.assertEqual(self.callCount, 1)
+
+ def testAsyncSignal(self):
+ self.called = False
+ self.running = True
+ o = Sender()
+ o.dummy2.connect(self.mySlot2, Qt.QueuedConnection)
+ o.callDummy2()
+ self.app.exec()
+ self.assertEqual(self.callCount, 1)
+
+ def testTwice(self):
+ self.called = False
+ self.running = True
+ o = Sender()
+ o.dummy2.connect(self.mySlot2, Qt.QueuedConnection)
+ o.callDummy2()
+ o.callDummy2()
+ self.app.exec()
+ self.assertEqual(self.callCount, 2)
+
+
+class PythonSigSlot(unittest.TestCase):
+ def setUp(self):
+ self.called = False
+
+ def tearDown(self):
+ try:
+ del self.args
+ except: # noqa: E722
+ pass
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def callback(self, *args):
+ if tuple(self.args) == args:
+ self.called = True
+
+ def testNoArgs(self):
+ """Python signal and slots without arguments"""
+ obj1 = Sender()
+
+ obj1.foo.connect(self.callback)
+ self.args = tuple()
+ obj1.foo.emit(*self.args)
+
+ self.assertTrue(self.called)
+
+ def testWithArgs(self):
+ """Python signal and slots with integer arguments"""
+ obj1 = Sender()
+
+ obj1.foo_int.connect(self.callback)
+ self.args = (42,)
+ obj1.foo_int.emit(*self.args)
+
+ self.assertTrue(self.called)
+
+ def testDisconnect(self):
+ obj1 = Sender()
+
+ obj1.foo_int.connect(self.callback)
+ self.assertTrue(obj1.foo_int.disconnect(self.callback))
+
+ self.args = (42, )
+ obj1.foo_int.emit(*self.args)
+
+ self.assertTrue(not self.called)
+
+
+class SpinBoxPySignal(UsesQApplication):
+ """Tests the connection of python signals to QSpinBox qt slots."""
+
+ def setUp(self):
+ super().setUp()
+ self.obj = Sender()
+ self.spin = QSpinBox()
+ self.spin.setValue(0)
+
+ def tearDown(self):
+ super().tearDown()
+ del self.obj
+ del self.spin
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testValueChanged(self):
+ """Emission of a python signal to QSpinBox setValue(int)"""
+
+ self.obj.foo_int.connect(self.spin.setValue)
+ self.assertEqual(self.spin.value(), 0)
+
+ self.obj.foo_int.emit(4)
+ self.assertEqual(self.spin.value(), 4)
+
+ def testValueChangedMultiple(self):
+ """Multiple emissions of a python signal to QSpinBox setValue(int)"""
+ self.obj.foo_int.connect(self.spin.setValue)
+ self.assertEqual(self.spin.value(), 0)
+
+ self.obj.foo_int.emit(4)
+ self.assertEqual(self.spin.value(), 4)
+
+ self.obj.foo_int.emit(77)
+ self.assertEqual(self.spin.value(), 77)
+
+
+class WidgetPySignal(UsesQApplication):
+ """Tests the connection of python signals to QWidget qt slots."""
+
+ def setUp(self):
+ super(WidgetPySignal, self).setUp()
+ self.obj = Sender()
+ self.widget = QWidget()
+
+ def tearDown(self):
+ super(WidgetPySignal, self).tearDown()
+ del self.obj
+ del self.widget
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testShow(self):
+ """Emission of a python signal to QWidget slot show()"""
+ self.widget.hide()
+
+ self.obj.foo.connect(self.widget.show)
+ self.assertTrue(not self.widget.isVisible())
+
+ self.obj.foo.emit()
+ self.assertTrue(self.widget.isVisible())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/qobject_callable_connect_test.py b/sources/pyside6/tests/signals/qobject_callable_connect_test.py
new file mode 100644
index 000000000..a7a26d6f5
--- /dev/null
+++ b/sources/pyside6/tests/signals/qobject_callable_connect_test.py
@@ -0,0 +1,45 @@
+# Copyright (C) 2024 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, Signal
+
+
+class Emitter(QObject):
+ sig = Signal(int)
+
+
+class CallableObject(QObject):
+ called = False
+ x = 0
+
+ def __call__(self, x: int):
+ self.called = True
+ self.x = x
+
+
+class QObjectCallableConnectTest(unittest.TestCase):
+ '''Test case for QObject.connect() when the callable is also a QObject.'''
+
+ def testCallableConnect(self):
+ emitter = Emitter()
+ obj = CallableObject()
+ x = 1
+
+ emitter.sig.connect(obj)
+ emitter.sig.emit(x)
+
+ self.assertTrue(obj.called)
+ self.assertEqual(obj.x, x)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/qobject_destroyed_test.py b/sources/pyside6/tests/signals/qobject_destroyed_test.py
new file mode 100644
index 000000000..a21762b41
--- /dev/null
+++ b/sources/pyside6/tests/signals/qobject_destroyed_test.py
@@ -0,0 +1,39 @@
+# 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
+
+
+class QObjectDestroyed(unittest.TestCase):
+ """Very simple test case for the destroyed() signal of QObject"""
+
+ def setUp(self):
+ self.called = False
+
+ def destroyed_cb(self):
+ self.called = True
+
+ def testDestroyed(self):
+ """Emission of QObject.destroyed() to a python slot"""
+ obj = QObject()
+ obj.destroyed.connect(self.destroyed_cb)
+ del obj
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ # PYSIDE-535: Why do I need to do it twice, here?
+ gc.collect()
+ self.assertTrue(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/qobject_receivers_test.py b/sources/pyside6/tests/signals/qobject_receivers_test.py
new file mode 100644
index 000000000..9839255ac
--- /dev/null
+++ b/sources/pyside6/tests/signals/qobject_receivers_test.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
+
+''' Test case for QObject.receivers()'''
+
+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, SLOT
+
+
+def cute_slot():
+ pass
+
+
+class TestQObjectReceivers(unittest.TestCase):
+ '''Test case for QObject::receivers'''
+
+ def testBasic(self):
+ sender = QObject()
+ receiver1 = QObject()
+ receiver2 = QObject()
+ self.assertEqual(sender.receivers(SIGNAL("")), 0)
+ sender.destroyed.connect(receiver1.deleteLater)
+ self.assertEqual(sender.receivers(SIGNAL("destroyed()")), 1)
+ sender.destroyed.connect(receiver2.deleteLater)
+ self.assertEqual(sender.receivers(SIGNAL("destroyed()")), 2)
+ sender.disconnect(sender, SIGNAL("destroyed()"), receiver2, SLOT("deleteLater()"))
+ self.assertEqual(sender.receivers(SIGNAL("destroyed()")), 1)
+ del receiver2
+ del receiver1
+ del sender
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testPySlots(self):
+ sender = QObject()
+ receiver = QObject()
+ sender.destroyed.connect(cute_slot)
+ self.assertEqual(sender.receivers(SIGNAL("destroyed( )")), 1)
+ sender.destroyed.connect(receiver.deleteLater)
+ self.assertEqual(sender.receivers(SIGNAL("destroyed()")), 2)
+ del sender
+ del receiver
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testPySignals(self):
+ sender = QObject()
+ receiver = QObject()
+ sender.connect(sender, SIGNAL("some_dynamic_signal()"), cute_slot)
+ self.assertEqual(sender.receivers(SIGNAL("some_dynamic_signal( )")), 1)
+ sender.connect(sender, SIGNAL("some_dynamic_signal()"), receiver, SLOT("deleteLater()"))
+ self.assertEqual(sender.receivers(SIGNAL("some_dynamic_signal( )")), 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/qobject_sender_test.py b/sources/pyside6/tests/signals/qobject_sender_test.py
new file mode 100644
index 000000000..9c1121eb8
--- /dev/null
+++ b/sources/pyside6/tests/signals/qobject_sender_test.py
@@ -0,0 +1,117 @@
+#!/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
+
+'''Test cases for QObject.sender()'''
+
+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 QCoreApplication, QObject, QTimer, Signal
+from helper.usesqapplication import UsesQApplication
+
+
+class ExtQTimer(QTimer):
+ def __init__(self):
+ super().__init__()
+
+
+class Sender(QObject):
+ foo = Signal()
+
+
+class Receiver(QObject):
+ def __init__(self):
+ super().__init__()
+ self.the_sender = None
+
+ def callback(self):
+ self.the_sender = self.sender()
+ if QCoreApplication.instance():
+ QCoreApplication.instance().exit()
+
+
+class ObjectSenderTest(unittest.TestCase):
+ '''Test case for QObject.sender() method.'''
+
+ def testSenderPythonSignal(self):
+ sender = Sender()
+ recv = Receiver()
+ sender.foo.connect(recv.callback)
+ sender.foo.emit()
+ self.assertEqual(sender, recv.the_sender)
+
+
+class ObjectSenderCheckOnReceiverTest(unittest.TestCase):
+ '''Test case for QObject.sender() method, this one tests the equality on the Receiver object.'''
+
+ def testSenderPythonSignal(self):
+ sender = Sender()
+ recv = Receiver()
+ sender.foo.connect(recv.callback)
+ sender.foo.emit()
+ self.assertEqual(sender, recv.the_sender)
+
+
+class ObjectSenderWithQAppTest(UsesQApplication):
+ '''Test case for QObject.sender() method with QApplication.'''
+
+ def testSenderCppSignal(self):
+ sender = QTimer()
+ sender.setObjectName('foo')
+ recv = Receiver()
+ sender.timeout.connect(recv.callback)
+ sender.start(10)
+ self.app.exec()
+ self.assertEqual(sender, recv.the_sender)
+
+ def testSenderCppSignalSingleShotTimer(self):
+ recv = Receiver()
+ QTimer.singleShot(10, recv.callback)
+ self.app.exec()
+ self.assertTrue(isinstance(recv.the_sender, QObject))
+
+ def testSenderCppSignalSingleShotTimerWithContext(self):
+ recv = Receiver()
+ QTimer.singleShot(10, recv, recv.callback)
+ self.app.exec()
+ self.assertTrue(isinstance(recv.the_sender, QObject))
+
+ def testSenderCppSignalWithPythonExtendedClass(self):
+ sender = ExtQTimer()
+ recv = Receiver()
+ sender.timeout.connect(recv.callback)
+ sender.start(10)
+ self.app.exec()
+ self.assertEqual(sender, recv.the_sender)
+
+
+class ObjectSenderWithQAppCheckOnReceiverTest(UsesQApplication):
+ '''Test case for QObject.sender() method with QApplication.'''
+
+ def testSenderCppSignal(self):
+ sender = QTimer()
+ sender.setObjectName('foo')
+ recv = Receiver()
+ sender.timeout.connect(recv.callback)
+ sender.start(10)
+ self.app.exec()
+ self.assertEqual(sender, recv.the_sender)
+
+ def testSenderCppSignalWithPythonExtendedClass(self):
+ sender = ExtQTimer()
+ recv = Receiver()
+ sender.timeout.connect(recv.callback)
+ sender.start(10)
+ self.app.exec()
+ self.assertEqual(sender, recv.the_sender)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/ref01_test.py b/sources/pyside6/tests/signals/ref01_test.py
new file mode 100644
index 000000000..1a62b2218
--- /dev/null
+++ b/sources/pyside6/tests/signals/ref01_test.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env 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(False)
+
+from PySide6.QtCore import QObject, Signal
+
+
+class BoundAndUnboundSignalsTest(unittest.TestCase):
+
+ def setUp(self):
+ self.methods = set(('connect', 'disconnect', 'emit'))
+
+ def tearDown(self):
+ del self.methods
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testUnboundSignal(self):
+ self.assertEqual(type(QObject.destroyed), Signal)
+ self.assertFalse(self.methods.issubset(dir(QObject.destroyed)))
+
+ def testBoundSignal(self):
+ obj = QObject()
+ self.assertNotEqual(type(obj.destroyed), Signal)
+ self.assertTrue(self.methods.issubset(dir(obj.destroyed)))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/ref02_test.py b/sources/pyside6/tests/signals/ref02_test.py
new file mode 100644
index 000000000..54b6f4a52
--- /dev/null
+++ b/sources/pyside6/tests/signals/ref02_test.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env 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(False)
+
+from PySide6.QtCore import QTimeLine
+from helper.usesqapplication import UsesQApplication
+
+
+class NativeSignalsTest(UsesQApplication):
+
+ def setUp(self):
+ UsesQApplication.setUp(self)
+ self.called = False
+ self.timeline = QTimeLine(100)
+
+ def tearDown(self):
+ del self.called
+ del self.timeline
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ UsesQApplication.tearDown(self)
+
+ def testSignalWithIntArgument(self):
+
+ def valueChangedSlot(value):
+ self.called = True
+ self.assertEqual(type(value), float)
+ self.app.quit()
+
+ self.timeline.valueChanged.connect(valueChangedSlot)
+ self.timeline.start()
+
+ self.app.exec()
+ self.assertTrue(self.called)
+
+ def testSignalWithoutArguments(self):
+
+ def finishedSlot():
+ self.called = True
+ self.app.quit()
+
+ self.timeline.finished.connect(finishedSlot)
+ self.timeline.start()
+
+ self.app.exec()
+ self.assertTrue(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/ref03_test.py b/sources/pyside6/tests/signals/ref03_test.py
new file mode 100644
index 000000000..c43c2e549
--- /dev/null
+++ b/sources/pyside6/tests/signals/ref03_test.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env 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(False)
+
+from PySide6.QtCore import QObject
+
+
+class DisconnectSignalsTest(unittest.TestCase):
+
+ def setUp(self):
+ self.emitter = QObject()
+
+ def tearDown(self):
+ del self.emitter
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testConnectionRefCount(self):
+
+ def destroyedSlot():
+ pass
+
+ self.assertEqual(sys.getrefcount(destroyedSlot), 2)
+ self.emitter.destroyed.connect(destroyedSlot)
+ self.assertEqual(sys.getrefcount(destroyedSlot), 3)
+ self.emitter.destroyed.disconnect(destroyedSlot)
+ self.assertEqual(sys.getrefcount(destroyedSlot), 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/ref04_test.py b/sources/pyside6/tests/signals/ref04_test.py
new file mode 100644
index 000000000..fce801456
--- /dev/null
+++ b/sources/pyside6/tests/signals/ref04_test.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env 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(False)
+
+from PySide6.QtCore import QObject, Signal
+
+
+class ExtQObject(QObject):
+
+ mySignal = Signal()
+
+ def __init__(self):
+ super().__init__()
+
+
+class UserSignalTest(unittest.TestCase):
+
+ def setUp(self):
+ self.emitter = ExtQObject()
+ self.counter = 0
+
+ def tearDown(self):
+ del self.emitter
+ del self.counter
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def testConnectEmitDisconnect(self):
+
+ def slot():
+ self.counter += 1
+
+ self.emitter.mySignal.connect(slot)
+
+ self.assertEqual(self.counter, 0)
+ self.emitter.mySignal.emit()
+ self.assertEqual(self.counter, 1)
+ self.emitter.mySignal.emit()
+ self.assertEqual(self.counter, 2)
+
+ self.emitter.mySignal.disconnect(slot)
+
+ self.emitter.mySignal.emit()
+ self.assertEqual(self.counter, 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/ref05_test.py b/sources/pyside6/tests/signals/ref05_test.py
new file mode 100644
index 000000000..fb9debf39
--- /dev/null
+++ b/sources/pyside6/tests/signals/ref05_test.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env 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(False)
+
+from PySide6.QtCore import QObject, QTimeLine, Slot
+from helper.usesqapplication import UsesQApplication
+
+
+class ExtQObject(QObject):
+
+ def __init__(self):
+ super().__init__()
+ self.counter = 0
+
+ @Slot('qreal')
+ def foo(self, value):
+ self.counter += 1
+
+
+class UserSlotTest(UsesQApplication):
+
+ def setUp(self):
+ UsesQApplication.setUp(self)
+ self.receiver = ExtQObject()
+ self.timeline = QTimeLine(100)
+
+ def tearDown(self):
+ del self.timeline
+ del self.receiver
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ UsesQApplication.tearDown(self)
+
+ def testUserSlot(self):
+ self.timeline.setUpdateInterval(10)
+
+ self.timeline.finished.connect(self.app.quit)
+
+ self.timeline.valueChanged.connect(self.receiver.foo)
+ self.timeline.start()
+
+ self.app.exec()
+
+ self.assertTrue(self.receiver.counter > 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/ref06_test.py b/sources/pyside6/tests/signals/ref06_test.py
new file mode 100644
index 000000000..a827131db
--- /dev/null
+++ b/sources/pyside6/tests/signals/ref06_test.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env 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(False)
+
+from PySide6.QtCore import QObject, QTimeLine, Signal, Slot
+from helper.usesqapplication import UsesQApplication
+
+
+class ExtQObject(QObject):
+ signalbetween = Signal('qreal')
+
+ def __init__(self):
+ super().__init__()
+ self.counter = 0
+
+ @Slot('qreal')
+ def foo(self, value):
+ self.counter += 1
+
+
+class SignaltoSignalTest(UsesQApplication):
+
+ def setUp(self):
+ UsesQApplication.setUp(self)
+ self.receiver = ExtQObject()
+ self.timeline = QTimeLine(100)
+
+ def tearDown(self):
+ del self.timeline
+ del self.receiver
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ UsesQApplication.tearDown(self)
+
+ def testSignaltoSignal(self):
+ self.timeline.setUpdateInterval(10)
+
+ self.timeline.finished.connect(self.app.quit)
+
+ self.timeline.valueChanged.connect(self.receiver.signalbetween)
+ self.receiver.signalbetween.connect(self.receiver.foo)
+
+ self.timeline.start()
+
+ self.app.exec()
+
+ self.assertTrue(self.receiver.counter > 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/segfault_proxyparent_test.py b/sources/pyside6/tests/signals/segfault_proxyparent_test.py
new file mode 100644
index 000000000..cb0df0978
--- /dev/null
+++ b/sources/pyside6/tests/signals/segfault_proxyparent_test.py
@@ -0,0 +1,78 @@
+# 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
+
+# Description of the problem
+# After creating an PyObject that inherits from QObject, connecting it,
+# deleting it and later creating another Python QObject-based object, this
+# new object will point to the same memory position as the first one.
+
+# Somehow the underlying QObject also points to the same position.
+
+
+class Sender(QObject):
+
+ bar = Signal(int)
+
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+
+
+class Joe(QObject):
+
+ bar = Signal(int)
+
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+
+
+class SegfaultCase(unittest.TestCase):
+ """Test case for the segfault happening when parent() is called inside
+ ProxyObject"""
+
+ def setUp(self):
+ self.called = False
+
+ def tearDown(self):
+ try:
+ del self.args
+ except: # noqa: E722
+ pass
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def callback(self, *args):
+ if tuple(self.args) == args:
+ self.called = True
+
+ def testSegfault(self):
+ """Regression: Segfault for qobjects in the same memory position."""
+ obj = Sender()
+ obj.bar.connect(self.callback)
+ self.args = (33,)
+ obj.bar.emit(self.args[0])
+ self.assertTrue(self.called)
+ del obj
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ obj = Joe()
+ obj.bar.connect(self.callback)
+ self.args = (33,)
+ obj.bar.emit(self.args[0])
+ self.assertTrue(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/self_connect_test.py b/sources/pyside6/tests/signals/self_connect_test.py
new file mode 100644
index 000000000..08ca725f8
--- /dev/null
+++ b/sources/pyside6/tests/signals/self_connect_test.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env 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
+
+'''Using self.connect(signal, method)'''
+
+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, Slot
+from PySide6.QtWidgets import QPushButton, QWidget
+
+from helper.usesqapplication import UsesQApplication
+
+
+class Receiver(QObject):
+ def __init__(self, p=None):
+ super().__init__(p)
+ self.triggered = False
+
+ @Slot(bool, int)
+ def default_parameter_slot(self, bool_value, int_value=0):
+ self.triggered = True
+
+
+class SelfConnect(UsesQApplication):
+
+ def testButtonClickClose(self):
+ button = QPushButton()
+ button.clicked.connect(button.close)
+
+ button.show()
+ self.assertTrue(button.isVisible())
+ button.click()
+ self.assertTrue(not button.isVisible())
+
+ def testWindowButtonClickClose(self):
+ button = QPushButton()
+ window = QWidget()
+ button.clicked.connect(window.close)
+
+ window.show()
+ self.assertTrue(window.isVisible())
+ button.click()
+ self.assertTrue(not window.isVisible())
+
+ def testDefaultParameters(self):
+ button = QPushButton()
+ receiver = Receiver(button)
+ button.clicked.connect(receiver.default_parameter_slot)
+ button.clicked.connect(button.close)
+ button.show()
+ button.click()
+ self.assertTrue(receiver.triggered)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/short_circuit_test.py b/sources/pyside6/tests/signals/short_circuit_test.py
new file mode 100644
index 000000000..1ad4bc24c
--- /dev/null
+++ b/sources/pyside6/tests/signals/short_circuit_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 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
+
+
+class Sender(QObject):
+ """Sender class used in this test."""
+
+ foo = Signal()
+ foo_int = Signal(int)
+ foo_int_int_string = Signal(int, int, str)
+ foo_int_qobject = Signal(int, QObject)
+
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+
+
+class ShortCircuitSignals(unittest.TestCase):
+ def setUp(self):
+ self.called = False
+
+ def tearDown(self):
+ try:
+ del self.args
+ except: # noqa: E722
+ pass
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def callback(self, *args):
+ if tuple(self.args) == args:
+ self.called = True
+
+ def testNoArgs(self):
+ """Short circuit signal without arguments"""
+ obj1 = Sender()
+ obj1.foo.connect(self.callback)
+ self.args = tuple()
+ obj1.foo.emit(*self.args)
+ self.assertTrue(self.called)
+
+ def testWithArgs(self):
+ """Short circuit signal with integer arguments"""
+ obj1 = Sender()
+
+ obj1.foo_int.connect(self.callback)
+ self.args = (42,)
+ obj1.foo_int.emit(*self.args)
+
+ self.assertTrue(self.called)
+
+ def testMultipleArgs(self):
+ """Short circuit signal with multiple arguments"""
+ obj1 = Sender()
+
+ obj1.foo_int_int_string.connect(self.callback)
+ self.args = (42, 33, 'char')
+ obj1.foo_int_int_string.emit(*self.args)
+
+ self.assertTrue(self.called)
+
+ def testComplexArgs(self):
+ """Short circuit signal with complex arguments"""
+ obj1 = Sender()
+
+ obj1.foo_int_qobject.connect(self.callback)
+ self.args = (42, obj1)
+
+ obj1.foo_int_qobject.emit(*self.args)
+ self.assertTrue(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal2signal_connect_test.py b/sources/pyside6/tests/signals/signal2signal_connect_test.py
new file mode 100644
index 000000000..31129f7a1
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal2signal_connect_test.py
@@ -0,0 +1,121 @@
+# 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 case for signal to signal connections.'''
+
+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
+
+
+class Sender(QObject):
+
+ mysignal_int = Signal(int)
+ mysignal_int_int = Signal(int, int)
+ mysignal_string = Signal(str)
+
+
+class Forwarder(Sender):
+
+ forward = Signal()
+ forward_qobject = Signal(QObject)
+
+
+def cute_slot():
+ pass
+
+
+class TestSignal2SignalConnect(unittest.TestCase):
+ '''Test case for signal to signal connections'''
+
+ def setUp(self):
+ # Set up the basic resources needed
+ self.sender = Sender()
+ self.forwarder = Forwarder()
+ self.args = None
+ self.called = False
+
+ def tearDown(self):
+ # Delete used resources
+ try:
+ del self.sender
+ except: # noqa: E722
+ pass
+ try:
+ del self.forwarder
+ except: # noqa: E722
+ pass
+ del self.args
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def callback_noargs(self):
+ # Default callback without arguments
+ self.called = True
+
+ def callback_args(self, *args):
+ # Default callback with arguments
+ if args == self.args:
+ self.called = True
+ else:
+ raise TypeError("Invalid arguments")
+
+ def callback_qobject(self, *args):
+ # Default callback for QObject as argument
+ if args[0].objectName() == self.args[0]:
+ self.called = True
+ else:
+ raise TypeError("Invalid arguments")
+
+ def testSignalWithoutArguments(self):
+ self.sender.destroyed.connect(self.forwarder.forward)
+ self.forwarder.forward.connect(self.callback_noargs)
+ del self.sender
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertTrue(self.called)
+
+ def testSignalWithOnePrimitiveTypeArgument(self):
+ self.sender.mysignal_int.connect(self.forwarder.mysignal_int)
+ self.forwarder.mysignal_int.connect(self.callback_args)
+ self.args = (19,)
+ self.sender.mysignal_int.emit(*self.args)
+ self.assertTrue(self.called)
+
+ def testSignalWithMultiplePrimitiveTypeArguments(self):
+ self.sender.mysignal_int_int.connect(self.forwarder.mysignal_int_int)
+ self.forwarder.mysignal_int_int.connect(self.callback_args)
+ self.args = (23, 29)
+ self.sender.mysignal_int_int.emit(*self.args)
+ self.assertTrue(self.called)
+
+ def testSignalWithOneStringArgument(self):
+ self.sender.mysignal_string.connect(self.forwarder.mysignal_string)
+ self.forwarder.mysignal_string.connect(self.callback_args)
+ self.args = ('myargument',)
+ self.sender.mysignal_string.emit(*self.args)
+ self.assertTrue(self.called)
+
+ def testSignalWithOneQObjectArgument(self):
+ self.sender.destroyed.connect(self.forwarder.forward_qobject)
+ self.forwarder.forward_qobject.connect(self.callback_qobject)
+
+ obj_name = 'sender'
+ self.sender.setObjectName(obj_name)
+ self.args = (obj_name, )
+ del self.sender
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ self.assertTrue(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_across_threads.py b/sources/pyside6/tests/signals/signal_across_threads.py
new file mode 100644
index 000000000..91b1ca986
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_across_threads.py
@@ -0,0 +1,82 @@
+# 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 case for PYSIDE-1354: Ensure that slots are invoked from the receiver's
+thread context when using derived classes (and thus, a global receiver).'''
+
+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, QThread, QTimer, Slot
+from helper.usesqapplication import UsesQApplication
+
+
+class ReceiverBase(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.senderThread = None
+
+ @Slot()
+ def slot_function(self):
+ self.senderThread = QThread.currentThread()
+
+
+class Receiver(ReceiverBase):
+ pass
+
+
+class TestThread(QThread):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ def run(self):
+ pass
+
+
+class SignalAcrossThreads(UsesQApplication):
+ def setUp(self):
+ UsesQApplication.setUp(self)
+ self._timer_tick = 0
+ self._timer = QTimer()
+ self._timer.setInterval(20)
+ self._timer.timeout.connect(self._control_test)
+ self._worker_thread = TestThread()
+
+ def tearDown(self):
+ UsesQApplication.tearDown(self)
+
+ @Slot()
+ def _control_test(self):
+ if self._timer_tick == 0:
+ self._worker_thread.start()
+ elif self._timer_tick == 1:
+ self._worker_thread.wait()
+ else:
+ self._timer.stop()
+ self.app.quit()
+ self._timer_tick += 1
+
+ def test(self):
+ worker_thread_receiver = Receiver()
+ worker_thread_receiver.moveToThread(self._worker_thread)
+ self._worker_thread.started.connect(worker_thread_receiver.slot_function)
+
+ main_thread = QThread.currentThread()
+ main_thread_receiver = Receiver()
+ self._worker_thread.started.connect(main_thread_receiver.slot_function)
+
+ self._timer.start()
+ self.app.exec()
+
+ self.assertEqual(worker_thread_receiver.senderThread, self._worker_thread)
+ self.assertEqual(main_thread_receiver.senderThread, main_thread)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_autoconnect_test.py b/sources/pyside6/tests/signals/signal_autoconnect_test.py
new file mode 100644
index 000000000..51d1cea3a
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_autoconnect_test.py
@@ -0,0 +1,41 @@
+# 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 QMetaObject, Slot
+from PySide6.QtWidgets import QApplication, QPushButton, QWidget
+
+
+class MyObject(QWidget):
+ def __init__(self, parent=None):
+ QWidget.__init__(self, parent)
+ self._method_called = False
+
+ @Slot()
+ def on_button_clicked(self):
+ self._method_called = True
+
+
+class AutoConnectionTest(unittest.TestCase):
+
+ def testConnection(self):
+ app = QApplication([]) # noqa: F841
+
+ win = MyObject()
+ btn = QPushButton("click", win)
+ btn.setObjectName("button")
+ QMetaObject.connectSlotsByName(win)
+ btn.click()
+ self.assertTrue(win._method_called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_connectiontype_support_test.py b/sources/pyside6/tests/signals/signal_connectiontype_support_test.py
new file mode 100644
index 000000000..0a69c1e02
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_connectiontype_support_test.py
@@ -0,0 +1,42 @@
+# 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, Signal, Qt
+
+
+class Sender(QObject):
+ """Dummy class used in this test."""
+
+ foo = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+class TestConnectionTypeSupport(unittest.TestCase):
+ def callback(self, *args):
+ if tuple(self.args) == args:
+ self.called = True
+
+ def testNoArgs(self):
+ """Connect signal using a Qt.ConnectionType as argument"""
+ obj1 = Sender()
+
+ obj1.foo.connect(self.callback, Qt.DirectConnection)
+ self.args = tuple()
+ obj1.foo.emit(*self.args)
+
+ self.assertTrue(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_emission_gui_test.py b/sources/pyside6/tests/signals/signal_emission_gui_test.py
new file mode 100644
index 000000000..5a49b9d12
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_emission_gui_test.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env 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
+
+"""Tests covering signal emission and receiving to python slots"""
+
+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.QtWidgets import QSpinBox, QPushButton
+
+from helper.basicpyslotcase import BasicPySlotCase
+from helper.usesqapplication import UsesQApplication
+
+
+class ButtonPySlot(UsesQApplication, BasicPySlotCase):
+ """Tests the connection of python slots to QPushButton signals"""
+
+ def testButtonClicked(self):
+ """Connection of a python slot to QPushButton.clicked()"""
+ button = QPushButton('Mylabel')
+ button.clicked.connect(self.cb)
+ self.args = tuple()
+ button.clicked.emit()
+ self.assertTrue(self.called)
+
+ def testButtonClick(self):
+ """Indirect qt signal emission using the QPushButton.click() method """
+ button = QPushButton('label')
+ button.clicked.connect(self.cb)
+ self.args = tuple()
+ button.click()
+ self.assertTrue(self.called)
+
+
+class SpinBoxPySlot(UsesQApplication, BasicPySlotCase):
+ """Tests the connection of python slots to QSpinBox signals"""
+
+ def setUp(self):
+ super(SpinBoxPySlot, self).setUp()
+ self.spin = QSpinBox()
+
+ def tearDown(self):
+ del self.spin
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super(SpinBoxPySlot, self).tearDown()
+
+ def testSpinBoxValueChanged(self):
+ """Connection of a python slot to QSpinBox.valueChanged(int)"""
+ self.spin.valueChanged.connect(self.cb)
+ self.args = [3]
+ self.spin.valueChanged.emit(*self.args)
+ self.assertTrue(self.called)
+
+ def testSpinBoxValueChangedImplicit(self):
+ """Indirect qt signal emission using QSpinBox.setValue(int)"""
+ self.spin.valueChanged.connect(self.cb)
+ self.args = [42]
+ self.spin.setValue(self.args[0])
+ self.assertTrue(self.called)
+
+ def atestSpinBoxValueChangedFewArgs(self):
+ """Emission of signals with fewer arguments than needed"""
+ self.spin.valueChanged.connect(self.cb)
+ self.args = (554,)
+ self.assertRaises(TypeError, self.spin.valueChanged.emit)
+
+
+class QSpinBoxQtSlots(UsesQApplication):
+ """Tests the connection to QSpinBox qt slots"""
+
+ qapplication = True
+
+ def testSetValueIndirect(self):
+ """Indirect signal emission: QSpinBox using valueChanged(int)/setValue(int)"""
+ spinSend = QSpinBox()
+ spinRec = QSpinBox()
+
+ spinRec.setValue(5)
+
+ spinSend.valueChanged.connect(spinRec.setValue)
+ self.assertEqual(spinRec.value(), 5)
+ spinSend.setValue(3)
+ self.assertEqual(spinRec.value(), 3)
+ self.assertEqual(spinSend.value(), 3)
+
+ def testSetValue(self):
+ """Direct signal emission: QSpinBox using valueChanged(int)/setValue(int)"""
+ spinSend = QSpinBox()
+ spinRec = QSpinBox()
+
+ spinRec.setValue(5)
+ spinSend.setValue(42)
+
+ spinSend.valueChanged.connect(spinRec.setValue)
+ self.assertEqual(spinRec.value(), 5)
+ self.assertEqual(spinSend.value(), 42)
+ spinSend.valueChanged.emit(3)
+
+ self.assertEqual(spinRec.value(), 3)
+ # Direct emission shouldn't change the value of the emitter
+ self.assertEqual(spinSend.value(), 42)
+
+ spinSend.valueChanged.emit(66)
+ self.assertEqual(spinRec.value(), 66)
+ self.assertEqual(spinSend.value(), 42)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_emission_test.py b/sources/pyside6/tests/signals/signal_emission_test.py
new file mode 100644
index 000000000..b31d89c2f
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_emission_test.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env 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
+
+"""Tests covering signal emission and receiving to python slots"""
+
+import functools
+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, SIGNAL, QProcess, QTimeLine
+
+from helper.usesqapplication import UsesQApplication
+
+
+class ArgsOnEmptySignal(UsesQApplication):
+ '''Trying to emit a signal without arguments passing some arguments'''
+
+ def testArgsToNoArgsSignal(self):
+ '''Passing arguments to a signal without arguments'''
+ process = QProcess()
+ self.assertRaises(TypeError, process.started.emit, 42)
+
+
+class MoreArgsOnEmit(UsesQApplication):
+ '''Trying to pass more args than needed to emit (signals with args)'''
+
+ def testMoreArgs(self):
+ '''Passing more arguments than needed'''
+ process = QProcess()
+ self.assertRaises(TypeError, process.finished.emit, 55, QProcess.ExitStatus.NormalExit, 42)
+
+
+class Sender(QObject):
+ '''Sender class'''
+
+ dummy = Signal()
+ dummy_int = Signal(int)
+
+
+class PythonSignalToCppSlots(UsesQApplication):
+ '''Connect python signals to C++ slots'''
+
+ def testWithoutArgs(self):
+ '''Connect python signal to QTimeLine.toggleDirection()'''
+ timeline = QTimeLine()
+ sender = Sender()
+ sender.dummy.connect(timeline.toggleDirection)
+
+ orig_dir = timeline.direction()
+ sender.dummy.emit()
+ new_dir = timeline.direction()
+
+ if orig_dir == QTimeLine.Forward:
+ self.assertEqual(new_dir, QTimeLine.Backward)
+ else:
+ self.assertEqual(new_dir, QTimeLine.Forward)
+
+ def testWithArgs(self):
+ '''Connect python signals to QTimeLine.setCurrentTime(int)'''
+ timeline = QTimeLine()
+ sender = Sender()
+
+ sender.dummy_int.connect(timeline.setCurrentTime)
+
+ current = timeline.currentTime()
+ sender.dummy_int.emit(current + 42)
+ self.assertEqual(timeline.currentTime(), current + 42)
+
+
+class CppSignalsToCppSlots(UsesQApplication):
+ '''Connection between C++ slots and signals'''
+
+ def testWithoutArgs(self):
+ '''Connect QProcess.started() to QTimeLine.togglePaused()'''
+ process = QProcess()
+ timeline = QTimeLine()
+
+ process.finished.connect(timeline.toggleDirection)
+
+ orig_dir = timeline.direction()
+
+ process.start(sys.executable, ['-c', '"print 42"'])
+ self.assertTrue(process.waitForStarted())
+ self.assertTrue(process.waitForFinished())
+
+ new_dir = timeline.direction()
+
+ if orig_dir == QTimeLine.Forward:
+ self.assertEqual(new_dir, QTimeLine.Backward)
+ else:
+ self.assertEqual(new_dir, QTimeLine.Forward)
+
+
+called = False
+
+
+def someSlot(args=None):
+ global called
+ called = True
+
+
+class DynamicSignalsToFuncPartial(UsesQApplication):
+
+ def testIt(self):
+ global called
+ called = False
+ o = Sender()
+ o.dummy.connect(functools.partial(someSlot, "partial .."))
+ o.dummy.emit()
+ self.assertTrue(called)
+
+
+class EmitUnknownType(UsesQApplication):
+ def testIt(self):
+ a = QObject()
+ a.connect(SIGNAL('foobar(Dummy)'), lambda x: 42) # Just connect with an unknown type
+ self.assertRaises(TypeError, a.emit, SIGNAL('foobar(Dummy)'), 22)
+
+
+class EmitEnum(UsesQApplication):
+ """Test emission of enum arguments"""
+
+ def slot(self, arg):
+ self.arg = arg
+
+ def testIt(self):
+ self.arg = None
+ p = QProcess()
+ p.stateChanged.connect(self.slot)
+ p.stateChanged.emit(QProcess.NotRunning)
+ self.assertEqual(self.arg, QProcess.NotRunning)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_enum_test.py b/sources/pyside6/tests/signals/signal_enum_test.py
new file mode 100644
index 000000000..a792e9b0c
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_enum_test.py
@@ -0,0 +1,57 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+from enum 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(False)
+
+from PySide6.QtCore import QObject, Signal, Slot
+
+
+class Colors(Enum):
+ red = 1
+ green = 2
+ blue = 3
+
+
+class Obj(QObject):
+ enum_signal = Signal(Colors)
+ object_signal = Signal(object)
+
+ def __init__(self, parent=None):
+ QObject.__init__(self, parent)
+ self.enum_signal.connect(self.get_result)
+ self.object_signal.connect(self.get_result)
+ self.value = -1
+
+ @Slot()
+ def get_result(self, i):
+ self.value = i
+
+
+class SignalEnumTests(unittest.TestCase):
+ '''Test Signal with enum.Enum'''
+
+ def testSignal(self):
+ o = Obj()
+ # Default value
+ self.assertEqual(o.value, -1)
+
+ # Enum Signal
+ o.enum_signal.emit(Colors.green)
+ self.assertEqual(o.value, Colors.green)
+
+ # object Signal
+ o.object_signal.emit(Colors.red)
+ self.assertEqual(o.value, Colors.red)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_func_test.py b/sources/pyside6/tests/signals/signal_func_test.py
new file mode 100644
index 000000000..d441d4de9
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_func_test.py
@@ -0,0 +1,31 @@
+# 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 SIGNAL, SLOT
+
+
+class SIGNALSLOTTests(unittest.TestCase):
+ '''Test the output of SIGNAL and SLOT.'''
+
+ def testSIGNAL(self):
+ # SIGNAL function
+ a = "foobar"
+ self.assertEqual(str(SIGNAL(a)), "2foobar")
+
+ def testSLOT(self):
+ # SLOT function
+ a = "foobar"
+ self.assertEqual(str(SLOT(a)), "1foobar")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_manager_refcount_test.py b/sources/pyside6/tests/signals/signal_manager_refcount_test.py
new file mode 100644
index 000000000..955d5b65b
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_manager_refcount_test.py
@@ -0,0 +1,36 @@
+#!/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.QtCore import QObject
+
+
+class SignalManagerRefCount(unittest.TestCase):
+ """Simple test case to check if the signal_manager is erroneously incrementing the
+ object refcounter."""
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testObjectRefcount(self):
+ """Emission of QObject.destroyed() to a python slot"""
+ def callback():
+ pass
+ obj = QObject()
+ refcount = sys.getrefcount(obj)
+ obj.destroyed.connect(callback)
+ self.assertEqual(refcount, sys.getrefcount(obj))
+ obj.destroyed.disconnect(callback)
+ self.assertEqual(refcount, sys.getrefcount(obj))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_newenum_test.py b/sources/pyside6/tests/signals/signal_newenum_test.py
new file mode 100644
index 000000000..5fbb875af
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_newenum_test.py
@@ -0,0 +1,50 @@
+# 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, Qt, Slot, Signal
+
+
+class Receiver(QObject):
+ def __init__(self):
+ super().__init__()
+ self.result = 0
+
+ @Slot(Qt.Alignment, str)
+ def handler(self, e, s):
+ print('handler', e, "type=", type(e).__name__, s)
+ self.result += 1
+
+
+class Sender(QObject):
+ test_sig = Signal(Qt.AlignmentFlag, str)
+
+ def __init__(self):
+ super().__init__()
+
+ def emit_test_sig(self):
+ self.test_sig.emit(Qt.AlignLeft, "bla")
+
+
+class TestSignalNewEnum(unittest.TestCase):
+ """Test for PYSIDE-2095, signals with new enums in Python 3.11."""
+
+ def testIt(self):
+ sender = Sender()
+ receiver = Receiver()
+ sender.test_sig.connect(receiver.handler)
+
+ sender.emit_test_sig()
+ self.assertEqual(receiver.result, 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_number_limit_test.py b/sources/pyside6/tests/signals/signal_number_limit_test.py
new file mode 100644
index 000000000..29825fe50
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_number_limit_test.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env 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.QtCore import QObject, Signal
+
+
+class Emitter(QObject):
+ s1 = Signal()
+ s2 = Signal()
+ s3 = Signal()
+ s4 = Signal()
+ s5 = Signal()
+ s6 = Signal()
+ s7 = Signal()
+ s8 = Signal()
+ s9 = Signal()
+ s10 = Signal()
+ s11 = Signal()
+ s12 = Signal()
+ s13 = Signal()
+ s14 = Signal()
+
+
+class SignalNumberLimitTest(unittest.TestCase):
+ def myCb(self):
+ self._count += 1
+
+ def testBug(self):
+ e = Emitter()
+ e.s1.connect(self.myCb)
+ e.s2.connect(self.myCb)
+ e.s3.connect(self.myCb)
+ e.s4.connect(self.myCb)
+ e.s5.connect(self.myCb)
+ e.s6.connect(self.myCb)
+ e.s7.connect(self.myCb)
+ e.s8.connect(self.myCb)
+ e.s9.connect(self.myCb)
+ e.s10.connect(self.myCb)
+ e.s11.connect(self.myCb)
+ e.s12.connect(self.myCb)
+ e.s13.connect(self.myCb)
+ e.s14.connect(self.myCb)
+
+ self._count = 0
+ e.s1.emit()
+ e.s2.emit()
+ e.s3.emit()
+ e.s4.emit()
+ e.s5.emit()
+ e.s6.emit()
+ e.s7.emit()
+ e.s8.emit()
+ e.s9.emit()
+ e.s10.emit()
+ e.s11.emit()
+ e.s12.emit()
+ e.s13.emit()
+ e.s14.emit()
+ self.assertEqual(self._count, 14)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_object_test.py b/sources/pyside6/tests/signals/signal_object_test.py
new file mode 100644
index 000000000..607f51813
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_object_test.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env 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.QtCore import QTimer, Signal, QObject, Slot, Qt
+from helper.usesqapplication import UsesQApplication
+
+
+class MyObject(QTimer):
+ sig1 = Signal()
+ sig2 = Signal(int, name='rangeChanged')
+ sig3 = Signal(int)
+ sig4 = Signal((int,), (str,))
+ sig5 = Signal((str,), (int,))
+ sig6 = Signal(QObject)
+
+ @Slot(int)
+ def myRange(self, r):
+ self._range = r
+
+ def slot1(self):
+ self._called = True
+
+ def slotString(self, s):
+ self._s = s
+
+ def slotObject(self, o):
+ self._o = o
+
+
+class SignalObjectTest(UsesQApplication):
+ def cb(self):
+ self._cb_called = True
+ self.app.exit()
+
+ def testsingleConnect(self):
+ o = MyObject()
+ o.sig1.connect(o.slot1)
+ o.sig1.emit()
+ self.assertTrue(o._called)
+
+ def testSignalWithArgs(self):
+ o = MyObject()
+ o.sig3.connect(o.myRange)
+ o.sig3.emit(10)
+ self.assertEqual(o._range, 10)
+
+ def testSignatureParse(self):
+ o = MyObject()
+ o.sig2.connect(o.myRange)
+ o.sig2.emit(10)
+
+ def testDictOperator(self):
+ o = MyObject()
+ o.sig4[str].connect(o.slotString)
+ o.sig4[str].emit("PySide")
+ self.assertEqual(o._s, "PySide")
+
+ def testGeneretedSignal(self):
+ o = MyObject()
+ o.timeout.connect(self.cb)
+ o.start(100)
+ self.app.exec()
+ self.assertTrue(self._cb_called)
+
+ def testConnectionType(self):
+ o = MyObject()
+ o.timeout.connect(self.cb, type=Qt.DirectConnection)
+ o.start(100)
+ self.app.exec()
+ self.assertTrue(self._cb_called)
+
+ def testSignalWithSignal(self):
+ o = MyObject()
+ o.sig2.connect(o.myRange)
+ o.sig5.connect(o.sig2)
+ o.sig5[int].emit(10)
+ self.assertEqual(o._range, 10)
+
+ def testSignalWithObject(self):
+ o = MyObject()
+ o.sig6.connect(o.slotObject)
+ arg = QObject()
+ o.sig6.emit(arg)
+ self.assertEqual(arg, o._o)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_signature_test.py b/sources/pyside6/tests/signals/signal_signature_test.py
new file mode 100644
index 000000000..e8f08b2d9
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_signature_test.py
@@ -0,0 +1,105 @@
+# 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 case for signal signature received by QObject::connectNotify().'''
+
+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, SIGNAL, SLOT
+from helper.usesqapplication import UsesQApplication
+
+
+called = False
+name = "Old"
+
+
+class Sender(QObject):
+ dummySignal = Signal()
+
+
+class Obj(QObject):
+ dummySignalArgs = Signal(str)
+ numberSignal = Signal(int)
+
+ def __init__(self):
+ super().__init__()
+ self.signal = ''
+
+ def connectNotify(self, signal):
+ self.signal = signal
+
+ @staticmethod
+ def static_method():
+ global called
+ called = True
+
+ @staticmethod
+ def static_method_args(arg="default"):
+ global name
+ name = arg
+
+
+def callback(arg=None):
+ pass
+
+
+def callback_empty():
+ pass
+
+
+class TestConnectNotifyWithNewStyleSignals(UsesQApplication):
+ '''Test case for signal signature received by QObject::connectNotify().'''
+
+ def testOldStyle(self):
+ sender = Obj()
+ receiver = QObject()
+ sender.connect(SIGNAL('destroyed()'), receiver, SLOT('deleteLater()'))
+ # When connecting to a regular slot, and not a python callback function, QObject::connect
+ # will use the non-cloned method signature, so connectinc to destroyed() will actually
+ # connect to destroyed(QObject*).
+ self.assertEqual(sender.signal.methodSignature(), 'destroyed(QObject*)')
+
+ def testOldStyleWithPythonCallback(self):
+ sender = Obj()
+ sender.connect(SIGNAL('destroyed()'), callback)
+ self.assertEqual(sender.signal.methodSignature(), 'destroyed()')
+
+ def testNewStyle(self):
+ sender = Obj()
+
+ sender.destroyed.connect(callback_empty)
+ self.assertEqual(sender.signal.methodSignature(), 'destroyed()')
+
+ sender.destroyed[QObject].connect(callback)
+ self.assertEqual(sender.signal.methodSignature(), 'destroyed(QObject*)')
+
+ def testStaticSlot(self):
+ global called
+ sender = Sender()
+ sender.dummySignal.connect(Obj.static_method)
+ sender.dummySignal.emit()
+ self.assertTrue(called)
+
+ def testStaticSlotArgs(self):
+ global name
+ sender = Obj()
+ sender.dummySignalArgs.connect(Obj.static_method_args)
+ sender.dummySignalArgs[str].emit("New")
+ self.assertEqual(name, "New")
+
+ def testLambdaSlot(self):
+ sender = Obj()
+ sender.numberSignal[int].connect(lambda x: 42)
+ with self.assertRaises(IndexError):
+ sender.numberSignal[str].emit("test")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signal_with_primitive_type_test.py b/sources/pyside6/tests/signals/signal_with_primitive_type_test.py
new file mode 100644
index 000000000..01492b333
--- /dev/null
+++ b/sources/pyside6/tests/signals/signal_with_primitive_type_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)
+
+from PySide6.QtCore import QCoreApplication, QTimeLine
+
+
+class SignalPrimitiveTypeTest(unittest.TestCase):
+
+ def signalValueChanged(self, v):
+ self.called = True
+ self._app.quit()
+
+ def createTimeLine(self):
+ self.called = False
+ tl = QTimeLine(10000)
+ tl.valueChanged.connect(self.signalValueChanged)
+ return tl
+
+ def testTimeLine(self):
+ self._valueChangedCount = 0
+ self._app = QCoreApplication([])
+ tl = self.createTimeLine()
+ tl.start()
+ self._app.exec()
+ self.assertTrue(self.called)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/signals.pyproject b/sources/pyside6/tests/signals/signals.pyproject
new file mode 100644
index 000000000..b63724eaf
--- /dev/null
+++ b/sources/pyside6/tests/signals/signals.pyproject
@@ -0,0 +1,19 @@
+{
+ "files": ["anonymous_slot_leak_test.py", "args_dont_match_test.py",
+ "bug_189.py", "bug_311.py", "bug_312.py", "bug_319.py", "bug_79.py",
+ "decorators_test.py", "disconnect_test.py", "invalid_callback_test.py",
+ "lambda_gui_test.py", "lambda_test.py", "leaking_signal_test.py",
+ "multiple_connections_gui_test.py", "multiple_connections_test.py",
+ "pysignal_test.py", "qobject_callable_connect_test.py", "qobject_destroyed_test.py",
+ "qobject_receivers_test.py", "qobject_sender_test.py", "ref01_test.py",
+ "ref02_test.py", "ref03_test.py", "ref04_test.py", "ref05_test.py",
+ "ref06_test.py", "segfault_proxyparent_test.py",
+ "self_connect_test.py", "short_circuit_test.py",
+ "signal2signal_connect_test.py", "signal_across_threads.py",
+ "signal_autoconnect_test.py", "signal_connectiontype_support_test.py",
+ "signal_emission_gui_test.py", "signal_emission_test.py",
+ "signal_enum_test.py", "signal_func_test.py", "signal_manager_refcount_test.py",
+ "signal_newenum_test.py", "signal_number_limit_test.py",
+ "signal_object_test.py", "signal_signature_test.py", "signal_with_primitive_type_test.py",
+ "slot_reference_count_test.py", "static_metaobject_test.py"]
+}
diff --git a/sources/pyside6/tests/signals/slot_reference_count_test.py b/sources/pyside6/tests/signals/slot_reference_count_test.py
new file mode 100644
index 000000000..9d5c73652
--- /dev/null
+++ b/sources/pyside6/tests/signals/slot_reference_count_test.py
@@ -0,0 +1,70 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+''' Forced disconnection: Delete one end of the signal connection'''
+
+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
+
+
+class Dummy(QObject):
+ foo = Signal()
+
+ def dispatch(self):
+ self.foo.emit()
+
+
+class PythonSignalRefCount(unittest.TestCase):
+
+ def setUp(self):
+ self.emitter = Dummy()
+
+ def tearDown(self):
+ self.emitter
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefCount(self):
+ def cb(*args):
+ pass
+
+ self.assertEqual(sys.getrefcount(cb), 2)
+
+ self.emitter.foo.connect(cb)
+ self.assertEqual(sys.getrefcount(cb), 3)
+
+ self.emitter.foo.disconnect(cb)
+ self.assertEqual(sys.getrefcount(cb), 2)
+
+
+class CppSignalRefCount(unittest.TestCase):
+
+ def setUp(self):
+ self.emitter = QObject()
+
+ def tearDown(self):
+ self.emitter
+
+ @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
+ def testRefCount(self):
+ def cb(*args):
+ pass
+
+ self.assertEqual(sys.getrefcount(cb), 2)
+
+ self.emitter.destroyed.connect(cb)
+ self.assertEqual(sys.getrefcount(cb), 3)
+
+ self.emitter.destroyed.disconnect(cb)
+ self.assertEqual(sys.getrefcount(cb), 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/signals/static_metaobject_test.py b/sources/pyside6/tests/signals/static_metaobject_test.py
new file mode 100644
index 000000000..d7bf73e44
--- /dev/null
+++ b/sources/pyside6/tests/signals/static_metaobject_test.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env 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
+
+"""Tests covering signal emission and receiving to python slots"""
+
+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, Slot, SIGNAL
+from helper.usesqapplication import UsesQApplication
+
+
+class Sender(QObject):
+
+ foo = Signal()
+ foo2 = Signal()
+
+
+class MyObject(QObject):
+
+ foo2 = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._slotCalledCount = 0
+
+ # this '@Slot()' is needed to get the right sort order in testSharedSignalEmission.
+ # For some reason, it also makes the tests actually work!
+ @Slot()
+ def mySlot(self):
+ self._slotCalledCount = self._slotCalledCount + 1
+
+
+class StaticMetaObjectTest(UsesQApplication):
+
+ def testSignalPropagation(self):
+ """Old style, dynamic signal creation."""
+ o = QObject()
+ o2 = MyObject()
+
+ # SIGNAL foo not created yet
+ self.assertEqual(o.metaObject().indexOfSignal("foo()"), -1)
+
+ o.connect(SIGNAL("foo()"), o2.mySlot)
+ # SIGNAL foo create after connect
+ self.assertTrue(o.metaObject().indexOfSignal("foo()") > 0)
+
+ # SIGNAL does not propagate to others objects of the same type
+ self.assertEqual(o2.metaObject().indexOfSignal("foo()"), -1)
+
+ del o
+ del o2
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ o = MyObject()
+ # The SIGNAL was destroyed with old objects
+ self.assertEqual(o.metaObject().indexOfSignal("foo()"), -1)
+
+ def testSharedSignalEmission(self):
+ o = Sender()
+ m = MyObject()
+
+ o.foo2.connect(m.mySlot)
+ m.foo2.connect(m.mySlot)
+ o.foo2.emit()
+ self.assertEqual(m._slotCalledCount, 1)
+ del o
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ m.foo2.emit()
+ self.assertEqual(m._slotCalledCount, 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/support/CMakeLists.txt b/sources/pyside6/tests/support/CMakeLists.txt
new file mode 100644
index 000000000..1f18ecf23
--- /dev/null
+++ b/sources/pyside6/tests/support/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(voidptr_test.py)
diff --git a/sources/pyside6/tests/support/voidptr_test.py b/sources/pyside6/tests/support/voidptr_test.py
new file mode 100644
index 000000000..d9ea57a61
--- /dev/null
+++ b/sources/pyside6/tests/support/voidptr_test.py
@@ -0,0 +1,49 @@
+# 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 shiboken6 import Shiboken
+from PySide6.support import VoidPtr
+from PySide6.QtCore import QByteArray
+
+
+class PySide6Support(unittest.TestCase):
+
+ def testVoidPtr(self):
+ # Creating a VoidPtr object requires an address of
+ # a C++ object, a wrapped Shiboken Object type,
+ # an object implementing the Python Buffer interface,
+ # or another VoidPtr object.
+
+ # Original content
+ b = b"Hello world"
+ ba = QByteArray(b)
+ vp = VoidPtr(ba, ba.size())
+ self.assertIsInstance(vp, Shiboken.VoidPtr)
+
+ # Create QByteArray from voidptr byte interpretation
+ nba = QByteArray(vp.toBytes())
+ # Compare original bytes to toBytes()
+ self.assertTrue(b, vp.toBytes())
+ # Compare original with new QByteArray data
+ self.assertTrue(b, nba.data())
+ # Convert original and new to str
+ self.assertTrue(str(b), str(nba))
+
+ # Modify nba through a memoryview of vp
+ mv = memoryview(vp)
+ self.assertFalse(mv.readonly)
+ mv[6:11] = b'void*'
+ self.assertEqual(str(ba), str(b"Hello void*"))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/tools/__init__.py b/sources/pyside6/tests/tools/__init__.py
new file mode 100644
index 000000000..31f792369
--- /dev/null
+++ b/sources/pyside6/tests/tools/__init__.py
@@ -0,0 +1 @@
+from init_paths import init_test_paths
diff --git a/sources/pyside6/tests/tools/list-class-hierarchy.py b/sources/pyside6/tests/tools/list-class-hierarchy.py
new file mode 100644
index 000000000..b773b7c58
--- /dev/null
+++ b/sources/pyside6/tests/tools/list-class-hierarchy.py
@@ -0,0 +1,88 @@
+#!/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
+
+# This is a small script printing out Qt binding class hierarchies
+# for comparison purposes.
+#
+# Usage:
+#
+# ./list-class-hierarchy.py PySide6 > pyside6.list
+# ./list-class-hierarchy.py PyQt5 > pyqt5.list
+#
+# meld pyside.list pyqt5.list
+
+import sys
+import pdb
+from inspect import isclass
+
+ignore = ["staticMetaObject",
+ "pyqtConfigure",
+ "registerUserData",
+ "thread"]
+
+
+def recurse_into(el, obj):
+ #s = el.split('.')[-1]
+ #pdb.set_trace()
+ symbols = []
+ for item in sorted(dir(obj)):
+ if item[0] == '_':
+ continue
+ mel = el + '.' + item
+ try:
+ mobj = eval(mel)
+ except Exception:
+ continue
+
+ if item in ignore:
+ continue
+ else:
+ symbols.append(mel)
+
+ if isclass(mobj):
+ symbols += recurse_into(mel, mobj)
+
+ return symbols
+
+
+if __name__ == '__main__':
+ modules = [ 'QtCore',
+ 'QtGui',
+ 'QtHelp',
+ #'QtMultimedia',
+ 'QtNetwork',
+ #'QtOpenGL',
+ 'QtScript',
+ 'QtScriptTools',
+ 'QtSql',
+ 'QtSvg',
+ 'QtTest',
+ #'QtUiTools',
+ 'QtXml',
+ 'QtXmlPatterns' ]
+
+ libraries = ["PySide6", "PyQt5"]
+ librarySymbols = {}
+ for l in libraries:
+ dictionary = []
+ if l == "PyQt5":
+ import sip
+ sip.setapi('QDate', 2)
+ sip.setapi('QDateTime', 2)
+ sip.setapi('QString', 2)
+ sip.setapi('QTextStream', 2)
+ sip.setapi('QTime', 2)
+ sip.setapi('QUrl', 2)
+ sip.setapi('QVariant', 2)
+
+ for m in modules:
+ exec(f"from {l} import {m}", globals(), locals())
+ dictionary += recurse_into(m, eval(m))
+ librarySymbols[l] = dictionary
+
+ print("PyQt5: ", len(librarySymbols["PyQt5"]), " PySide6: ", len(librarySymbols["PySide6"]))
+
+ for symbol in librarySymbols["PyQt5"]:
+ if not (symbol in librarySymbols["PySide6"]):
+ print("Symbol not found in PySide6:", symbol)
diff --git a/sources/pyside6/tests/tools/metaobjectdump/CMakeLists.txt b/sources/pyside6/tests/tools/metaobjectdump/CMakeLists.txt
new file mode 100644
index 000000000..f1ad6ab16
--- /dev/null
+++ b/sources/pyside6/tests/tools/metaobjectdump/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(test_metaobjectdump.py)
diff --git a/sources/pyside6/tests/tools/metaobjectdump/baseline_default_birthdayparty.json b/sources/pyside6/tests/tools/metaobjectdump/baseline_default_birthdayparty.json
new file mode 100644
index 000000000..6a695dd5c
--- /dev/null
+++ b/sources/pyside6/tests/tools/metaobjectdump/baseline_default_birthdayparty.json
@@ -0,0 +1 @@
+[{"classes": [{"className": "BirthdayParty", "qualifiedClassName": "BirthdayParty", "object": true, "superClasses": [{"access": "public", "name": "QObject"}], "classInfos": [{"name": "QML.Element", "value": "auto"}, {"name": "DefaultProperty", "value": "guests"}], "properties": [{"name": "host", "type": "Person", "index": 0, "read": "host", "notify": "host_changed", "write": "host"}, {"name": "guests", "type": "QQmlListProperty<Person>", "index": 1}], "signals": [{"access": "public", "name": "host_changed", "arguments": [], "returnType": "void"}, {"access": "public", "name": "guests_changed", "arguments": [], "returnType": "void"}]}], "outputRevision": 68, "QML_IMPORT_NAME": "People", "QML_IMPORT_MAJOR_VERSION": 1, "QML_IMPORT_MINOR_VERSION": 0, "QT_MODULES": ["QtCore", "QtQml"]}] \ No newline at end of file
diff --git a/sources/pyside6/tests/tools/metaobjectdump/baseline_default_person.json b/sources/pyside6/tests/tools/metaobjectdump/baseline_default_person.json
new file mode 100644
index 000000000..571056c2a
--- /dev/null
+++ b/sources/pyside6/tests/tools/metaobjectdump/baseline_default_person.json
@@ -0,0 +1 @@
+[{"classes": [{"className": "Person", "qualifiedClassName": "Person", "object": true, "superClasses": [{"access": "public", "name": "QObject"}], "classInfos": [{"name": "QML.Element", "value": "anonymous"}], "properties": [{"name": "name", "type": "QString", "index": 0, "read": "name", "notify": "name_changed", "write": "name"}, {"name": "shoe_size", "type": "int", "index": 1, "read": "shoe_size", "notify": "shoe_size_changed", "write": "shoe_size"}], "signals": [{"access": "public", "name": "name_changed", "arguments": [], "returnType": "void"}, {"access": "public", "name": "shoe_size_changed", "arguments": [], "returnType": "void"}]}, {"className": "Boy", "qualifiedClassName": "Boy", "object": true, "superClasses": [{"access": "public", "name": "Person"}], "classInfos": [{"name": "QML.Element", "value": "auto"}]}, {"className": "Girl", "qualifiedClassName": "Girl", "object": true, "superClasses": [{"access": "public", "name": "Person"}], "classInfos": [{"name": "QML.Element", "value": "auto"}]}], "outputRevision": 68, "QML_IMPORT_NAME": "People", "QML_IMPORT_MAJOR_VERSION": 1, "QML_IMPORT_MINOR_VERSION": 0, "QT_MODULES": ["QtCore", "QtQml"]}] \ No newline at end of file
diff --git a/sources/pyside6/tests/tools/metaobjectdump/baseline_inheritance_birthdayparty.json b/sources/pyside6/tests/tools/metaobjectdump/baseline_inheritance_birthdayparty.json
new file mode 100644
index 000000000..0491e41cc
--- /dev/null
+++ b/sources/pyside6/tests/tools/metaobjectdump/baseline_inheritance_birthdayparty.json
@@ -0,0 +1 @@
+[{"classes": [{"className": "BirthdayParty", "qualifiedClassName": "BirthdayParty", "object": true, "superClasses": [{"access": "public", "name": "QObject"}], "classInfos": [{"name": "QML.Element", "value": "auto"}], "properties": [{"name": "host", "type": "Person", "index": 0, "read": "host", "notify": "host_changed", "write": "host"}, {"name": "guests", "type": "QQmlListProperty<Person>", "index": 1}], "signals": [{"access": "public", "name": "host_changed", "arguments": [], "returnType": "void"}, {"access": "public", "name": "guests_changed", "arguments": [], "returnType": "void"}]}], "outputRevision": 68, "QML_IMPORT_NAME": "People", "QML_IMPORT_MAJOR_VERSION": 1, "QML_IMPORT_MINOR_VERSION": 0, "QT_MODULES": ["QtCore", "QtQml"]}] \ No newline at end of file
diff --git a/sources/pyside6/tests/tools/metaobjectdump/baseline_inheritance_person.json b/sources/pyside6/tests/tools/metaobjectdump/baseline_inheritance_person.json
new file mode 100644
index 000000000..82021ee0a
--- /dev/null
+++ b/sources/pyside6/tests/tools/metaobjectdump/baseline_inheritance_person.json
@@ -0,0 +1 @@
+[{"classes": [{"className": "Person", "qualifiedClassName": "Person", "object": true, "superClasses": [{"access": "public", "name": "QObject"}], "classInfos": [{"name": "QML.Element", "value": "auto"}, {"name": "QML.Creatable", "value": "false"}, {"name": "QML.UncreatableReason", "value": "Person is an abstract base class."}], "properties": [{"name": "name", "type": "QString", "index": 0, "read": "name", "notify": "name_changed", "write": "name"}, {"name": "shoe_size", "type": "int", "index": 1, "read": "shoe_size", "notify": "shoe_size_changed", "write": "shoe_size"}], "signals": [{"access": "public", "name": "name_changed", "arguments": [], "returnType": "void"}, {"access": "public", "name": "shoe_size_changed", "arguments": [], "returnType": "void"}]}, {"className": "Boy", "qualifiedClassName": "Boy", "object": true, "superClasses": [{"access": "public", "name": "Person"}], "classInfos": [{"name": "QML.Element", "value": "auto"}]}, {"className": "Girl", "qualifiedClassName": "Girl", "object": true, "superClasses": [{"access": "public", "name": "Person"}], "classInfos": [{"name": "QML.Element", "value": "auto"}]}], "outputRevision": 68, "QML_IMPORT_NAME": "People", "QML_IMPORT_MAJOR_VERSION": 1, "QML_IMPORT_MINOR_VERSION": 0, "QT_MODULES": ["QtCore", "QtQml"]}] \ No newline at end of file
diff --git a/sources/pyside6/tests/tools/metaobjectdump/baseline_property_happybirthdaysong.json b/sources/pyside6/tests/tools/metaobjectdump/baseline_property_happybirthdaysong.json
new file mode 100644
index 000000000..c009111b7
--- /dev/null
+++ b/sources/pyside6/tests/tools/metaobjectdump/baseline_property_happybirthdaysong.json
@@ -0,0 +1 @@
+[{"classes": [{"className": "HappyBirthdaySong", "qualifiedClassName": "HappyBirthdaySong", "object": false, "superClasses": [{"access": "public", "name": "QPyQmlPropertyValueSource"}], "classInfos": [{"name": "QML.Element", "value": "auto"}], "properties": [{"name": "name", "type": "QString", "index": 0, "read": "name", "notify": "name_changed", "write": "name"}], "signals": [{"access": "public", "name": "name_changed", "arguments": [], "returnType": "void"}], "slots": [{"access": "public", "name": "advance", "arguments": [], "returnType": "void"}]}], "outputRevision": 68, "QML_IMPORT_NAME": "People", "QML_IMPORT_MAJOR_VERSION": 1, "QML_IMPORT_MINOR_VERSION": 0, "QT_MODULES": ["QtCore", "QtQml"]}] \ No newline at end of file
diff --git a/sources/pyside6/tests/tools/metaobjectdump/test_metaobjectdump.py b/sources/pyside6/tests/tools/metaobjectdump/test_metaobjectdump.py
new file mode 100644
index 000000000..5e7412bf5
--- /dev/null
+++ b/sources/pyside6/tests/tools/metaobjectdump/test_metaobjectdump.py
@@ -0,0 +1,73 @@
+# 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 subprocess
+import unittest
+
+from pathlib import Path
+
+"""Test for pyside6-metaobjectdump.
+
+The test prints commands to regenerate the base line."""
+
+
+def msg_regenerate(cmd, baseline):
+ cmd_str = " ".join(cmd)
+ return (f"# Regenerate {baseline}\n"
+ f"{cmd_str} > {baseline}")
+
+
+@unittest.skipIf(sys.version_info < (3, 8), "Needs a recent ast module")
+class TestMetaObjectDump(unittest.TestCase):
+ """Test for the metaobjectdump tool. Compares the output of metaobjectdump.py for some
+ example files in compact format."""
+
+ def setUp(self):
+ super().setUp()
+ self._dir = Path(__file__).parent.resolve()
+ pyside_root = self._dir.parents[4]
+ self._metaobjectdump_tool = pyside_root / "sources" / "pyside-tools" / "metaobjectdump.py"
+ self._examples_dir = (pyside_root / "examples" /
+ "qml" / "tutorials" / "extending-qml-advanced")
+
+ # Compile a list of examples (tuple [file, base line, command])
+ examples = []
+ for d in ["advanced2-Inheritance-and-coercion", "advanced3-Default-properties"]:
+ example_dir = self._examples_dir / d
+ examples.append(example_dir / "birthdayparty.py")
+ examples.append(example_dir / "person.py")
+ # Example with slot
+ examples.append(self._examples_dir / "advanced6-Property-value-source"
+ / "happybirthdaysong.py")
+
+ metaobjectdump_cmd_root = [sys.executable, os.fspath(self._metaobjectdump_tool), "-c", "-s"]
+ self._examples = []
+ for example in examples:
+ name = example.parent.name
+ # Simplify "advanced2-Inheritance-and-coercion" -> "inheritance"
+ short_name = name.split("-")[1].lower()
+ baseline_name = f"baseline_{short_name}_{example.stem}.json"
+ baseline_path = self._dir / baseline_name
+ cmd = metaobjectdump_cmd_root + [os.fspath(example)]
+ self._examples.append((example, baseline_path, cmd))
+ print(msg_regenerate(cmd, baseline_path))
+
+ def testMetaObjectDump(self):
+ self.assertTrue(self._examples_dir.is_dir())
+ self.assertTrue(self._metaobjectdump_tool.is_file())
+
+ for example, baseline, cmd in self._examples:
+ self.assertTrue(example.is_file())
+ self.assertTrue(baseline.is_file())
+ baseline_data = baseline.read_text()
+
+ popen = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ actual = popen.communicate()[0].decode("UTF-8")
+ self.assertEqual(popen.returncode, 0)
+ self.assertEqual(baseline_data, actual)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/tools/pyside6-android-deploy/CMakeLists.txt b/sources/pyside6/tests/tools/pyside6-android-deploy/CMakeLists.txt
new file mode 100644
index 000000000..c32d636ed
--- /dev/null
+++ b/sources/pyside6/tests/tools/pyside6-android-deploy/CMakeLists.txt
@@ -0,0 +1,3 @@
+if(CMAKE_HOST_UNIX)
+ PYSIDE_TEST(test_pyside6_android_deploy.py)
+endif()
diff --git a/sources/pyside6/tests/tools/pyside6-android-deploy/extensive_android_deploy_test.py b/sources/pyside6/tests/tools/pyside6-android-deploy/extensive_android_deploy_test.py
new file mode 100644
index 000000000..271f8eebd
--- /dev/null
+++ b/sources/pyside6/tests/tools/pyside6-android-deploy/extensive_android_deploy_test.py
@@ -0,0 +1,88 @@
+# Copyright (C) 2023 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
+
+"""
+ Extensive manual test of pyside6-android-deploy
+
+ Note: Not to be added into the CI
+"""
+
+import logging
+import unittest
+import tempfile
+import shutil
+import sys
+import os
+import importlib
+from pathlib import Path
+
+
+class TestPySide6Deploy(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.pyside_root = Path(__file__).parents[5].resolve()
+ example_root = cls.pyside_root / "examples"
+ example_application = example_root / "gui" / "analogclock"
+ cls.temp_dir = tempfile.mkdtemp()
+ cls.temp_example = Path(
+ shutil.copytree(example_application, Path(cls.temp_dir) / "analogclock")
+ ).resolve()
+ cls.current_dir = Path.cwd()
+
+ sys.path.append(str(cls.pyside_root / "sources" / "pyside-tools"))
+ cls.deploy_lib = importlib.import_module("deploy_lib")
+ cls.android_deploy = importlib.import_module("android_deploy")
+ sys.modules["android_deploy"] = cls.android_deploy
+
+ if os.environ.get("WHEEL_PYSIDE") is not None:
+ cls.pyside_wheel = Path(os.environ.get("WHEEL_PYSIDE")).resolve()
+ else:
+ raise Exception("Environment variable WHEEL_PYSIDE does not exist")
+
+ if os.environ.get("WHEEL_SHIBOKEN") is not None:
+ cls.shiboken_wheel = Path(os.environ.get("WHEEL_SHIBOKEN")).resolve()
+ else:
+ raise Exception("Environment variable WHEEL_SHIBOKEN does not exist")
+
+ def setUp(self):
+ os.chdir(self.temp_example)
+ self.config_file = self.temp_example / "pysidedeploy.spec"
+
+ def testDeployment(self):
+ self.android_deploy.main(name="android_app", shiboken_wheel=self.shiboken_wheel,
+ pyside_wheel=self.pyside_wheel, keep_deployment_files=True,
+ loglevel=logging.INFO, force=True)
+
+ print("Testing with config file")
+ self.android_deploy.main(name="android_app", config_file=self.config_file,
+ loglevel=logging.INFO, force=True)
+
+ def testWithNdkSdk(self):
+ if os.environ.get("ANDROID_SDK_ROOT") is not None:
+ android_sdk_root = Path(os.environ.get("ANDROID_SDK_ROOT")).resolve()
+ else:
+ raise Exception("Environment variable ANDROID_SDK_ROOT does not exist")
+
+ if os.environ.get("ANDROID_NDK_ROOT") is not None:
+ android_ndk_root = Path(os.environ.get("ANDROID_NDK_ROOT")).resolve()
+ else:
+ raise Exception("Environment variable ANDROID_NDK_ROOT does not exist")
+
+ self.android_deploy.main(name="android_app", shiboken_wheel=self.shiboken_wheel,
+ pyside_wheel=self.pyside_wheel,
+ ndk_path=android_ndk_root,
+ sdk_path=android_sdk_root,
+ keep_deployment_files=True,
+ loglevel=logging.INFO, force=True)
+
+ def tearDown(self) -> None:
+ super().tearDown()
+ os.chdir(self.current_dir)
+
+ @classmethod
+ def tearDownClass(cls) -> None:
+ shutil.rmtree(Path(cls.temp_dir))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py b/sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py
new file mode 100644
index 000000000..ec575e923
--- /dev/null
+++ b/sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py
@@ -0,0 +1,274 @@
+# Copyright (C) 2023 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 importlib
+import os
+import re
+import shutil
+import sys
+import tempfile
+import unittest
+import subprocess
+from pathlib import Path
+from unittest import mock
+from unittest.mock import patch
+
+sys.path.append(os.fspath(Path(__file__).resolve().parents[2]))
+from init_paths import init_test_paths # noqa: E402
+init_test_paths(False)
+
+
+class DeployTestBase(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.pyside_root = Path(__file__).parents[5].resolve()
+ cls.example_root = cls.pyside_root / "examples"
+ cls.temp_dir = tempfile.mkdtemp()
+ cls.current_dir = Path.cwd()
+ cls.pyside_wheel = Path("/tmp/PySide6-6.5.0a1-6.5.0-cp37-abi3-android_x86_64.whl")
+ cls.shiboken_wheel = Path("/tmp/shiboken6-6.5.0a1-6.5.0-cp37-abi3-android_x86_64.whl")
+ cls.ndk_path = Path("/tmp/android_sdk/ndk/25.2.9519653")
+ cls.sdk_path = Path("/tmp/android_sdk")
+ pyside_tools = cls.pyside_root / "sources" / "pyside-tools"
+
+ # install extra python dependencies
+ android_requirements_file = pyside_tools / "requirements-android.txt"
+ with open(android_requirements_file, 'r', encoding='UTF-8') as file:
+ while line := file.readline():
+ dependent_package = line.rstrip()
+ if not bool(importlib.util.find_spec(dependent_package)):
+ command = [sys.executable, "-m", "pip", "install", dependent_package]
+ subprocess.run(command)
+
+ sys.path.append(str(pyside_tools))
+ cls.deploy_lib = importlib.import_module("deploy_lib")
+ cls.android_deploy = importlib.import_module("android_deploy")
+ sys.modules["android_deploy"] = cls.android_deploy
+
+ # required for comparing long strings
+ cls.maxDiff = None
+
+ # print no outputs to stdout
+ sys.stdout = mock.MagicMock()
+
+ def tearDown(self) -> None:
+ super().tearDown()
+ os.chdir(self.current_dir)
+
+ @classmethod
+ def tearDownClass(cls) -> None:
+ shutil.rmtree(Path(cls.temp_dir))
+
+
+@patch("deploy_lib.android.android_config.extract_and_copy_jar")
+class TestPySide6AndroidDeployWidgets(DeployTestBase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ example_widget_application = cls.example_root / "gui" / "analogclock"
+ cls.temp_example = Path(
+ shutil.copytree(example_widget_application, Path(cls.temp_dir) / "analogclock")
+ ).resolve()
+
+ def setUp(self):
+ os.chdir(self.temp_example)
+ self.config_file = self.temp_example / "pysidedeploy.spec"
+ self.buildozer_config = self.temp_example / "buildozer.spec"
+
+ @patch("deploy_lib.android.android_config.AndroidConfig._find_local_libs")
+ @patch("deploy_lib.android.android_config.AndroidConfig._find_dependent_qt_modules")
+ @patch("deploy_lib.android.android_config.find_qtlibs_in_wheel")
+ def test_dry_run(self, mock_qtlibs, mock_extraqtmodules, mock_local_libs, mock_extract_jar):
+ mock_qtlibs.return_value = self.pyside_wheel / "PySide6/Qt/lib"
+ mock_extraqtmodules.return_value = []
+ dependent_plugins = ["platforms_qtforandroid",
+ "platforminputcontexts_qtvirtualkeyboardplugin",
+ "iconengines_qsvgicon"]
+ mock_local_libs.return_value = [], dependent_plugins
+ self.android_deploy.main(name="android_app", shiboken_wheel=self.shiboken_wheel,
+ pyside_wheel=self.pyside_wheel, ndk_path=self.ndk_path,
+ dry_run=True, force=True)
+
+ self.assertEqual(mock_extract_jar.call_count, 0)
+ self.assertEqual(mock_qtlibs.call_count, 1)
+ self.assertEqual(mock_extraqtmodules.call_count, 1)
+ self.assertEqual(mock_local_libs.call_count, 1)
+
+ @patch("deploy_lib.android.buildozer.BuildozerConfig._BuildozerConfig__find_jars")
+ @patch("deploy_lib.android.android_config.AndroidConfig.recipes_exist")
+ @patch("deploy_lib.android.android_config.AndroidConfig._find_dependent_qt_modules")
+ @patch("deploy_lib.android.android_config.find_qtlibs_in_wheel")
+ def test_config(self, mock_qtlibs, mock_extraqtmodules, mock_recipes_exist, mock_find_jars,
+ mock_extract_jar):
+ jar_dir = "tmp/jar/PySide6/jar"
+ mock_extract_jar.return_value = Path(jar_dir)
+ mock_qtlibs.return_value = self.pyside_wheel / "PySide6/Qt/lib"
+ mock_extraqtmodules.return_value = []
+ mock_recipes_exist.return_value = True
+ jars, init_classes = ["/tmp/jar/PySide6/jar/Qt6Android.jar",
+ "/tmp/jar/PySide6/jar/Qt6AndroidBindings.jar"], []
+ mock_find_jars.return_value = jars, init_classes
+
+ self.android_deploy.main(name="android_app", shiboken_wheel=self.shiboken_wheel,
+ pyside_wheel=self.pyside_wheel, ndk_path=self.ndk_path,
+ init=True, force=True, keep_deployment_files=True)
+
+ self.assertEqual(mock_extract_jar.call_count, 1)
+ self.assertEqual(mock_qtlibs.call_count, 1)
+ self.assertEqual(mock_extraqtmodules.call_count, 1)
+ self.assertEqual(mock_recipes_exist.call_count, 1)
+ self.assertEqual(mock_find_jars.call_count, 1)
+ self.assertTrue(self.config_file.exists())
+ self.assertTrue(self.buildozer_config.exists())
+
+ # test config file contents
+ config_obj = self.deploy_lib.BaseConfig(config_file=self.config_file)
+ self.assertEqual(config_obj.get_value("app", "input_file"), "main.py")
+ self.assertEqual(config_obj.get_value("python", "android_packages"),
+ "buildozer==1.5.0,cython==0.29.33")
+ self.assertEqual(config_obj.get_value("android", "wheel_pyside"),
+ str(self.pyside_wheel.resolve()))
+ self.assertEqual(config_obj.get_value("android", "wheel_shiboken"),
+ str(self.shiboken_wheel.resolve()))
+ self.assertEqual(config_obj.get_value("buildozer", "mode"), "debug")
+ self.assertEqual(config_obj.get_value("buildozer", "recipe_dir"),
+ '')
+ self.assertEqual(config_obj.get_value("buildozer", "jars_dir"),
+ str(self.temp_example / jar_dir))
+ self.assertIn(str(self.ndk_path), config_obj.get_value("buildozer", "ndk_path"))
+ self.assertEqual(config_obj.get_value("buildozer", "sdk_path"), '')
+ expected_modules = {"Core", "Gui"}
+ obtained_modules = set(config_obj.get_value("qt", "modules").split(","))
+ self.assertEqual(obtained_modules, expected_modules)
+ expected_local_libs = ""
+ self.assertEqual(config_obj.get_value("buildozer", "local_libs"),
+ expected_local_libs)
+ self.assertEqual(config_obj.get_value("buildozer", "arch"), "x86_64")
+
+ # test buildozer config file contents
+ buildozer_config_obj = self.deploy_lib.BaseConfig(config_file=self.buildozer_config)
+ obtained_jars = set(buildozer_config_obj.get_value("app", "android.add_jars").split(','))
+ expected_jars = set(jars)
+ self.assertEqual(obtained_jars, expected_jars)
+ obtained_extra_args = buildozer_config_obj.get_value("app", "p4a.extra_args")
+ extra_args_patrn = re.compile("--qt-libs=(?P<modules>.*) --load-local-libs="
+ "(?P<local_libs>.*) --init-classes=(?P<init_classes>.*)")
+ match = extra_args_patrn.search(obtained_extra_args)
+ obtained_modules = match.group("modules").split(',')
+ obtained_local_libs = match.group("local_libs")
+ obtained_init_classes = match.group("init_classes")
+ self.assertEqual(set(obtained_modules), expected_modules)
+ self.assertEqual(obtained_local_libs, expected_local_libs)
+ self.assertEqual(obtained_init_classes, '')
+ expected_include_exts = "py,png,jpg,kv,atlas,qml,js"
+ obtained_include_exts = buildozer_config_obj.get_value("app", "source.include_exts")
+ self.assertEqual(expected_include_exts, obtained_include_exts)
+
+ self.config_file.unlink()
+ self.buildozer_config.unlink()
+
+ def test_errors(self, mock_extract_jar):
+ # test if error raises for non existing NDK
+ with self.assertRaises(FileNotFoundError) as context:
+ self.android_deploy.main(name="android_app", shiboken_wheel=self.shiboken_wheel,
+ pyside_wheel=self.pyside_wheel, force=True)
+ self.assertTrue("Unable to find Android NDK" in str(context.exception))
+
+ # test when cwd() is not project_dir
+ os.chdir(self.current_dir)
+ with self.assertRaises(RuntimeError) as context:
+ self.android_deploy.main(name="android_app", shiboken_wheel=self.shiboken_wheel,
+ pyside_wheel=self.pyside_wheel, init=True, force=True)
+ self.assertTrue("For Android deployment to work" in str(context.exception))
+
+
+@patch("deploy_lib.config.run_qmlimportscanner")
+@patch("deploy_lib.android.android_config.extract_and_copy_jar")
+class TestPySide6AndroidDeployQml(DeployTestBase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ # setting up example
+ example_qml_application = cls.example_root / "quick" / "models" / "stringlistmodel"
+ cls.temp_qml_example = Path(
+ shutil.copytree(example_qml_application, Path(cls.temp_dir) / "stringlistmodel")
+ ).resolve()
+
+ def setUp(self):
+ os.chdir(self.temp_qml_example)
+ self.config_file = self.temp_qml_example / "pysidedeploy.spec"
+ self.buildozer_config_file = self.temp_qml_example / "buildozer.spec"
+ (self.temp_qml_example / "stringlistmodel.py").rename(self.temp_qml_example / "main.py")
+ (self.temp_qml_example / "stringlistmodel.pyproject").unlink()
+
+ @patch("deploy_lib.android.android_config.AndroidConfig._find_local_libs")
+ @patch("deploy_lib.android.buildozer.BuildozerConfig._BuildozerConfig__find_jars")
+ @patch("deploy_lib.android.android_config.AndroidConfig.recipes_exist")
+ @patch("deploy_lib.android.android_config.AndroidConfig._find_dependent_qt_modules")
+ @patch("deploy_lib.android.android_config.find_qtlibs_in_wheel")
+ def test_config_with_Qml(self, mock_qtlibs, mock_extraqtmodules, mock_recipes_exist,
+ mock_find_jars, mock_local_libs, mock_extract_jar,
+ mock_qmlimportscanner):
+ # setting up mocks
+ jar_dir = "tmp/jar/PySide6/jar"
+ mock_extract_jar.return_value = Path(jar_dir)
+ mock_qtlibs.return_value = self.pyside_wheel / "PySide6/Qt/lib"
+ mock_extraqtmodules.return_value = ['Qml', 'Network', 'QmlModels', 'OpenGL']
+ mock_recipes_exist.return_value = True
+ jars, init_classes = ["/tmp/jar/PySide6/jar/Qt6Android.jar",
+ "/tmp/jar/PySide6/jar/Qt6AndroidBindings.jar",
+ "/tmp/jar/PySide6/jar/Qt6AndroidNetworkInformationBackend.jar",
+ "/tmp/jar/PySide6/jar/Qt6AndroidNetwork.jar"], []
+ mock_find_jars.return_value = jars, init_classes
+ dependent_plugins = ["platforms_qtforandroid",
+ "platforminputcontexts_qtvirtualkeyboardplugin",
+ "iconengines_qsvgicon"]
+ mock_local_libs.return_value = [], dependent_plugins
+ mock_qmlimportscanner.return_value = ["QtQuick"]
+
+ self.android_deploy.main(name="android_app", shiboken_wheel=self.shiboken_wheel,
+ pyside_wheel=self.pyside_wheel, ndk_path=self.ndk_path,
+ init=True, force=True, keep_deployment_files=True)
+
+ self.assertEqual(mock_extract_jar.call_count, 1)
+ self.assertEqual(mock_qtlibs.call_count, 1)
+ self.assertEqual(mock_extraqtmodules.call_count, 1)
+ self.assertEqual(mock_recipes_exist.call_count, 1)
+ self.assertEqual(mock_find_jars.call_count, 1)
+ self.assertEqual(mock_qmlimportscanner.call_count, 1)
+ self.assertTrue(self.config_file.exists())
+ self.assertTrue(self.buildozer_config_file.exists())
+
+ config_obj = self.deploy_lib.BaseConfig(config_file=self.config_file)
+ expected_modules = {"Quick", "Core", "Gui", "Network", "Qml", "QmlModels", "OpenGL"}
+ obtained_modules = set(config_obj.get_value("qt", "modules").split(","))
+ self.assertEqual(obtained_modules, expected_modules)
+ expected_local_libs = ""
+ self.assertEqual(config_obj.get_value("buildozer", "local_libs"),
+ expected_local_libs)
+ expected_qt_plugins = set(dependent_plugins)
+ obtained_qt_plugins = set(config_obj.get_value("android", "plugins").split(","))
+ self.assertEqual(expected_qt_plugins, obtained_qt_plugins)
+
+ # test buildozer config file contents
+ buildozer_config_obj = self.deploy_lib.BaseConfig(config_file=self.buildozer_config_file)
+ obtained_jars = set(buildozer_config_obj.get_value("app", "android.add_jars").split(','))
+ expected_jars = set(jars)
+ self.assertEqual(obtained_jars, expected_jars)
+ obtained_extra_args = buildozer_config_obj.get_value("app", "p4a.extra_args")
+ extra_args_patrn = re.compile("--qt-libs=(?P<modules>.*) --load-local-libs="
+ "(?P<local_libs>.*) --init-classes=(?P<init_classes>.*)")
+ match = extra_args_patrn.search(obtained_extra_args)
+ obtained_modules = match.group("modules").split(',')
+ obtained_local_libs = match.group("local_libs")
+ obtained_init_classes = match.group("init_classes")
+ self.assertEqual(set(obtained_modules), expected_modules)
+ self.assertEqual(obtained_local_libs, expected_local_libs)
+ self.assertEqual(obtained_init_classes, '')
+
+ self.config_file.unlink()
+ self.buildozer_config_file.unlink()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/tools/pyside6-deploy/CMakeLists.txt b/sources/pyside6/tests/tools/pyside6-deploy/CMakeLists.txt
new file mode 100644
index 000000000..7f010fbd6
--- /dev/null
+++ b/sources/pyside6/tests/tools/pyside6-deploy/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(test_pyside6_deploy.py)
diff --git a/sources/pyside6/tests/tools/pyside6-deploy/extensive_deploy_test.py b/sources/pyside6/tests/tools/pyside6-deploy/extensive_deploy_test.py
new file mode 100644
index 000000000..40afc7f5c
--- /dev/null
+++ b/sources/pyside6/tests/tools/pyside6-deploy/extensive_deploy_test.py
@@ -0,0 +1,88 @@
+# Copyright (C) 2023 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
+
+"""
+ Extensive manual test of pyside6-deploy
+
+ Note: Not to be added into the CI
+"""
+
+import logging
+import unittest
+import tempfile
+import shutil
+import sys
+import os
+import importlib
+from pathlib import Path
+
+
+class TestPySide6Deploy(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.pyside_root = Path(__file__).parents[5].resolve()
+ example_root = cls.pyside_root / "examples"
+ example_widgets = example_root / "widgets" / "widgets" / "tetrix"
+ example_qml = example_root / "qml" / "editingmodel"
+ example_webenginequick = example_root / "webenginequick" / "nanobrowser"
+ cls.temp_dir = tempfile.mkdtemp()
+ cls.temp_example_widgets = Path(
+ shutil.copytree(example_widgets, Path(cls.temp_dir) / "tetrix")
+ ).resolve()
+ cls.temp_example_qml = Path(
+ shutil.copytree(example_qml, Path(cls.temp_dir) / "editingmodel")
+ ).resolve()
+ cls.temp_example_webenginequick = Path(
+ shutil.copytree(example_webenginequick, Path(cls.temp_dir) / "nanobrowser")
+ ).resolve()
+ cls.current_dir = Path.cwd()
+ cls.linux_onefile_icon = (
+ cls.pyside_root / "sources" / "pyside-tools" / "deploy_lib" / "pyside_icon.jpg"
+ )
+
+ sys.path.append(str(cls.pyside_root / "sources" / "pyside-tools"))
+ cls.deploy_lib = importlib.import_module("deploy_lib")
+ cls.deploy = importlib.import_module("deploy")
+ sys.modules["deploy"] = cls.deploy
+
+ def setUpWidgets(self):
+ os.chdir(self.temp_example_widgets)
+ self.main_file = self.temp_example_widgets / "tetrix.py"
+ self.config_file = self.temp_example_widgets / "pysidedeploy.spec"
+
+ def testWidget(self):
+ self.setUpWidgets()
+ self.deploy.main(self.main_file, name="widget_app", loglevel=logging.INFO,
+ keep_deployment_files=True, force=True)
+
+ print("Now testing Widget with config file")
+ self.deploy.main(self.main_file, config_file=self.config_file, loglevel=logging.INFO,
+ force=True)
+
+ def setUpQml(self):
+ os.chdir(self.temp_example_qml)
+ self.main_file = self.temp_example_qml / "main.py"
+ self.config_file = self.temp_example_qml / "pysidedeploy.spec"
+
+ def testQml(self):
+ self.setUpQml()
+ self.deploy.main(self.main_file, name="qml_app", loglevel=logging.INFO,
+ keep_deployment_files=True, force=True)
+
+ def testWebEngineQuickDryRun(self):
+ os.chdir(self.temp_example_webenginequick)
+ main_file = self.temp_example_webenginequick / "quicknanobrowser.py"
+ self.deploy.main(main_file, name="qml_app", keep_deployment_files=True,
+ loglevel=logging.INFO, force=True)
+
+ def tearDown(self) -> None:
+ super().tearDown()
+ os.chdir(self.current_dir)
+
+ @classmethod
+ def tearDownClass(cls) -> None:
+ shutil.rmtree(Path(cls.temp_dir))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/tools/pyside6-deploy/test_pyside6_deploy.py b/sources/pyside6/tests/tools/pyside6-deploy/test_pyside6_deploy.py
new file mode 100644
index 000000000..db60c8c3f
--- /dev/null
+++ b/sources/pyside6/tests/tools/pyside6-deploy/test_pyside6_deploy.py
@@ -0,0 +1,400 @@
+# 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 unittest
+import tempfile
+import shutil
+import sys
+import os
+import importlib
+import platform
+from pathlib import Path
+from unittest.mock import patch
+from unittest import mock
+
+sys.path.append(os.fspath(Path(__file__).resolve().parents[2]))
+from init_paths import init_test_paths, _get_qt_lib_dir # noqa: E402
+init_test_paths(False)
+
+
+def is_pyenv_python():
+ pyenv_root = os.environ.get("PYENV_ROOT")
+
+ if pyenv_root and (resolved_exe := str(Path(sys.executable).resolve())):
+ return resolved_exe.startswith(pyenv_root)
+ return False
+
+
+class LongSortedOptionTest(unittest.TestCase):
+ @staticmethod
+ def _option_prepare(s):
+ """
+ Take a string and return a list obtained by text.split().
+ Options starting with "--" are also sorted."
+ """
+ items = s.split()
+ for idx in range(len(items)):
+ if items[idx].startswith("--"):
+ return items[:idx] + sorted(items[idx:])
+ return items
+
+ def assertEqual(self, text_a, text_b):
+ if (not isinstance(text_a, str) or not isinstance(text_b, str)
+ or (len(text_a) < 50 and len(text_b) < 50)):
+ return super().assertEqual(text_a, text_b)
+ sort_a = self._option_prepare(text_a)
+ sort_b = self._option_prepare(text_b)
+ return super().assertEqual(sort_a, sort_b)
+
+
+class DeployTestBase(LongSortedOptionTest):
+ @classmethod
+ def setUpClass(cls):
+ cls.pyside_root = Path(__file__).parents[5].resolve()
+ cls.example_root = cls.pyside_root / "examples"
+ cls.temp_dir = tempfile.mkdtemp()
+ cls.current_dir = Path.cwd()
+ tools_path = cls.pyside_root / "sources" / "pyside-tools"
+ cls.win_icon = tools_path / "deploy_lib" / "pyside_icon.ico"
+ cls.linux_icon = tools_path / "deploy_lib" / "pyside_icon.jpg"
+ cls.macos_icon = tools_path / "deploy_lib" / "pyside_icon.icns"
+ if tools_path not in sys.path:
+ sys.path.append(str(cls.pyside_root / "sources" / "pyside-tools"))
+ cls.deploy_lib = importlib.import_module("deploy_lib")
+ cls.deploy = importlib.import_module("deploy")
+ sys.modules["deploy"] = cls.deploy
+ files_to_ignore = [".cpp.o", ".qsb", ".webp"]
+ cls.dlls_ignore_nuitka = " ".join([f"--noinclude-dlls=*{file}"
+ for file in files_to_ignore])
+
+ # required for comparing long strings
+ cls.maxDiff = None
+
+ # print no outputs to stdout
+ sys.stdout = mock.MagicMock()
+
+ @classmethod
+ def tearDownClass(cls) -> None:
+ shutil.rmtree(Path(cls.temp_dir))
+
+ def tearDown(self) -> None:
+ super().tearDown()
+ os.chdir(self.current_dir)
+
+
+@unittest.skipIf(sys.platform == "darwin" and int(platform.mac_ver()[0].split('.')[0]) <= 11,
+ "Test only works on macOS version 12+")
+@patch("deploy_lib.config.QtDependencyReader.find_plugin_dependencies")
+class TestPySide6DeployWidgets(DeployTestBase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ example_widgets = cls.example_root / "widgets" / "widgets" / "tetrix"
+ cls.temp_example_widgets = Path(
+ shutil.copytree(example_widgets, Path(cls.temp_dir) / "tetrix")
+ ).resolve()
+
+ def setUp(self):
+ os.chdir(self.temp_example_widgets)
+ self.main_file = self.temp_example_widgets / "tetrix.py"
+ self.deployment_files = self.temp_example_widgets / "deployment"
+ # All the plugins included. This is different from plugins_nuitka, because Nuitka bundles
+ # some plugins by default
+ self.all_plugins = ["accessiblebridge", "egldeviceintegrations", "generic", "iconengines",
+ "imageformats", "platforminputcontexts", "platforms",
+ "platforms/darwin", "platformthemes", "styles", "xcbglintegrations"]
+ # Plugins that needs to be passed to Nuitka
+ plugins_nuitka = ("accessiblebridge,platforminputcontexts,platforms/darwin")
+ self.expected_run_cmd = (
+ f"{sys.executable} -m nuitka {str(self.main_file)} --follow-imports"
+ f" --enable-plugin=pyside6 --output-dir={str(self.deployment_files)} --quiet"
+ f" --noinclude-qt-translations"
+ f" --include-qt-plugins={plugins_nuitka}"
+ f" {self.dlls_ignore_nuitka}"
+ )
+ if sys.platform.startswith("linux"):
+ self.expected_run_cmd += f" --linux-icon={str(self.linux_icon)} --onefile"
+ elif sys.platform == "darwin":
+ self.expected_run_cmd += (f" --macos-app-icon={str(self.macos_icon)}"
+ " --macos-create-app-bundle --standalone")
+ elif sys.platform == "win32":
+ self.expected_run_cmd += f" --windows-icon-from-ico={str(self.win_icon)} --onefile"
+
+ if is_pyenv_python():
+ self.expected_run_cmd += " --static-libpython=no"
+ self.config_file = self.temp_example_widgets / "pysidedeploy.spec"
+
+ def testWidgetDryRun(self, mock_plugins):
+ mock_plugins.return_value = self.all_plugins
+ # Checking for dry run commands is equivalent to mocking the
+ # subprocess.check_call() in commands.py as the the dry run command
+ # is the command being run.
+ original_output = self.deploy.main(self.main_file, dry_run=True, force=True)
+ self.assertEqual(original_output, self.expected_run_cmd)
+
+ @patch("deploy_lib.dependency_util.QtDependencyReader.get_qt_libs_dir")
+ def testWidgetConfigFile(self, mock_sitepackages, mock_plugins):
+ mock_sitepackages.return_value = Path(_get_qt_lib_dir())
+ mock_plugins.return_value = self.all_plugins
+ # includes both dry run and config_file tests
+ # init
+ init_result = self.deploy.main(self.main_file, init=True, force=True)
+ self.assertEqual(init_result, None)
+
+ # test with config
+ original_output = self.deploy.main(config_file=self.config_file, dry_run=True, force=True)
+ self.assertEqual(original_output, self.expected_run_cmd)
+
+ # # test config file contents
+ config_obj = self.deploy_lib.BaseConfig(config_file=self.config_file)
+ self.assertEqual(config_obj.get_value("app", "input_file"), "tetrix.py")
+ self.assertEqual(config_obj.get_value("app", "project_dir"), ".")
+ self.assertEqual(config_obj.get_value("app", "exec_directory"), ".")
+ self.assertEqual(config_obj.get_value("python", "packages"),
+ "Nuitka==2.1")
+ self.assertEqual(config_obj.get_value("qt", "qml_files"), "")
+ equ_base = "--quiet --noinclude-qt-translations"
+ equ_value = equ_base + " --static-libpython=no" if is_pyenv_python() else equ_base
+ self.assertEqual(config_obj.get_value("nuitka", "extra_args"), equ_value)
+ self.assertEqual(config_obj.get_value("qt", "excluded_qml_plugins"), "")
+ expected_modules = {"Core", "Gui", "Widgets"}
+ if sys.platform != "win32":
+ expected_modules.add("DBus")
+ obtained_modules = set(config_obj.get_value("qt", "modules").split(","))
+ self.assertEqual(obtained_modules, expected_modules)
+ obtained_qt_plugins = config_obj.get_value("qt", "plugins").split(",")
+ self.assertEqual(obtained_qt_plugins.sort(), self.all_plugins.sort())
+ self.config_file.unlink()
+
+ def testErrorReturns(self, mock_plugins):
+ mock_plugins.return_value = self.all_plugins
+ # main file and config file does not exists
+ fake_main_file = self.main_file.parent / "main.py"
+ with self.assertRaises(RuntimeError) as context:
+ self.deploy.main(main_file=fake_main_file, config_file=self.config_file)
+ self.assertTrue("Directory does not contain main.py file." in str(context.exception))
+
+
+@unittest.skipIf(sys.platform == "darwin" and int(platform.mac_ver()[0].split('.')[0]) <= 11,
+ "Test only works on macOS version 12+")
+@patch("deploy_lib.config.QtDependencyReader.find_plugin_dependencies")
+class TestPySide6DeployQml(DeployTestBase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ example_qml = cls.example_root / "qml" / "editingmodel"
+ cls.temp_example_qml = Path(
+ shutil.copytree(example_qml, Path(cls.temp_dir) / "editingmodel")
+ ).resolve()
+
+ def setUp(self):
+ os.chdir(self.temp_example_qml)
+ self.main_file = self.temp_example_qml / "main.py"
+ self.deployment_files = self.temp_example_qml / "deployment"
+ self.first_qml_file = "main.qml"
+ self.second_qml_file = "MovingRectangle.qml"
+
+ # All the plugins included. This is different from plugins_nuitka, because Nuitka bundles
+ # some plugins by default
+ self.all_plugins = ["accessiblebridge", "egldeviceintegrations", "generic", "iconengines",
+ "imageformats", "networkaccess", "networkinformation",
+ "platforminputcontexts", "platforms", "platforms/darwin",
+ "platformthemes", "qmltooling", "scenegraph", "tls",
+ "xcbglintegrations"]
+ # Plugins that needs to be passed to Nuitka
+ plugins_nuitka = ("accessiblebridge,networkaccess,networkinformation,platforminputcontexts,"
+ "platforms/darwin,qml,qmltooling,scenegraph")
+ self.expected_run_cmd = (
+ f"{sys.executable} -m nuitka {str(self.main_file)} --follow-imports"
+ f" --enable-plugin=pyside6 --output-dir={str(self.deployment_files)} --quiet"
+ f" --noinclude-qt-translations"
+ f" {self.dlls_ignore_nuitka}"
+ " --noinclude-dlls=*/qml/QtQuickEffectMaker/*"
+ f" --include-qt-plugins={plugins_nuitka}"
+ f" --include-data-files={str(self.temp_example_qml / self.first_qml_file)}="
+ f"./main.qml --include-data-files="
+ f"{str(self.temp_example_qml / self.second_qml_file)}=./MovingRectangle.qml"
+ )
+
+ if sys.platform != "win32":
+ self.expected_run_cmd += (
+ " --noinclude-dlls=libQt6Charts*"
+ " --noinclude-dlls=libQt6Quick3D* --noinclude-dlls=libQt6Sensors*"
+ " --noinclude-dlls=libQt6Test* --noinclude-dlls=libQt6WebEngine*"
+ )
+ else:
+ self.expected_run_cmd += (
+ " --noinclude-dlls=Qt6Charts*"
+ " --noinclude-dlls=Qt6Quick3D* --noinclude-dlls=Qt6Sensors*"
+ " --noinclude-dlls=Qt6Test* --noinclude-dlls=Qt6WebEngine*"
+ )
+
+ if sys.platform.startswith("linux"):
+ self.expected_run_cmd += f" --linux-icon={str(self.linux_icon)} --onefile"
+ elif sys.platform == "darwin":
+ self.expected_run_cmd += (f" --macos-app-icon={str(self.macos_icon)}"
+ " --macos-create-app-bundle --standalone")
+ elif sys.platform == "win32":
+ self.expected_run_cmd += f" --windows-icon-from-ico={str(self.win_icon)} --onefile"
+
+ if is_pyenv_python():
+ self.expected_run_cmd += " --static-libpython=no"
+ self.config_file = self.temp_example_qml / "pysidedeploy.spec"
+
+ @patch("deploy_lib.dependency_util.QtDependencyReader.get_qt_libs_dir")
+ def testQmlConfigFile(self, mock_sitepackages, mock_plugins):
+ mock_sitepackages.return_value = Path(_get_qt_lib_dir())
+ mock_plugins.return_value = self.all_plugins
+ # create config file
+ with patch("deploy_lib.config.run_qmlimportscanner") as mock_qmlimportscanner:
+ mock_qmlimportscanner.return_value = ["QtQuick"]
+ init_result = self.deploy.main(self.main_file, init=True, force=True)
+ self.assertEqual(init_result, None)
+
+ # test config file contents
+ config_obj = self.deploy_lib.BaseConfig(config_file=self.config_file)
+ self.assertEqual(config_obj.get_value("app", "input_file"), "main.py")
+ self.assertEqual(config_obj.get_value("app", "project_dir"), ".")
+ self.assertEqual(config_obj.get_value("app", "exec_directory"), ".")
+ self.assertEqual(config_obj.get_value("python", "packages"),
+ "Nuitka==2.1")
+ self.assertEqual(config_obj.get_value("qt", "qml_files"), "main.qml,MovingRectangle.qml")
+ equ_base = "--quiet --noinclude-qt-translations"
+ equ_value = equ_base + " --static-libpython=no" if is_pyenv_python() else equ_base
+ self.assertEqual(config_obj.get_value("nuitka", "extra_args"), equ_value)
+ self.assertEqual(
+ config_obj.get_value("qt", "excluded_qml_plugins"),
+ "QtCharts,QtQuick3D,QtSensors,QtTest,QtWebEngine",
+ )
+ expected_modules = {"Core", "Gui", "Qml", "Quick", "Network", "OpenGL", "QmlModels"}
+ if sys.platform != "win32":
+ expected_modules.add("DBus")
+ obtained_modules = set(config_obj.get_value("qt", "modules").split(","))
+ self.assertEqual(obtained_modules, expected_modules)
+ obtained_qt_plugins = config_obj.get_value("qt", "plugins").split(",")
+ self.assertEqual(obtained_qt_plugins.sort(), self.all_plugins.sort())
+ self.config_file.unlink()
+
+ def testQmlDryRun(self, mock_plugins):
+ mock_plugins.return_value = self.all_plugins
+ with patch("deploy_lib.config.run_qmlimportscanner") as mock_qmlimportscanner:
+ mock_qmlimportscanner.return_value = ["QtQuick"]
+ original_output = self.deploy.main(self.main_file, dry_run=True, force=True)
+ self.assertEqual(original_output, self.expected_run_cmd)
+ self.assertEqual(mock_qmlimportscanner.call_count, 1)
+
+ def testMainFileDryRun(self, mock_plugins):
+ mock_plugins.return_value = self.all_plugins
+ with patch("deploy_lib.config.run_qmlimportscanner") as mock_qmlimportscanner:
+ mock_qmlimportscanner.return_value = ["QtQuick"]
+ original_output = self.deploy.main(Path.cwd() / "main.py", dry_run=True, force=True)
+ self.assertEqual(original_output, self.expected_run_cmd)
+ self.assertEqual(mock_qmlimportscanner.call_count, 1)
+
+
+@unittest.skipIf(sys.platform == "darwin" and int(platform.mac_ver()[0].split('.')[0]) <= 11,
+ "Test only works on macOS version 12+")
+class TestPySide6DeployWebEngine(DeployTestBase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ example_webenginequick = cls.example_root / "webenginequick" / "nanobrowser"
+ cls.temp_example_webenginequick = Path(
+ shutil.copytree(example_webenginequick, Path(cls.temp_dir) / "nanobrowser")
+ ).resolve()
+
+ @patch("deploy_lib.config.QtDependencyReader.find_plugin_dependencies")
+ @patch("deploy_lib.dependency_util.QtDependencyReader.get_qt_libs_dir")
+ def testWebEngineQuickDryRun(self, mock_sitepackages, mock_plugins):
+ mock_sitepackages.return_value = Path(_get_qt_lib_dir())
+ all_plugins = ["accessiblebridge", "egldeviceintegrations", "generic", "iconengines",
+ "imageformats", "networkaccess", "networkinformation",
+ "platforminputcontexts", "platforms", "platforms/darwin",
+ "platformthemes", "qmltooling", "scenegraph", "tls",
+ "xcbglintegrations"]
+ mock_plugins.return_value = all_plugins
+ # this test case retains the QtWebEngine dlls
+ # setup
+ os.chdir(self.temp_example_webenginequick)
+ main_file = self.temp_example_webenginequick / "quicknanobrowser.py"
+ deployment_files = self.temp_example_webenginequick / "deployment"
+ # Plugins that needs to be passed to Nuitka
+ plugins_nuitka = ("accessiblebridge,networkaccess,networkinformation,platforminputcontexts,"
+ "platforms/darwin,qml,qmltooling,scenegraph")
+ qml_files = [
+ "ApplicationRoot.qml",
+ "BrowserDialog.qml",
+ "BrowserWindow.qml",
+ "DownloadView.qml",
+ "FindBar.qml",
+ "FullScreenNotification.qml",
+ ]
+ data_files_cmd = " ".join(
+ [
+ f"--include-data-files={str(self.temp_example_webenginequick / file)}=./{file}"
+ for file in qml_files
+ ]
+ )
+ expected_run_cmd = (
+ f"{sys.executable} -m nuitka {str(main_file)} --follow-imports"
+ f" --enable-plugin=pyside6 --output-dir={str(deployment_files)} --quiet"
+ f" --noinclude-qt-translations --include-qt-plugins=all"
+ f" {data_files_cmd}"
+ f" --include-qt-plugins={plugins_nuitka}"
+ f" {self.dlls_ignore_nuitka}"
+ " --noinclude-dlls=*/qml/QtQuickEffectMaker/*"
+ )
+
+ if sys.platform != "win32":
+ expected_run_cmd += (
+ " --noinclude-dlls=libQt6Charts*"
+ " --noinclude-dlls=libQt6Quick3D* --noinclude-dlls=libQt6Sensors*"
+ " --noinclude-dlls=libQt6Test*"
+ )
+ else:
+ expected_run_cmd += (
+ " --noinclude-dlls=Qt6Charts*"
+ " --noinclude-dlls=Qt6Quick3D* --noinclude-dlls=Qt6Sensors*"
+ " --noinclude-dlls=Qt6Test*"
+ )
+
+ if sys.platform.startswith("linux"):
+ expected_run_cmd += f" --linux-icon={str(self.linux_icon)} --onefile"
+ elif sys.platform == "darwin":
+ expected_run_cmd += (f" --macos-app-icon={str(self.macos_icon)}"
+ " --macos-create-app-bundle --standalone")
+ elif sys.platform == "win32":
+ expected_run_cmd += f" --windows-icon-from-ico={str(self.win_icon)} --onefile"
+
+ config_file = self.temp_example_webenginequick / "pysidedeploy.spec"
+
+ # create config file
+ with patch("deploy_lib.config.run_qmlimportscanner") as mock_qmlimportscanner:
+ mock_qmlimportscanner.return_value = ["QtQuick", "QtWebEngine"]
+ init_result = self.deploy.main(main_file, init=True, force=True)
+ self.assertEqual(init_result, None)
+
+ # run dry_run
+ original_output = self.deploy.main(main_file, dry_run=True, force=True)
+ self.assertTrue(original_output, expected_run_cmd)
+ self.assertEqual(mock_qmlimportscanner.call_count, 2)
+
+ # test config file contents
+ config_obj = self.deploy_lib.BaseConfig(config_file=config_file)
+ self.assertEqual(config_obj.get_value("app", "input_file"), "quicknanobrowser.py")
+ self.assertEqual(config_obj.get_value("qt", "qml_files"), ",".join(qml_files))
+ self.assertEqual(
+ config_obj.get_value("qt", "excluded_qml_plugins"),
+ "QtCharts,QtQuick3D,QtSensors,QtTest",
+ )
+ expected_modules = {"Core", "Gui", "Quick", "Qml", "WebEngineQuick", "Network", "OpenGL",
+ "Positioning", "WebEngineCore", "WebChannel", "WebChannelQuick",
+ "QmlModels"}
+ if sys.platform != "win32":
+ expected_modules.add("DBus")
+ obtained_modules = set(config_obj.get_value("qt", "modules").split(","))
+ self.assertEqual(obtained_modules, expected_modules)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/tools/pyside6-qml/CMakeLists.txt b/sources/pyside6/tests/tools/pyside6-qml/CMakeLists.txt
new file mode 100644
index 000000000..4d801264a
--- /dev/null
+++ b/sources/pyside6/tests/tools/pyside6-qml/CMakeLists.txt
@@ -0,0 +1 @@
+PYSIDE_TEST(test_pyside6_qml.py)
diff --git a/sources/pyside6/tests/tools/pyside6-qml/test_pyside6_qml.py b/sources/pyside6/tests/tools/pyside6-qml/test_pyside6_qml.py
new file mode 100644
index 000000000..fdaf3d471
--- /dev/null
+++ b/sources/pyside6/tests/tools/pyside6-qml/test_pyside6_qml.py
@@ -0,0 +1,75 @@
+# Copyright (C) 2018 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
+
+"""Test for pyside6-qml
+
+The tests does a unittest and some integration tests for pyside6-qml."""
+
+from asyncio.subprocess import PIPE
+import os
+import sys
+import unittest
+import subprocess
+import importlib.util
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[2]))
+from init_paths import init_test_paths
+init_test_paths(False)
+
+
+class TestPySide6QmlUnit(unittest.TestCase):
+ def setUp(self) -> None:
+ super().setUp()
+ self._dir = Path(__file__).parent.resolve()
+ self.pyside_root = self._dir.parents[4]
+
+ self.pyqml_path = self.pyside_root / "sources" / "pyside-tools" / "qml.py"
+ self.core_qml_path = (self.pyside_root / "examples" / "qml" /
+ "tutorials" / "extending-qml-advanced" / "adding")
+
+ self.pyqml_run_cmd = [sys.executable, os.fspath(self.pyqml_path)]
+
+ # self.pyqml_path will not abe able to find pyside and other related binaries, if not added
+ # to path explicitly. The following lines does that.
+ self.test_env = os.environ.copy()
+ self.test_env["PYTHONPATH"] = os.pathsep + os.pathsep.join(sys.path)
+
+ def testImportQmlModules(self):
+
+ # because pyside-tools has a hyphen, a normal 'from pyside-tools import qml' cannot be done
+ spec = importlib.util.spec_from_file_location("qml", self.pyqml_path)
+ pyqml = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(pyqml)
+ pyqml.import_qml_modules(self.core_qml_path)
+
+ # path added to sys.path
+ self.assertIn(str(self.core_qml_path), sys.path)
+
+ # module is imported
+ self.assertIn("person", sys.modules.keys())
+
+ # remove the imported modules
+ sys.path.remove(str(self.core_qml_path))
+ del sys.modules["person"]
+
+ # test with module_paths - dir
+ self.person_path = self.core_qml_path / "person.py"
+ pyqml.import_qml_modules(self.core_qml_path, module_paths=[self.core_qml_path])
+ self.assertIn(str(self.core_qml_path), sys.path)
+ self.assertIn("person", sys.modules.keys())
+
+ # test with module_paths - file - in testCoreApplication(self)
+
+ def testCoreApplication(self):
+ self.pyqml_run_cmd.extend(["--apptype", "core"])
+ self.pyqml_run_cmd.append(str(self.core_qml_path / "People" / "Main.qml"))
+ self.pyqml_run_cmd.extend(["-I", str(self.core_qml_path / "person.py")])
+
+ result = subprocess.run(self.pyqml_run_cmd, stdout=PIPE, env=self.test_env)
+ self.assertEqual(result.returncode, 0)
+ self.assertEqual(result.stdout.rstrip(), b"{'_name': 'Bob Jones', '_shoe_size': 12}")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/util/color.py b/sources/pyside6/tests/util/color.py
new file mode 100644
index 000000000..e85be28f3
--- /dev/null
+++ b/sources/pyside6/tests/util/color.py
@@ -0,0 +1,14 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Function to print a colored line to terminal'''
+
+
+def print_colored(message):
+ print(f'\033[0;31m{message}\033[m') # red
+
+
+if __name__ == '__main__':
+ print('42 - the answer')
+ print_colored("But what's the question?")
+ print('Hum?')
diff --git a/sources/pyside6/tests/util/helper/__init__.py b/sources/pyside6/tests/util/helper/__init__.py
new file mode 100644
index 000000000..218d8921e
--- /dev/null
+++ b/sources/pyside6/tests/util/helper/__init__.py
@@ -0,0 +1 @@
+# This file intentionally left blank.
diff --git a/sources/pyside6/tests/util/helper/basicpyslotcase.py b/sources/pyside6/tests/util/helper/basicpyslotcase.py
new file mode 100644
index 000000000..500735c3a
--- /dev/null
+++ b/sources/pyside6/tests/util/helper/basicpyslotcase.py
@@ -0,0 +1,33 @@
+# 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
+
+
+class BasicPySlotCase(object):
+ '''Base class that tests python slots and signal emissions.
+
+ Python slots are defined as any callable passed to QObject.connect().
+ '''
+ def setUp(self):
+ self.called = False
+
+ def tearDown(self):
+ try:
+ del self.args
+ except:
+ pass
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+
+ def cb(self, *args):
+ '''Simple callback with arbitrary arguments.
+
+ The test function must setup the 'args' attribute with a sequence
+ containing the arguments expected to be received by this slot.
+ Currently only a single connection is supported.
+ '''
+ if tuple(self.args) == args:
+ self.called = True
+ else:
+ raise ValueError('Invalid arguments for callback')
diff --git a/sources/pyside6/tests/util/helper/docmodifier.py b/sources/pyside6/tests/util/helper/docmodifier.py
new file mode 100644
index 000000000..cfb665640
--- /dev/null
+++ b/sources/pyside6/tests/util/helper/docmodifier.py
@@ -0,0 +1,91 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Helper metaclass do 'decorate' docstrings from base test case classes'''
+
+import types
+
+
+def copy_func(func):
+ '''Helper function to copy a function object (except docstring)'''
+ return types.FunctionType(func.func_code, func.func_globals, func.func_name,
+ func.func_defaults, func.func_closure)
+
+
+class DocModifier(type):
+ '''Metaclass for modifiying method documentation.
+
+ It allows the managed class to modify the method documentation, adding
+ prefixes and suffixes to a given set of methods.
+
+ For example, you have some unittest.TestCases that run on different set
+ of data. These methods could be written once in a base class and the
+ inheriting class just setup different setUp/tearDown methods with the
+ proper data. To differentiate the methods when using docstrings, you
+ can add a suffix or prefix to the docstring.
+
+ Variables in the implementing class:
+
+ doc_prefix - The prefix to the docstring
+ doc_suffix - The suffix to the docstring
+ doc_filter - The function to filter the methods. If not provided, this
+ no docstrings are changed.'''
+
+ def __new__(mcs, name, bases, dct):
+
+ # FIXME currently we have to define doc_filter on each subclass
+ filter_function = dct.get('doc_filter')
+ if not filter_function:
+ filter_function = lambda x: False
+
+ for base in bases:
+ for attr in [x for x in base.__dict__ if filter_function(x)]:
+ original = getattr(base, attr)
+
+ if original.__doc__:
+ copy = copy_func(original)
+ copy.__doc__ = (dct.get('doc_prefix', '') +
+ original.__doc__ +
+ dct.get('doc_suffix', ''))
+ dct[attr] = copy
+
+ return type.__new__(mcs, name, bases, dct)
+
+ def __init__(mcs, name, bases, dct):
+ super(DocModifier, mcs).__init__(name, bases, dct)
+
+
+if __name__ == '__main__':
+
+ # tests
+ class BaseTest(object):
+ __metaclass__ = DocModifier
+
+ def testBase(self):
+ '''base'''
+
+ def testWithoutDoc(self):
+ pass
+
+ class Implementing(BaseTest):
+
+ doc_filter = lambda x: x.startswith('test')
+ doc_prefix = 'prefix'
+ doc_suffix = 'suffix'
+
+ class OnlyPrefix(BaseTest):
+
+ doc_filter = lambda x: x.startswith('test')
+ doc_prefix = 'prefix'
+
+ class OnlySuffix(BaseTest):
+
+ doc_filter = lambda x: x.startswith('test')
+ doc_suffix = 'suffix'
+
+ assert (Implementing.testBase.__doc__ == 'prefixbasesuffix')
+ assert (Implementing.testWithoutDoc.__doc__ == None)
+ assert (OnlySuffix.testBase.__doc__ == 'basesuffix')
+ assert (OnlySuffix.testWithoutDoc.__doc__ == None)
+ assert (OnlyPrefix.testBase.__doc__ == 'prefixbase')
+ assert (OnlyPrefix.testWithoutDoc.__doc__ == None)
diff --git a/sources/pyside6/tests/util/helper/helper.py b/sources/pyside6/tests/util/helper/helper.py
new file mode 100644
index 000000000..f80753f1f
--- /dev/null
+++ b/sources/pyside6/tests/util/helper/helper.py
@@ -0,0 +1,37 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Helper classes and functions'''
+
+import os
+from random import randint
+
+
+def adjust_filename(filename, orig_mod_filename):
+ dirpath = os.path.dirname(os.path.abspath(orig_mod_filename))
+ return os.path.join(dirpath, filename)
+
+
+def _join_qml_errors(errors):
+ '''Return an error string from a list of QQmlError'''
+ result = ''
+ for i, error in enumerate(errors):
+ if i:
+ result += ', '
+ result += error.toString()
+ return result
+
+
+def quickview_errorstring(quickview):
+ '''Return an error string from a QQuickView'''
+ return _join_qml_errors(quickview.errors())
+
+
+def qmlcomponent_errorstring(component):
+ '''Return an error string from a QQmlComponent'''
+ return _join_qml_errors(component.errors())
+
+
+def random_string(size=5):
+ '''Generate random string with the given size'''
+ return ''.join(map(chr, [randint(33, 126) for x in range(size)]))
diff --git a/sources/pyside6/tests/util/helper/helper.pyproject b/sources/pyside6/tests/util/helper/helper.pyproject
new file mode 100644
index 000000000..dc23d87a5
--- /dev/null
+++ b/sources/pyside6/tests/util/helper/helper.pyproject
@@ -0,0 +1,5 @@
+{
+ "files": ["basicpyslotcase.py", "docmodifier.py", "helper.py",
+ "timedqapplication.py", "usesqapplication.py", "usesqcoreapplication.py",
+ "usesqguiapplication.py" ]
+}
diff --git a/sources/pyside6/tests/util/helper/timedqapplication.py b/sources/pyside6/tests/util/helper/timedqapplication.py
new file mode 100644
index 000000000..d9250a9e0
--- /dev/null
+++ b/sources/pyside6/tests/util/helper/timedqapplication.py
@@ -0,0 +1,27 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Helper classes and functions'''
+
+import gc
+import unittest
+
+from PySide6.QtCore import QTimer
+from PySide6.QtWidgets import QApplication
+
+
+class TimedQApplication(unittest.TestCase):
+ '''Helper class with timed QApplication exec loop'''
+
+ def setUp(self, timeout=100):
+ '''Setups this Application.
+
+ timeout - timeout in milisseconds'''
+ self.app = QApplication.instance() or QApplication([])
+ QTimer.singleShot(timeout, self.app.quit)
+
+ def tearDown(self):
+ '''Delete resources'''
+ del self.app
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
diff --git a/sources/pyside6/tests/util/helper/timedqguiapplication.py b/sources/pyside6/tests/util/helper/timedqguiapplication.py
new file mode 100644
index 000000000..3d9a4217c
--- /dev/null
+++ b/sources/pyside6/tests/util/helper/timedqguiapplication.py
@@ -0,0 +1,27 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Helper classes and functions'''
+
+import gc
+import unittest
+
+from PySide6.QtCore import QTimer
+from PySide6.QtGui import QGuiApplication
+
+
+class TimedQGuiApplication(unittest.TestCase):
+ '''Helper class with timed QGuiApplication exec loop'''
+
+ def setUp(self, timeout=100):
+ '''Sets up this Application.
+
+ timeout - timeout in millisseconds'''
+ self.app = QGuiApplication.instance() or QGuiApplication([])
+ QTimer.singleShot(timeout, self.app.quit)
+
+ def tearDown(self):
+ '''Delete resources'''
+ del self.app
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
diff --git a/sources/pyside6/tests/util/helper/usesqapplication.py b/sources/pyside6/tests/util/helper/usesqapplication.py
new file mode 100644
index 000000000..f62e320f4
--- /dev/null
+++ b/sources/pyside6/tests/util/helper/usesqapplication.py
@@ -0,0 +1,43 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Helper classes and functions'''
+
+import gc
+import sys
+import unittest
+
+# This version avoids explicit import in order to adapt to the
+# import decision of the main module.
+# This should work with every compatible library.
+# Replaces the QtGui and QtCore versions as well.
+
+
+class UsesQApplication(unittest.TestCase):
+ '''Helper class to provide Q(Core|Gui|)Application instances
+ Just connect or call self.exit_app_cb. When called, will ask
+ self.app to exit.
+ '''
+
+ def setUp(self):
+ '''Creates the QApplication instance'''
+ module = sys.modules[sorted(_ for _ in sys.modules
+ if _.endswith((".QtCore", ".QtGui", ".QtWidgets")))[-1]]
+ found = module.__name__.rsplit(".")[-1]
+ cls = getattr(module, {"QtWidgets": "QApplication",
+ "QtGui": "QGuiApplication",
+ "QtCore": "QCoreApplication"}[found])
+ # Simple way of making instance a singleton
+ super().setUp()
+ self.app = cls.instance() or cls([])
+
+ def tearDown(self):
+ '''Deletes the reference owned by self'''
+ del self.app
+ # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
+ gc.collect()
+ super().tearDown()
+
+ def exit_app_cb(self):
+ '''Quits the application'''
+ self.app.exit(0)
diff --git a/sources/pyside6/tests/util/httpd.py b/sources/pyside6/tests/util/httpd.py
new file mode 100644
index 000000000..4e6be4881
--- /dev/null
+++ b/sources/pyside6/tests/util/httpd.py
@@ -0,0 +1,153 @@
+# 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 http.server as BaseHTTPServer
+import os
+import random
+import select
+import sys
+import socketserver as SocketServer
+import tempfile
+import threading
+
+sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "util"))
+
+
+class TestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+ DATA = b"PySide Server"
+ allow_reuse_address = True
+
+ def do_GET(self):
+ self.send_head()
+ self.wfile.write(TestHandler.DATA)
+
+ def do_HEAD(self):
+ self.send_head()
+
+ def send_head(self):
+ self.send_response(200)
+ self.send_header("Content-type", "text/plain")
+ self.send_header("Content-Length", str(len(TestHandler.DATA)))
+ self.end_headers()
+
+
+class TestSecureHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+ DATA = "PySide"
+ allow_reuse_address = True
+
+ def do_GET(self):
+ self.send_head()
+ self.wfile.write(py3k.b(TestHandler.DATA))
+
+ def do_HEAD(self):
+ self.send_head()
+
+ def send_head(self):
+ try:
+ handler = self.marshall_handler()
+ handler.do_request(self)
+ except:
+ self.send_response(401)
+ self.send_header("WWW-Authenticate", "Basic realm='Secure Area'")
+ self.send_header("Content-type", "text/plain")
+ self.send_header("Content-Length", str(len(TestHandler.DATA)))
+ self.end_headers()
+
+# Workaround for the missing shutdown method in python2.5
+
+
+class CompatTCPServer(SocketServer.TCPServer):
+ def __init__(self, server_address, RequestHandlerClass):
+ SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
+
+ self.isPy25 = sys.version_info[0] == 2 and sys.version_info[1] == 5
+ if self.isPy25:
+ self.__is_shut_down = threading.Event()
+ self.__serving = False
+
+ def serve_forever(self, poll_interval=0.5):
+ """Handle one request at a time until shutdown.
+
+ Polls for shutdown every poll_interval seconds. Ignores
+ self.timeout. If you need to do periodic tasks, do them in
+ another thread.
+ """
+ if self.isPy25:
+ self.__serving = True
+ self.__is_shut_down.clear()
+ while self.__serving:
+ # XXX: Consider using another file descriptor or
+ # connecting to the socket to wake this up instead of
+ # polling. Polling reduces our responsiveness to a
+ # shutdown request and wastes cpu at all other times.
+ r, w, e = select.select([self], [], [], poll_interval)
+ if r:
+ self.py25_handle_request_noblock()
+ self.__is_shut_down.set()
+ else:
+ SocketServer.TCPServer.serve_forever(self, poll_interval)
+
+ def py25_handle_request_noblock(self):
+ """Handle one request, without blocking.
+
+ I assume that select.select has returned that the socket is
+ readable before this function was called, so there should be
+ no risk of blocking in get_request().
+ """
+ if self.isPy25:
+ try:
+ request, client_address = self.get_request()
+ except socket.error:
+ return
+ if self.verify_request(request, client_address):
+ try:
+ self.process_request(request, client_address)
+ except:
+ self.handle_error(request, client_address)
+ self.close_request(request)
+
+ def shutdown(self):
+ """Stops the serve_forever loop.
+
+ Blocks until the loop has finished. This must be called while
+ serve_forever() is running in another thread, or it will
+ deadlock.
+ """
+ if self.isPy25:
+ self.__serving = False
+ if not self.__is_shut_down:
+ self.__is_shut_down.wait()
+ else:
+ SocketServer.TCPServer.shutdown(self)
+
+
+class TestServer(threading.Thread):
+
+ def __init__(self, secure=False):
+ threading.Thread.__init__(self)
+
+ self._port = int(os.getenv("PYSIDE_TESTSERVER_PORT") or 12321)
+ self.keep_running = True
+
+ if secure:
+ handle = TestSecureHandler
+ else:
+ handle = TestHandler
+
+ while True:
+ try:
+ self.httpd = CompatTCPServer(('', self._port), handle)
+ break
+ except:
+ self._port = self._port + random.randint(1, 100)
+
+ def port(self):
+ return self._port
+
+ def run(self):
+ self.httpd.serve_forever()
+
+ def shutdown(self):
+ self.httpd.shutdown()
+ self.join()
+
diff --git a/sources/pyside6/tests/util/processtimer.py b/sources/pyside6/tests/util/processtimer.py
new file mode 100644
index 000000000..e471cf167
--- /dev/null
+++ b/sources/pyside6/tests/util/processtimer.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env 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 time
+
+
+class TimeoutException(Exception):
+ def __init__(self, msg):
+ self.msg = msg
+
+ def __str__(self):
+ return repr(self.msg)
+
+
+class ProcessTimer(object):
+ '''Timeout function for controlling a subprocess.Popen instance.
+
+ Naive implementation using busy loop, see later other means
+ of doing this.
+ '''
+
+ def __init__(self, proc, timeout):
+ self.proc = proc
+ self.timeout = timeout
+
+ def waitfor(self):
+ time_passed = 0
+ while (self.proc.poll() is None and time_passed < self.timeout):
+ time_passed = time_passed + 1
+ time.sleep(1)
+
+ if time_passed >= self.timeout:
+ raise TimeoutException("Timeout expired, possible deadlock")
+
+
+if __name__ == "__main__":
+ # simple example
+
+ from subprocess import Popen
+
+ proc = Popen(['sleep', '10'])
+ t = ProcessTimer(proc, 5)
+ try:
+ t.waitfor()
+ except TimeoutException:
+ print(f"timeout - PID: {t.proc.pid}")
+ #TODO: detect SO and kill accordingly
+ #Linux
+ os.kill(t.proc.pid, 9)
+ #Windows (not tested)
+ #subprocess.Popen("taskkill /F /T /PID %i"%handle.pid , shell=True)
+ print(f"exit code: {t.proc.poll()}")
diff --git a/sources/pyside6/tests/util/rename_imports.sh b/sources/pyside6/tests/util/rename_imports.sh
new file mode 100755
index 000000000..1ec900cb3
--- /dev/null
+++ b/sources/pyside6/tests/util/rename_imports.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+# Rename import statements from .py script to use a specific module name
+set -e
+
+if [ $# -lt 3 ]; then
+ echo "Usage: $0 <old_name> <new_name> <directories...>"
+ exit 1
+fi
+
+old_name=$1; shift
+new_name=$1; shift
+
+find "$@" -name "*.py" -exec sed -ri "s/(import|from) $old_name/\1 $new_name/" '{}' \;
diff --git a/sources/pyside6/tests/util/test_processtimer.py b/sources/pyside6/tests/util/test_processtimer.py
new file mode 100644
index 000000000..cee6aa14d
--- /dev/null
+++ b/sources/pyside6/tests/util/test_processtimer.py
@@ -0,0 +1,73 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'Tests for processtimer.py'
+
+import unittest
+import os
+
+from subprocess import Popen, PIPE
+from processtimer import TimeoutException, ProcessTimer
+
+
+class TimeoutTest(unittest.TestCase):
+
+ def tearDown(self):
+ try:
+ os.kill(self.proc.pid, 9)
+ except OSError:
+ pass
+
+ def testRaise(self):
+ self.proc = Popen(['python2.5', '-c', 'while True: pass'], stdout=PIPE, stderr=PIPE)
+ timer = ProcessTimer(self.proc, 1)
+ self.assertRaises(TimeoutException, timer.waitfor)
+
+
+class SimpleTest(unittest.TestCase):
+
+ def tearDown(self):
+ try:
+ os.kill(self.proc.pid, 9)
+ except OSError:
+ pass
+
+ def testSimple(self):
+ self.proc = Popen(['python2.5', '-c', '"print"'], stdout=PIPE, stderr=PIPE)
+ timer = ProcessTimer(self.proc, 10)
+ timer.waitfor()
+
+
+class TestEchoOutput(unittest.TestCase):
+
+ def tearDown(self):
+ try:
+ os.kill(self.proc.pid, 9)
+ except OSError:
+ pass
+
+ def testOutput(self):
+ self.proc = Popen(['python2.5', '-c', 'print 1',], stdout=PIPE, stderr=PIPE)
+ timer = ProcessTimer(self.proc, 1)
+ timer.waitfor()
+ self.assertEqual(self.proc.stdout.read().strip(), '1')
+
+
+class TestRetCode(unittest.TestCase):
+
+ def tearDown(self):
+ try:
+ os.kill(self.proc.pid, 9)
+ except OSError:
+ pass
+
+ def testSimple(self):
+ self.proc = Popen(['python2.5', '-c', 'print 1'], stdout=PIPE, stderr=PIPE)
+ timer = ProcessTimer(self.proc, 10)
+ timer.waitfor()
+
+ self.assertEqual(self.proc.poll(), 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/pyside6/tests/util/valgrind-python.supp b/sources/pyside6/tests/util/valgrind-python.supp
new file mode 100644
index 000000000..a54b451b3
--- /dev/null
+++ b/sources/pyside6/tests/util/valgrind-python.supp
@@ -0,0 +1,349 @@
+#
+# This is a valgrind suppression file that should be used when using valgrind.
+#
+# Here's an example of running valgrind:
+#
+# cd python/dist/src
+# valgrind --tool=memcheck --suppressions=Misc/valgrind-python.supp \
+# ./python -E -tt ./Lib/test/regrtest.py -u bsddb,network
+#
+# You must edit Objects/obmalloc.c and uncomment Py_USING_MEMORY_DEBUGGER
+# to use the preferred suppressions with Py_ADDRESS_IN_RANGE.
+#
+# If you do not want to recompile Python, you can uncomment
+# suppressions for PyObject_Free and PyObject_Realloc.
+#
+# See Misc/README.valgrind for more information.
+
+# all tool names: Addrcheck,Memcheck,cachegrind,helgrind,massif
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Addr4
+ fun:Py_ADDRESS_IN_RANGE
+}
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Value4
+ fun:Py_ADDRESS_IN_RANGE
+}
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 8 (x86_64 aka amd64)
+ Memcheck:Value8
+ fun:Py_ADDRESS_IN_RANGE
+}
+
+{
+ ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value
+ Memcheck:Cond
+ fun:Py_ADDRESS_IN_RANGE
+}
+
+#
+# Leaks (including possible leaks)
+# Hmmm, I wonder if this masks some real leaks. I think it does.
+# Will need to fix that.
+#
+
+{
+ Handle PyMalloc confusing valgrind (possibly leaked)
+ Memcheck:Leak
+ fun:realloc
+ fun:_PyObject_GC_Resize
+ fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING
+}
+
+{
+ Handle PyMalloc confusing valgrind (possibly leaked)
+ Memcheck:Leak
+ fun:malloc
+ fun:_PyObject_GC_New
+ fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING
+}
+
+{
+ Handle PyMalloc confusing valgrind (possibly leaked)
+ Memcheck:Leak
+ fun:malloc
+ fun:_PyObject_GC_NewVar
+ fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING
+}
+
+#
+# Non-python specific leaks
+#
+
+{
+ Handle pthread issue (possibly leaked)
+ Memcheck:Leak
+ fun:calloc
+ fun:allocate_dtv
+ fun:_dl_allocate_tls_storage
+ fun:_dl_allocate_tls
+}
+
+{
+ Handle pthread issue (possibly leaked)
+ Memcheck:Leak
+ fun:memalign
+ fun:_dl_allocate_tls_storage
+ fun:_dl_allocate_tls
+}
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Addr4
+ fun:PyObject_Free
+}
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Value4
+ fun:PyObject_Free
+}
+
+{
+ ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value
+ Memcheck:Cond
+ fun:PyObject_Free
+}
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Addr4
+ fun:PyObject_Realloc
+}
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Value4
+ fun:PyObject_Realloc
+}
+
+{
+ ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value
+ Memcheck:Cond
+ fun:PyObject_Realloc
+}
+
+###
+### All the suppressions below are for errors that occur within libraries
+### that Python uses. The problems to not appear to be related to Python's
+### use of the libraries.
+###
+
+{
+ Generic gentoo ld problems
+ Memcheck:Cond
+ obj:/lib/ld-2.3.4.so
+ obj:/lib/ld-2.3.4.so
+ obj:/lib/ld-2.3.4.so
+ obj:/lib/ld-2.3.4.so
+}
+
+{
+ DBM problems, see test_dbm
+ Memcheck:Param
+ write(buf)
+ fun:write
+ obj:/usr/lib/libdb1.so.2
+ obj:/usr/lib/libdb1.so.2
+ obj:/usr/lib/libdb1.so.2
+ obj:/usr/lib/libdb1.so.2
+ fun:dbm_close
+}
+
+{
+ DBM problems, see test_dbm
+ Memcheck:Value8
+ fun:memmove
+ obj:/usr/lib/libdb1.so.2
+ obj:/usr/lib/libdb1.so.2
+ obj:/usr/lib/libdb1.so.2
+ obj:/usr/lib/libdb1.so.2
+ fun:dbm_store
+ fun:dbm_ass_sub
+}
+
+{
+ DBM problems, see test_dbm
+ Memcheck:Cond
+ obj:/usr/lib/libdb1.so.2
+ obj:/usr/lib/libdb1.so.2
+ obj:/usr/lib/libdb1.so.2
+ fun:dbm_store
+ fun:dbm_ass_sub
+}
+
+{
+ DBM problems, see test_dbm
+ Memcheck:Cond
+ fun:memmove
+ obj:/usr/lib/libdb1.so.2
+ obj:/usr/lib/libdb1.so.2
+ obj:/usr/lib/libdb1.so.2
+ obj:/usr/lib/libdb1.so.2
+ fun:dbm_store
+ fun:dbm_ass_sub
+}
+
+{
+ GDBM problems, see test_gdbm
+ Memcheck:Param
+ write(buf)
+ fun:write
+ fun:gdbm_open
+
+}
+
+{
+ ZLIB problems, see test_gzip
+ Memcheck:Cond
+ obj:/lib/libz.so.1.2.3
+ obj:/lib/libz.so.1.2.3
+ fun:deflate
+}
+
+{
+ Avoid problems w/readline doing a putenv and leaking on exit
+ Memcheck:Leak
+ fun:malloc
+ fun:xmalloc
+ fun:sh_set_lines_and_columns
+ fun:_rl_get_screen_size
+ fun:_rl_init_terminal_io
+ obj:/lib/libreadline.so.4.3
+ fun:rl_initialize
+}
+
+###
+### These occur from somewhere within the SSL, when running
+### test_socket_sll. They are too general to leave on by default.
+###
+###{
+### somewhere in SSL stuff
+### Memcheck:Cond
+### fun:memset
+###}
+###{
+### somewhere in SSL stuff
+### Memcheck:Value4
+### fun:memset
+###}
+###
+###{
+### somewhere in SSL stuff
+### Memcheck:Cond
+### fun:MD5_Update
+###}
+###
+###{
+### somewhere in SSL stuff
+### Memcheck:Value4
+### fun:MD5_Update
+###}
+
+#
+# All of these problems come from using test_socket_ssl
+#
+{
+ from test_socket_ssl
+ Memcheck:Cond
+ fun:BN_bin2bn
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Cond
+ fun:BN_num_bits_word
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Value4
+ fun:BN_num_bits_word
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Cond
+ fun:BN_mod_exp_mont_word
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Cond
+ fun:BN_mod_exp_mont
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Param
+ write(buf)
+ fun:write
+ obj:/usr/lib/libcrypto.so.0.9.7
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Cond
+ fun:RSA_verify
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Value4
+ fun:RSA_verify
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Value4
+ fun:DES_set_key_unchecked
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Value4
+ fun:DES_encrypt2
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Cond
+ obj:/usr/lib/libssl.so.0.9.7
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Value4
+ obj:/usr/lib/libssl.so.0.9.7
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Cond
+ fun:BUF_MEM_grow_clean
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Cond
+ fun:memcpy
+ fun:ssl3_read_bytes
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Cond
+ fun:SHA1_Update
+}
+
+{
+ from test_socket_ssl
+ Memcheck:Value4
+ fun:SHA1_Update
+}
+
+