Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added PySide6 Support (squash) #394

Merged
merged 39 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
80dc006
Added PySide6 Support
zoshua Feb 22, 2024
822cac0
Merge branch 'mottosso:master' into squash
zoshua Feb 26, 2024
a25cc94
Create pyside6.yml
zoshua Feb 28, 2024
55889ed
Updated pyside6.yml
zoshua Feb 29, 2024
47ac768
Update pyside6.yml
zoshua Feb 29, 2024
f993695
Update entrypoint.sh
zoshua Feb 29, 2024
5209c24
Update pyside6.yml
zoshua Feb 29, 2024
39c28dd
Update entrypoint.sh
zoshua Feb 29, 2024
c0d64e0
Update entrypoint.sh
zoshua Feb 29, 2024
d855ccf
Update entrypoint.sh
zoshua Feb 29, 2024
e23780c
Update entrypoint.sh - rolling back changes
zoshua Mar 1, 2024
f9b4ca1
Update pyside6.yml - run tests directly
zoshua Mar 1, 2024
6d6f955
Update pyside6.yml - Testing examples step
zoshua Mar 1, 2024
158651d
Update pyside6.yml - Testing Example PYTHONPATH
zoshua Mar 1, 2024
392f0cd
Update run_tests.py - added with binding PySide6
zoshua Mar 1, 2024
4e1fd21
Update pyside6.yml - added step Pip install .
zoshua Mar 1, 2024
606010c
Update run_tests.py - rolling back last commit
zoshua Mar 1, 2024
5083eb9
Update pyside6.yml - changed step Testing implementation..
zoshua Mar 1, 2024
a31ea4a
Update pyside6.yml - updated jobs/env
zoshua Mar 1, 2024
da81b09
Merge branch 'mottosso:master' into squash
zoshua Mar 22, 2024
3105351
Major overhaul to:
zoshua Apr 1, 2024
a3dffae
Updated _misplaced_members PySide6 and PySide2
zoshua Apr 5, 2024
f8e4124
Reverting _misplaced_members QStringListModel as a test
zoshua Apr 5, 2024
55a9c7b
Reverting binding("PySide2") QStringListModel as a test
zoshua Apr 5, 2024
0cea915
Updated _common_members for PySide2
zoshua Apr 5, 2024
7ca0224
Updated _common_members for test_caveats.py
zoshua Apr 5, 2024
af8af75
Update pyside6.yml - added Install EGL mesa step
zoshua Apr 5, 2024
73a6ba4
Update pyside6.yml - Added Install GUI Libs step, Removed Install EGL…
zoshua Apr 5, 2024
42395b6
Update pyside6.yml - Reverting back to Install EGL Mesa step, adding …
zoshua Apr 5, 2024
5493aa0
Update pyside6.yml - Updated Install GUI libs step
zoshua Apr 5, 2024
93ab974
Update pyside6.yml - Testing QT_QPA_PLATFORM=minimal env variable
zoshua Apr 5, 2024
7351971
Update pyside6.yml - Added QT_VERBOSE=1 env variable
zoshua Apr 5, 2024
d65eaf9
Updated _misplaced_members PySide6
zoshua Apr 6, 2024
fed4836
Updated test_vendoring() to include PySide6 in QT_PREFERRED_BINDING_J…
zoshua Apr 6, 2024
c4b202d
Updated pyside6.yml - Testing examples..
zoshua Apr 6, 2024
e6edaa8
Added PySide6 to QT_PREFERRED_BINDING
zoshua Apr 6, 2024
3967fe4
added PySide6 to update_misplaced_members() and update_compatibility_…
zoshua Apr 6, 2024
66e379b
Update pyside6.yml - Testing examples.. Step
zoshua Apr 7, 2024
25e117d
updated _compatibility_members - added QFont.setWeight, Qt.MidButton
zoshua May 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/pyside6.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Run PySide6 Tests

on:
push:
branches:
- "*"
pull_request:
branches:
- "*"

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- os: ubuntu-latest
VFXPLATFORM: "2018"
PYTHON: "3.6"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, the strategy: block can go away.

A strategy: matrix: block is used to execute tests within the Docker container multiples times in a row in run-tests.yml, using different parameters.

→ I think this does not have any use in here, and can be removed.


steps:
- name: Checkout code
uses: actions/checkout@v4

- name: pip install PySide6
run: |
pip install PySide6
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose pip explicitly, install needed dependencies.

As @mottosso mentioned, these tests will not be run within the Docker container anymore. So you probably also need to install a few more dependency packages here.

