From 260e6d611afae9adaac528c28a4879097c357b74 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sun, 24 Jun 2018 16:20:36 -0400 Subject: [PATCH 1/2] Fix import of PyQt5 5.11. sip is not really required by this code when using PyQt5, and 5.11 now no longer requires it nor provides it globally [1]. Also, move the PyQt/PySide shim bits to the end to be near the Qt5/Qt4 shim. [1] http://pyqt.sourceforge.net/Docs/PyQt5/incompatibilities.html#pyqt-v5-11 --- lib/matplotlib/backends/qt_compat.py | 55 +++++++++++++--------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/lib/matplotlib/backends/qt_compat.py b/lib/matplotlib/backends/qt_compat.py index e02e881a3969..759fe24a7a66 100644 --- a/lib/matplotlib/backends/qt_compat.py +++ b/lib/matplotlib/backends/qt_compat.py @@ -98,7 +98,7 @@ _sip_imported = False # Now perform the imports. -if QT_API in (QT_API_PYQT, QT_API_PYQTv2, QT_API_PYQT5): +if QT_API in (QT_API_PYQT, QT_API_PYQTv2): try: import sip _sip_imported = True @@ -131,18 +131,20 @@ except: res = 'QVariant API v2 specification failed. Defaulting to v1.' _log.info(cond + res) - if QT_API == QT_API_PYQT5: - try: - from PyQt5 import QtCore, QtGui, QtWidgets - _getSaveFileName = QtWidgets.QFileDialog.getSaveFileName - except ImportError: - if _fallback_to_qt4: - # fell through, tried PyQt5, failed fall back to PyQt4 - QT_API = QT_API_PYQT - QT_RC_MAJOR_VERSION = 4 - else: - raise +if QT_API == QT_API_PYQT5: + try: + from PyQt5 import QtCore, QtGui, QtWidgets + _getSaveFileName = QtWidgets.QFileDialog.getSaveFileName + except ImportError: + if _fallback_to_qt4: + # fell through, tried PyQt5, failed fall back to PyQt4 + QT_API = QT_API_PYQT + QT_RC_MAJOR_VERSION = 4 + else: + raise + +if _sip_imported: # needs to be if so we can re-test the value of QT_API which may # have been changed in the above if block if QT_API in [QT_API_PYQT, QT_API_PYQTv2]: # PyQt4 API @@ -164,23 +166,6 @@ def _getSaveFileName(*args, **kwargs): # call to getapi() can fail in older versions of sip def _getSaveFileName(*args, **kwargs): return QtGui.QFileDialog.getSaveFileName(*args, **kwargs), None - try: - # Alias PyQt-specific functions for PySide compatibility. - QtCore.Signal = QtCore.pyqtSignal - try: - QtCore.Slot = QtCore.pyqtSlot - except AttributeError: - # Not a perfect match but works in simple cases - QtCore.Slot = QtCore.pyqtSignature - - QtCore.Property = QtCore.pyqtProperty - __version__ = QtCore.PYQT_VERSION_STR - except NameError: - # QtCore did not get imported, fall back to pyside - if QT_RC_MAJOR_VERSION == 5: - QT_API = QT_API_PYSIDE2 - else: - QT_API = QT_API_PYSIDE if QT_API == QT_API_PYSIDE2: @@ -207,6 +192,18 @@ def _getSaveFileName(*args, **kwargs): _getSaveFileName = QtGui.QFileDialog.getSaveFileName +if QT_API in (QT_API_PYQT, QT_API_PYQTv2, QT_API_PYQT5): + # Alias PyQt-specific functions for PySide compatibility. + QtCore.Signal = QtCore.pyqtSignal + try: + QtCore.Slot = QtCore.pyqtSlot + except AttributeError: + # Not a perfect match but works in simple cases + QtCore.Slot = QtCore.pyqtSignature + + QtCore.Property = QtCore.pyqtProperty + __version__ = QtCore.PYQT_VERSION_STR + # Apply shim to Qt4 APIs to make them look like Qt5 if QT_API in (QT_API_PYQT, QT_API_PYQTv2, QT_API_PYSIDE): '''Import all used QtGui objects into QtWidgets From 26fbd92763c57df541af0314838f5804bc8fa67a Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sun, 24 Jun 2018 16:21:04 -0400 Subject: [PATCH 2/2] Remove unnecessary Qt signal connection. This fails with PyQt5.11, but is also unnecessary. `_destroying` is set to True before this signal is connected, so the callback simply returns immediately. Thus, just remove the connection entirely. --- lib/matplotlib/backends/backend_qt5.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index ddbdf56e8177..6287c706091d 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -671,7 +671,6 @@ def destroy(self, *args): if self.window._destroying: return self.window._destroying = True - self.window.destroyed.connect(self._widgetclosed) if self.toolbar: self.toolbar.destroy() self.window.close()