add PyQt6 to CI
skip tests that don't work for Qt6 add Qt6 and remove Qt4 from test_examples.py update README.md switch mouse tests to use QPointF this eliminates all the special casing for different bindings
This commit is contained in:
parent
eec411a3c6
commit
6c760f3de1
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@ -31,7 +31,7 @@ jobs:
|
|||||||
numpy-version: "~=1.19.0"
|
numpy-version: "~=1.19.0"
|
||||||
- python-version: "3.9"
|
- python-version: "3.9"
|
||||||
qt-lib: "pyqt"
|
qt-lib: "pyqt"
|
||||||
qt-version: "PyQt5~=5.15"
|
qt-version: "PyQt6"
|
||||||
numpy-version: "~=1.19.0"
|
numpy-version: "~=1.19.0"
|
||||||
- python-version: "3.9"
|
- python-version: "3.9"
|
||||||
qt-lib: "pyside"
|
qt-lib: "pyside"
|
||||||
|
@ -9,7 +9,7 @@ PyQtGraph
|
|||||||
[![Total alerts](https://img.shields.io/lgtm/alerts/g/pyqtgraph/pyqtgraph.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/pyqtgraph/pyqtgraph/alerts/)
|
[![Total alerts](https://img.shields.io/lgtm/alerts/g/pyqtgraph/pyqtgraph.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/pyqtgraph/pyqtgraph/alerts/)
|
||||||
[![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/pyqtgraph/pyqtgraph.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/pyqtgraph/pyqtgraph/context:python)
|
[![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/pyqtgraph/pyqtgraph.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/pyqtgraph/pyqtgraph/context:python)
|
||||||
|
|
||||||
A pure-Python graphics library for PyQt5/PySide2/PySide6
|
A pure-Python graphics library for PyQt5/PyQt6/PySide2/PySide6
|
||||||
|
|
||||||
Copyright 2020 Luke Campagnola, University of North Carolina at Chapel Hill
|
Copyright 2020 Luke Campagnola, University of North Carolina at Chapel Hill
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ Currently this means:
|
|||||||
* Python 3.7+
|
* Python 3.7+
|
||||||
* Qt 5.12-6.0
|
* Qt 5.12-6.0
|
||||||
* Required
|
* Required
|
||||||
* PyQt5, PySide2 or PySide6
|
* PyQt5, PyQt6, PySide2 or PySide6
|
||||||
* `numpy` 1.17+
|
* `numpy` 1.17+
|
||||||
* Optional
|
* Optional
|
||||||
* `scipy` for image processing
|
* `scipy` for image processing
|
||||||
@ -57,8 +57,9 @@ The following table represents the python environments we test in our CI system.
|
|||||||
| PySide2-5.12 | :white_check_mark: | :x: | :x: |
|
| PySide2-5.12 | :white_check_mark: | :x: | :x: |
|
||||||
| PyQt5-5.12 | :white_check_mark: | :x: | :x: |
|
| PyQt5-5.12 | :white_check_mark: | :x: | :x: |
|
||||||
| PySide2-5.15 | :x: | :white_check_mark: | :x: |
|
| PySide2-5.15 | :x: | :white_check_mark: | :x: |
|
||||||
| PyQt5-5.15 | :x: | :white_check_mark: | :white_check_mark: |
|
| PyQt5-5.15 | :x: | :white_check_mark: | :x: |
|
||||||
| PySide6-6.0 | :x: | :x: | :white_check_mark: |
|
| PySide6-6.0 | :x: | :x: | :white_check_mark: |
|
||||||
|
| PyQt6-6.0 | :x: | :x: | :white_check_mark: |
|
||||||
|
|
||||||
Support
|
Support
|
||||||
-------
|
-------
|
||||||
|
@ -35,10 +35,10 @@ def buildFileList(examples, files=None):
|
|||||||
path = os.path.abspath(os.path.dirname(__file__))
|
path = os.path.abspath(os.path.dirname(__file__))
|
||||||
files = sorted(set(buildFileList(examples)))
|
files = sorted(set(buildFileList(examples)))
|
||||||
frontends = {
|
frontends = {
|
||||||
Qt.PYQT4: False,
|
|
||||||
Qt.PYQT5: False,
|
Qt.PYQT5: False,
|
||||||
Qt.PYSIDE: False,
|
Qt.PYQT6: False,
|
||||||
Qt.PYSIDE2: False
|
Qt.PYSIDE2: False,
|
||||||
|
Qt.PYSIDE6: False,
|
||||||
}
|
}
|
||||||
# sort out which of the front ends are available
|
# sort out which of the front ends are available
|
||||||
for frontend in frontends.keys():
|
for frontend in frontends.keys():
|
||||||
@ -66,13 +66,6 @@ conditionalExamples = {
|
|||||||
False,
|
False,
|
||||||
reason="Test is being problematic on CI machines"
|
reason="Test is being problematic on CI machines"
|
||||||
),
|
),
|
||||||
"optics_demos.py": exceptionCondition(
|
|
||||||
not frontends[Qt.PYSIDE],
|
|
||||||
reason=(
|
|
||||||
"Test fails due to PySide bug: ",
|
|
||||||
"https://bugreports.qt.io/browse/PYSIDE-671"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'GLVolumeItem.py': exceptionCondition(
|
'GLVolumeItem.py': exceptionCondition(
|
||||||
not(platform.system() == "Darwin" and
|
not(platform.system() == "Darwin" and
|
||||||
tuple(map(int, platform.mac_ver()[0].split("."))) >= (10, 16) and
|
tuple(map(int, platform.mac_ver()[0].split("."))) >= (10, 16) and
|
||||||
|
@ -7,7 +7,7 @@ pytest.importorskip("matplotlib")
|
|||||||
app = pg.mkQApp()
|
app = pg.mkQApp()
|
||||||
|
|
||||||
skip_qt6 = pytest.mark.skipif(
|
skip_qt6 = pytest.mark.skipif(
|
||||||
pg.QT_LIB == "PySide6",
|
pg.QT_LIB in ["PySide6", "PyQt6"],
|
||||||
reason= (
|
reason= (
|
||||||
"Matplotlib has no Qt6 support yet, "
|
"Matplotlib has no Qt6 support yet, "
|
||||||
"see https://github.com/matplotlib/matplotlib/pull/19255"
|
"see https://github.com/matplotlib/matplotlib/pull/19255"
|
||||||
|
@ -63,8 +63,8 @@ def test_mouseInteraction():
|
|||||||
plt.setYRange(-10, 10)
|
plt.setYRange(-10, 10)
|
||||||
|
|
||||||
# test horizontal drag
|
# test horizontal drag
|
||||||
pos = plt.plotItem.vb.mapViewToScene(pg.Point(0,5)).toPoint()
|
pos = plt.plotItem.vb.mapViewToScene(pg.Point(0,5))
|
||||||
pos2 = pos - QtCore.QPoint(200, 200)
|
pos2 = pos - QtCore.QPointF(200, 200)
|
||||||
mouseMove(plt, pos)
|
mouseMove(plt, pos)
|
||||||
assert vline.mouseHovering is True and hline.mouseHovering is False
|
assert vline.mouseHovering is True and hline.mouseHovering is False
|
||||||
mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
|
mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
|
||||||
@ -72,17 +72,17 @@ def test_mouseInteraction():
|
|||||||
assert abs(vline.value() - plt.plotItem.vb.mapSceneToView(pos2).x()) <= px
|
assert abs(vline.value() - plt.plotItem.vb.mapSceneToView(pos2).x()) <= px
|
||||||
|
|
||||||
# test missed drag
|
# test missed drag
|
||||||
pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,0)).toPoint()
|
pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,0))
|
||||||
pos = pos + QtCore.QPoint(0, 6)
|
pos = pos + QtCore.QPointF(0, 6)
|
||||||
pos2 = pos + QtCore.QPoint(-20, -20)
|
pos2 = pos + QtCore.QPointF(-20, -20)
|
||||||
mouseMove(plt, pos)
|
mouseMove(plt, pos)
|
||||||
assert vline.mouseHovering is False and hline.mouseHovering is False
|
assert vline.mouseHovering is False and hline.mouseHovering is False
|
||||||
mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
|
mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
|
||||||
assert hline.value() == 0
|
assert hline.value() == 0
|
||||||
|
|
||||||
# test vertical drag
|
# test vertical drag
|
||||||
pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,0)).toPoint()
|
pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,0))
|
||||||
pos2 = pos - QtCore.QPoint(50, 50)
|
pos2 = pos - QtCore.QPointF(50, 50)
|
||||||
mouseMove(plt, pos)
|
mouseMove(plt, pos)
|
||||||
assert vline.mouseHovering is False and hline.mouseHovering is True
|
assert vline.mouseHovering is False and hline.mouseHovering is True
|
||||||
mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
|
mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
|
||||||
@ -90,8 +90,8 @@ def test_mouseInteraction():
|
|||||||
assert abs(hline.value() - plt.plotItem.vb.mapSceneToView(pos2).y()) <= px
|
assert abs(hline.value() - plt.plotItem.vb.mapSceneToView(pos2).y()) <= px
|
||||||
|
|
||||||
# test non-interactive line
|
# test non-interactive line
|
||||||
pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,-1)).toPoint()
|
pos = plt.plotItem.vb.mapViewToScene(pg.Point(5,-1))
|
||||||
pos2 = pos - QtCore.QPoint(50, 50)
|
pos2 = pos - QtCore.QPointF(50, 50)
|
||||||
mouseMove(plt, pos)
|
mouseMove(plt, pos)
|
||||||
assert hline2.mouseHovering == False
|
assert hline2.mouseHovering == False
|
||||||
mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
|
mouseDrag(plt, pos, pos2, QtCore.Qt.LeftButton)
|
||||||
|
@ -257,7 +257,7 @@ def assertImageMatch(im1, im2, minCorr=None, pxThreshold=50.,
|
|||||||
assert im1.dtype == im2.dtype
|
assert im1.dtype == im2.dtype
|
||||||
|
|
||||||
if pxCount == -1:
|
if pxCount == -1:
|
||||||
if QT_LIB in {'PyQt5', 'PySide2', 'PySide6'}:
|
if QT_LIB in {'PyQt5', 'PySide2', 'PySide6', 'PyQt6'}:
|
||||||
# Qt5 generates slightly different results; relax the tolerance
|
# Qt5 generates slightly different results; relax the tolerance
|
||||||
# until test images are updated.
|
# until test images are updated.
|
||||||
pxCount = int(im1.shape[0] * im1.shape[1] * 0.01)
|
pxCount = int(im1.shape[0] * im1.shape[1] * 0.01)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import time
|
import time
|
||||||
from ..Qt import QtCore, QtGui, QtTest, QT_LIB
|
from ..Qt import QtCore, QtGui, QtTest
|
||||||
|
|
||||||
|
|
||||||
def resizeWindow(win, w, h, timeout=2.0):
|
def resizeWindow(win, w, h, timeout=2.0):
|
||||||
@ -32,8 +32,6 @@ def mousePress(widget, pos, button, modifier=None):
|
|||||||
widget = widget.viewport()
|
widget = widget.viewport()
|
||||||
if modifier is None:
|
if modifier is None:
|
||||||
modifier = QtCore.Qt.NoModifier
|
modifier = QtCore.Qt.NoModifier
|
||||||
if QT_LIB != 'PyQt5' and isinstance(pos, QtCore.QPointF):
|
|
||||||
pos = pos.toPoint()
|
|
||||||
event = QtGui.QMouseEvent(QtCore.QEvent.MouseButtonPress, pos, button, QtCore.Qt.NoButton, modifier)
|
event = QtGui.QMouseEvent(QtCore.QEvent.MouseButtonPress, pos, button, QtCore.Qt.NoButton, modifier)
|
||||||
QtGui.QApplication.sendEvent(widget, event)
|
QtGui.QApplication.sendEvent(widget, event)
|
||||||
|
|
||||||
@ -43,8 +41,6 @@ def mouseRelease(widget, pos, button, modifier=None):
|
|||||||
widget = widget.viewport()
|
widget = widget.viewport()
|
||||||
if modifier is None:
|
if modifier is None:
|
||||||
modifier = QtCore.Qt.NoModifier
|
modifier = QtCore.Qt.NoModifier
|
||||||
if QT_LIB != 'PyQt5' and isinstance(pos, QtCore.QPointF):
|
|
||||||
pos = pos.toPoint()
|
|
||||||
event = QtGui.QMouseEvent(QtCore.QEvent.MouseButtonRelease, pos, button, QtCore.Qt.NoButton, modifier)
|
event = QtGui.QMouseEvent(QtCore.QEvent.MouseButtonRelease, pos, button, QtCore.Qt.NoButton, modifier)
|
||||||
QtGui.QApplication.sendEvent(widget, event)
|
QtGui.QApplication.sendEvent(widget, event)
|
||||||
|
|
||||||
@ -56,8 +52,6 @@ def mouseMove(widget, pos, buttons=None, modifier=None):
|
|||||||
modifier = QtCore.Qt.NoModifier
|
modifier = QtCore.Qt.NoModifier
|
||||||
if buttons is None:
|
if buttons is None:
|
||||||
buttons = QtCore.Qt.NoButton
|
buttons = QtCore.Qt.NoButton
|
||||||
if QT_LIB != 'PyQt5' and isinstance(pos, QtCore.QPointF):
|
|
||||||
pos = pos.toPoint()
|
|
||||||
event = QtGui.QMouseEvent(QtCore.QEvent.MouseMove, pos, QtCore.Qt.NoButton, buttons, modifier)
|
event = QtGui.QMouseEvent(QtCore.QEvent.MouseMove, pos, QtCore.Qt.NoButton, buttons, modifier)
|
||||||
QtGui.QApplication.sendEvent(widget, event)
|
QtGui.QApplication.sendEvent(widget, event)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user