You'll probably need to installnose and nosepipe, maybe a few more. (→ You can have a look at the Dockerfile, to see what's needed.)


Also, it might be good to be explicit about the pip/python version that you are using.

So please replace:
(Using Python 3.10 in my example...)

pip install PySide6

with:

python3.10 -m pip install PySide6


- name: Run tests in Docker container
run: |
docker run --rm \
-v $(pwd):/Qt.py \
-e PYTHON=${{ matrix.PYTHON }} \
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line runs a Docker container, which we would no longer need in this case. Instead, call the ./entrypoint.sh file directly, along with the Python version used.

run: PYTHON=3.11 ./entrypoint.sh

Set PYTHON=3.10 or 3.11, depending on which version of Python ubuntu-latest has. You should probably set it to a specific version of Ubuntu, so we know and that it won't change in the future.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From here, it looks like Ubuntu 22.

It would be safe to set runs-on to always use Ubuntu 22. That way, we will be made aware of when it is no longer available, a few years from now, and can update accordingly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, I just had a look: Ubuntu 22 seems to ship with Python 3.10.
(→ source)

fredrikaverpil/qt.py:${{ matrix.VFXPLATFORM }}
137 changes: 111 additions & 26 deletions Qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
DOCUMENTATION
Qt.py was born in the film and visual effects industry to address
the growing need for the development of software capable of running
with more than one flavour of the Qt bindings for Python - PySide,
PySide2, PyQt4 and PyQt5.
with more than one flavour of the Qt bindings for Python.

Supported Binding: PySide, PySide2, PySide6, PyQt4, PyQt5

1. Build for one, run with all
2. Explicit is better than implicit
3. Support co-existence

Default resolution order:
- PySide6
- PySide2
- PyQt5
- PySide
Expand Down Expand Up @@ -80,10 +82,12 @@

