From 6b5ea5bcc83447c1c2be23069ddc98a0d941e396 Mon Sep 17 00:00:00 2001 From: Thorsten Liebig Date: Sun, 7 Feb 2016 22:50:35 +0100 Subject: [PATCH 1/2] add support for PySide2, #5971 Signed-off-by: Thorsten Liebig --- lib/matplotlib/backends/qt_compat.py | 22 +++++++++++++++++----- lib/matplotlib/rcsetup.py | 2 +- setupext.py | 28 +++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/lib/matplotlib/backends/qt_compat.py b/lib/matplotlib/backends/qt_compat.py index 67d0687a7ca..a0917864156 100644 --- a/lib/matplotlib/backends/qt_compat.py +++ b/lib/matplotlib/backends/qt_compat.py @@ -13,10 +13,11 @@ QT_API_PYQT = 'PyQt4' # API is not set here; Python 2.x default is V 1 QT_API_PYQTv2 = 'PyQt4v2' # forced to Version 2 API QT_API_PYSIDE = 'PySide' # only supports Version 2 API -QT_API_PYQT5 = 'PyQt5' # use PyQt5 API; Version 2 with module shim +QT_API_PYQT5 = 'PyQt5' # use PyQt5 API; Version 2 with module shim +QT_API_PYSIDE2 = 'PySide2' # Version 2 API with module shim ETS = dict(pyqt=(QT_API_PYQTv2, 4), pyside=(QT_API_PYSIDE, 4), - pyqt5=(QT_API_PYQT5, 5)) + pyqt5=(QT_API_PYQT5, 5), pyside2=(QT_API_PYSIDE2, 5)) # ETS is a dict of env variable to (QT_API, QT_MAJOR_VERSION) # If the ETS QT_API environment variable is set, use it, but only # if the varible if of the same major QT version. Note that @@ -64,7 +65,7 @@ # A different backend was specified, but we still got here because a Qt # related file was imported. This is allowed, so lets try and guess # what we should be using. - if "PyQt4" in sys.modules or "PySide" in sys.modules: + if "PyQt4" in sys.modules or ("PySide" in sys.modules and not "PySide2" in sys.modules): # PyQt4 or PySide is actually used. QT_API = rcParams['backend.qt4'] else: @@ -154,13 +155,24 @@ def _getSaveFileName(*args, **kwargs): # QtCore did not get imported, fall back to pyside QT_API = QT_API_PYSIDE + +if QT_API == QT_API_PYSIDE2: + try: + from PySide2 import QtCore, QtGui, QtWidgets, __version__ + _getSaveFileName = QtWidgets.QFileDialog.getSaveFileName + except ImportError: + # tried PySide2, failed, fall back to PySide + QT_API = rcParams['backend.qt4'] + QT_RC_MAJOR_VERSION = 4 + QT_API = QT_API_PYSIDE + if QT_API == QT_API_PYSIDE: # try importing pyside try: from PySide import QtCore, QtGui, __version__, __version_info__ except ImportError: raise ImportError( - "Matplotlib qt-based backends require an external PyQt4, PyQt5,\n" - "or PySide package to be installed, but it was not found.") + "Matplotlib qt-based backends require an external PyQt4, PyQt5, PySide,\n" + "or PySide2 package to be installed, but it was not found.") if __version_info__ < (1, 0, 3): raise ImportError( diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index f8c23986708..70d95055e4c 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -243,7 +243,7 @@ def validate_backend(s): validate_qt4 = ValidateInStrings('backend.qt4', ['PyQt4', 'PySide', 'PyQt4v2']) -validate_qt5 = ValidateInStrings('backend.qt5', ['PyQt5']) +validate_qt5 = ValidateInStrings('backend.qt5', ['PyQt5', 'PySide2']) def validate_toolbar(s): diff --git a/setupext.py b/setupext.py index b130679ce9f..0d0f0bca3e3 100755 --- a/setupext.py +++ b/setupext.py @@ -2207,8 +2207,18 @@ def __init__(self, *args, **kwargs): BackendQtBase.__init__(self, *args, **kwargs) self.callback = backend_qt4_internal_check +def backend_pyside2_internal_check(self): + try: + from PySide2 import __version__ + from PySide2 import QtCore + except ImportError: + raise CheckFailed("PySide2 not found") + else: + BackendAgg.force = True + return ("Qt: %s, PySide2: %s" % + (QtCore.__version__, __version__)) -def backend_qt5_internal_check(self): +def backend_pyqt5_internal_check(self): try: from PyQt5 import QtCore except ImportError: @@ -2223,6 +2233,22 @@ def backend_qt5_internal_check(self): BackendAgg.force = True return ("Qt: %s, PyQt: %s" % (self.convert_qt_version(qt_version), pyqt_version_str)) +def backend_qt5_internal_check(self): + successes = [] + failures = [] + try: + successes.append(backend_pyside2_internal_check(self)) + except CheckFailed as e: + failures.append(str(e)) + + try: + successes.append(backend_pyqt5_internal_check(self)) + except CheckFailed as e: + failures.append(str(e)) + + if len(successes) == 0: + raise CheckFailed('; '.join(failures)) + return '; '.join(successes + failures) class BackendQt5(BackendQtBase): name = "qt5agg" From 118ef3b75eb64189a22a5ad7d5a4b6143ae0d5de Mon Sep 17 00:00:00 2001 From: Thorsten Liebig Date: Sun, 7 Feb 2016 23:44:57 +0100 Subject: [PATCH 2/2] PySide2: fix some problems in qt_compat, #5971 Signed-off-by: Thorsten Liebig --- lib/matplotlib/backends/qt_compat.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/backends/qt_compat.py b/lib/matplotlib/backends/qt_compat.py index a0917864156..e30796537eb 100644 --- a/lib/matplotlib/backends/qt_compat.py +++ b/lib/matplotlib/backends/qt_compat.py @@ -65,11 +65,11 @@ # A different backend was specified, but we still got here because a Qt # related file was imported. This is allowed, so lets try and guess # what we should be using. - if "PyQt4" in sys.modules or ("PySide" in sys.modules and not "PySide2" in sys.modules): + if "PyQt4" in sys.modules or "PySide" in sys.modules: # PyQt4 or PySide is actually used. QT_API = rcParams['backend.qt4'] else: - # This is a fallback: PyQt5 + # This is a fallback: PyQt5 or PySide2 QT_API = rcParams['backend.qt5'] # We will define an appropriate wrapper for the differing versions @@ -171,8 +171,8 @@ def _getSaveFileName(*args, **kwargs): from PySide import QtCore, QtGui, __version__, __version_info__ except ImportError: raise ImportError( - "Matplotlib qt-based backends require an external PyQt4, PyQt5, PySide,\n" - "or PySide2 package to be installed, but it was not found.") + "Matplotlib qt-based backends require an external PyQt4, PyQt5,\n" + "PySide or PySide2 package to be installed, but it was not found.") if __version_info__ < (1, 0, 3): raise ImportError(