_common_members = {
"QtCore": [
"Property",
"QAbstractAnimation",
"QAbstractEventDispatcher",
"QAbstractItemModel",
"QAbstractListModel",
"QAbstractProxyModel",
"QAbstractState",
"QAbstractTableModel",
"QAbstractTransition",
Expand Down Expand Up @@ -114,6 +118,8 @@
"QGenericArgument",
"QGenericReturnArgument",
"QHistoryState",
"QItemSelection",
"QItemSelectionModel",
"QItemSelectionRange",
"QIODevice",
"QLibraryInfo",
Expand Down Expand Up @@ -155,8 +161,10 @@
"QSize",
"QSizeF",
"QSocketNotifier",
"QSortFilterProxyModel",
"QState",
"QStateMachine",
"QStringListModel",
"QSysInfo",
"QSystemSemaphore",
"QT_TRANSLATE_NOOP",
Expand Down Expand Up @@ -211,7 +219,9 @@
"qVersion",
"qWarning",
"qrand",
"qsrand"
"qsrand",
"Signal",
"Slot"
],
"QtGui": [
"QAbstractTextDocumentLayout",
Expand Down Expand Up @@ -730,12 +740,14 @@ def messageOutputHandler(*args):
passObject = messageOutputHandler if handler else handler
if Qt.IsPySide or Qt.IsPyQt4:
return Qt._QtCore.qInstallMsgHandler(passObject)
elif Qt.IsPySide2 or Qt.IsPyQt5:
elif Qt.IsPySide2 or Qt.IsPyQt5 or Qt.IsPySide6:
return Qt._QtCore.qInstallMessageHandler(passObject)


def _getcpppointer(object):
if hasattr(Qt, "_shiboken2"):
if hasattr(Qt, "_shiboken6"):
return getattr(Qt, "_shiboken6").getCppPointer(object)[0]
elif hasattr(Qt, "_shiboken2"):
return getattr(Qt, "_shiboken2").getCppPointer(object)[0]
elif hasattr(Qt, "_shiboken"):
return getattr(Qt, "_shiboken").getCppPointer(object)[0]
Expand Down Expand Up @@ -773,6 +785,8 @@ def _wrapinstance(ptr, base=None):
func = getattr(Qt, "_sip").wrapinstance
elif Qt.IsPySide2:
func = getattr(Qt, "_shiboken2").wrapInstance
elif Qt.IsPySide6:
func = getattr(Qt, "_shiboken6").wrapInstance
elif Qt.IsPySide:
func = getattr(Qt, "_shiboken").wrapInstance
else:
Expand Down Expand Up @@ -812,7 +826,10 @@ def _isvalid(object):
object (QObject): QObject to check the validity of.

"""
if hasattr(Qt, "_shiboken2"):
if hasattr(Qt, "_shiboken6"):
return getattr(Qt, "_shiboken6").isValid(object)

elif hasattr(Qt, "_shiboken2"):
return getattr(Qt, "_shiboken2").isValid(object)

elif hasattr(Qt, "_shiboken"):
Expand Down Expand Up @@ -1014,17 +1031,29 @@ def createWidget(self, class_name, parent=None, name=""):

"""
_misplaced_members = {
"PySide6": {
"QtGui.QShortcut": "QtWidgets.QShortcut",
"QtGui.QStringListModel": "QtCore.QStringListModel",
"QtGui.QAction": "QtWidgets.QAction",
"QtUiTools.QUiLoader": ["QtCompat.loadUi", _loadUi],
"shiboken6.wrapInstance": ["QtCompat.wrapInstance", _wrapinstance],
"shiboken6.getCppPointer": ["QtCompat.getCppPointer", _getcpppointer],
"shiboken6.isValid": ["QtCompat.isValid", _isvalid],
"QtWidgets.qApp": "QtWidgets.QApplication.instance()",
"QtCore.QCoreApplication.translate": [
"QtCompat.translate", _translate
],
"QtWidgets.QApplication.translate": [
"QtCompat.translate", _translate
],
"QtCore.qInstallMessageHandler": [
"QtCompat.qInstallMessageHandler", _qInstallMessageHandler
],
"QtWidgets.QStyleOptionViewItem": "QtCompat.QStyleOptionViewItemV4",
"QtMultimedia.QSound": "QtMultimedia.QSound",
},
"PySide2": {
"QtCore.QStringListModel": "QtCore.QStringListModel",
"QtGui.QStringListModel": "QtCore.QStringListModel",
"QtCore.Property": "QtCore.Property",
"QtCore.Signal": "QtCore.Signal",
"QtCore.Slot": "QtCore.Slot",
"QtCore.QAbstractProxyModel": "QtCore.QAbstractProxyModel",
"QtCore.QSortFilterProxyModel": "QtCore.QSortFilterProxyModel",
"QtCore.QItemSelection": "QtCore.QItemSelection",
"QtCore.QItemSelectionModel": "QtCore.QItemSelectionModel",
"QtCore.QItemSelectionRange": "QtCore.QItemSelectionRange",
"QtUiTools.QUiLoader": ["QtCompat.loadUi", _loadUi],
"shiboken2.wrapInstance": ["QtCompat.wrapInstance", _wrapinstance],
"shiboken2.getCppPointer": ["QtCompat.getCppPointer", _getcpppointer],
Expand All @@ -1046,12 +1075,6 @@ def createWidget(self, class_name, parent=None, name=""):
"QtCore.pyqtProperty": "QtCore.Property",
"QtCore.pyqtSignal": "QtCore.Signal",
"QtCore.pyqtSlot": "QtCore.Slot",
"QtCore.QAbstractProxyModel": "QtCore.QAbstractProxyModel",
"QtCore.QSortFilterProxyModel": "QtCore.QSortFilterProxyModel",
"QtCore.QStringListModel": "QtCore.QStringListModel",
"QtCore.QItemSelection": "QtCore.QItemSelection",
"QtCore.QItemSelectionModel": "QtCore.QItemSelectionModel",
"QtCore.QItemSelectionRange": "QtCore.QItemSelectionRange",
"uic.loadUi": ["QtCompat.loadUi", _loadUi],
"sip.wrapinstance": ["QtCompat.wrapInstance", _wrapinstance],
"sip.unwrapinstance": ["QtCompat.getCppPointer", _getcpppointer],
Expand All @@ -1075,9 +1098,6 @@ def createWidget(self, class_name, parent=None, name=""):
"QtGui.QStringListModel": "QtCore.QStringListModel",
"QtGui.QItemSelection": "QtCore.QItemSelection",
"QtGui.QItemSelectionModel": "QtCore.QItemSelectionModel",
"QtCore.Property": "QtCore.Property",
"QtCore.Signal": "QtCore.Signal",
"QtCore.Slot": "QtCore.Slot",
"QtGui.QItemSelectionRange": "QtCore.QItemSelectionRange",
"QtGui.QAbstractPrintDialog": "QtPrintSupport.QAbstractPrintDialog",
"QtGui.QPageSetupDialog": "QtPrintSupport.QPageSetupDialog",
Expand Down Expand Up @@ -1122,7 +1142,6 @@ def createWidget(self, class_name, parent=None, name=""):
"QtGui.QPrintPreviewWidget": "QtPrintSupport.QPrintPreviewWidget",
"QtGui.QPrinter": "QtPrintSupport.QPrinter",
"QtGui.QPrinterInfo": "QtPrintSupport.QPrinterInfo",
# "QtCore.pyqtSignature": "QtCore.Slot",
"uic.loadUi": ["QtCompat.loadUi", _loadUi],
"sip.wrapinstance": ["QtCompat.wrapInstance", _wrapinstance],
"sip.unwrapinstance": ["QtCompat.getCppPointer", _getcpppointer],
Expand Down Expand Up @@ -1157,6 +1176,26 @@ def createWidget(self, class_name, parent=None, name=""):
}
"""
_compatibility_members = {
"PySide6": {
"QWidget": {
"grab": "QtWidgets.QWidget.grab",
},
"QHeaderView": {
"sectionsClickable": "QtWidgets.QHeaderView.sectionsClickable",
"setSectionsClickable":
"QtWidgets.QHeaderView.setSectionsClickable",
"sectionResizeMode": "QtWidgets.QHeaderView.sectionResizeMode",
"setSectionResizeMode":
"QtWidgets.QHeaderView.setSectionResizeMode",
"sectionsMovable": "QtWidgets.QHeaderView.sectionsMovable",
"setSectionsMovable": "QtWidgets.QHeaderView.setSectionsMovable",
},
"QFileDialog": {
"getOpenFileName": "QtWidgets.QFileDialog.getOpenFileName",
"getOpenFileNames": "QtWidgets.QFileDialog.getOpenFileNames",
"getSaveFileName": "QtWidgets.QFileDialog.getSaveFileName",
},
},
"PySide2": {
"QWidget": {
"grab": "QtWidgets.QWidget.grab",
Expand Down Expand Up @@ -1435,6 +1474,50 @@ def _build_compatibility_members(binding, decorators=None):
setattr(Qt.QtCompat, classname, compat_class)


def _pyside6():
"""Initialise PySide6

These functions serve to test the existence of a binding
along with set it up in such a way that it aligns with
the final step; adding members from the original binding
to Qt.py

"""

import PySide6 as module
extras = ["QtUiTools"]
try:
import shiboken6
extras.append("shiboken6")
except ImportError as e:
print("ImportError: %s" % e)

_setup(module, extras)
Qt.__binding_version__ = module.__version__

if hasattr(Qt, "_shiboken6"):
Qt.QtCompat.wrapInstance = _wrapinstance
Qt.QtCompat.getCppPointer = _getcpppointer
Qt.QtCompat.delete = shiboken6.delete

if hasattr(Qt, "_QtUiTools"):
Qt.QtCompat.loadUi = _loadUi

if hasattr(Qt, "_QtCore"):
Qt.__qt_version__ = Qt._QtCore.qVersion()
Qt.QtCompat.dataChanged = (
lambda self, topleft, bottomright, roles=None:
self.dataChanged.emit(topleft, bottomright, roles or [])
)

if hasattr(Qt, "_QtWidgets"):
Qt.QtCompat.setSectionResizeMode = \
Qt._QtWidgets.QHeaderView.setSectionResizeMode

_reassign_misplaced_members("PySide6")
_build_compatibility_members("PySide6")


def _pyside2():
"""Initialise PySide2

Expand Down Expand Up @@ -1821,7 +1904,7 @@ def __call__(self, *a, **kw):

def _install():
# Default order (customize order and content via QT_PREFERRED_BINDING)
default_order = ("PySide2", "PyQt5", "PySide", "PyQt4")
default_order = ("PySide6", "PySide2", "PyQt5", "PySide", "PyQt4")
preferred_order = None
if QT_PREFERRED_BINDING_JSON:
# A per-vendor preferred binding customization was defined
Expand Down Expand Up @@ -1854,6 +1937,7 @@ def _install():
order = preferred_order or default_order

available = {
"PySide6": _pyside6,
"PySide2": _pyside2,
"PyQt5": _pyqt5,
"PySide": _pyside,
Expand Down Expand Up @@ -1938,6 +2022,7 @@ def _install():
_install()

# Setup Binding Enum states
Qt.IsPySide6 = Qt.__binding__ == "PySide6"
Qt.IsPySide2 = Qt.__binding__ == 'PySide2'
Qt.IsPyQt5 = Qt.__binding__ == 'PyQt5'
Qt.IsPySide = Qt.__binding__ == 'PySide'
Expand Down