From 767e944e9fa0836a6698d07f903de9d188a4f888 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 22 Feb 2016 21:30:04 +0000 Subject: [PATCH 1/4] Make _forbidden an attribute of ImportHook, as otherwise in some corner cases, _forbidden can become reset to None, causing issues. --- qt_helpers.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/qt_helpers.py b/qt_helpers.py index 5446ef4..defbac7 100644 --- a/qt_helpers.py +++ b/qt_helpers.py @@ -80,20 +80,16 @@ def is_pyqt5(): is_pyqt = is_pyqt4 QT_API_PYQT = QT_API_PYQT4 -_forbidden = set() - - -def deny_module(module): - _forbidden.add(module) - class ImportDenier(object): """ Import hook to protect importing of both PySide and PyQt. """ + _forbidden = set() + def find_module(self, mod_name, pth): - if pth or not mod_name in _forbidden: + if pth or not mod_name in self._forbidden: return else: return self @@ -102,6 +98,8 @@ def load_module(self, mod_name): raise ImportError("Importing %s forbidden by %s" % (mod_name, __name__)) + def deny_module(self, module): + self._forbidden.add(module) _import_hook = ImportDenier() sys.meta_path.append(_import_hook) @@ -154,8 +152,8 @@ def _load_pyqt4(): global QT_API QT_API = QT_API_PYQT4 - deny_module('PySide') - deny_module('PyQt5') + _import_hook.deny_module('PySide') + _import_hook.deny_module('PyQt5') def _load_pyqt5(): @@ -185,8 +183,8 @@ def _load_pyqt5(): global QT_API QT_API = QT_API_PYQT5 - deny_module('PySide') - deny_module('PyQt4') + _import_hook.deny_module('PySide') + _import_hook.deny_module('PyQt4') def _load_pyside(): @@ -208,8 +206,8 @@ def setMargin(self, x): global QT_API QT_API = QT_API_PYSIDE - deny_module('PyQt4') - deny_module('PyQt5') + _import_hook.deny_module('PyQt4') + _import_hook.deny_module('PyQt5') QtCore = None @@ -227,7 +225,7 @@ def reload_qt(): e.g. PySide if PyQt4 is loaded). """ - _forbidden.clear() + _import_hook._forbidden.clear() global QtCore global QtGui From 4879b0e3de0b43e75a1ab82d0f975e0a76ee5b8c Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 22 Feb 2016 21:30:20 +0000 Subject: [PATCH 2/4] Keep a global reference to QApplication instance --- qt_helpers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qt_helpers.py b/qt_helpers.py index defbac7..2887657 100644 --- a/qt_helpers.py +++ b/qt_helpers.py @@ -296,7 +296,10 @@ def _load_ui_pyqt5(path, parent): return loadUi(path, parent) +qapp = None + def get_qapp(icon_path=None): + global qapp qapp = QtGui.QApplication.instance() if qapp is None: qapp = QtGui.QApplication(['']) From 8d3d55146b25d5c12f4851a5ce15fb62058d57b9 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 22 Feb 2016 21:39:41 +0000 Subject: [PATCH 3/4] Fix test --- test_switch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_switch.py b/test_switch.py index b59a8e4..4d9b068 100644 --- a/test_switch.py +++ b/test_switch.py @@ -18,7 +18,7 @@ def teardown_class(cls): sys.modules.pop(m) def setup_method(self, method): - qt.deny_module(None) + qt._import_hook.deny_module(None) if 'QT_API' in os.environ: os.environ.pop('QT_API') From a47fdf0d389efd64b0bd3f5a810c80695c0c379b Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Tue, 23 Feb 2016 10:04:30 +0000 Subject: [PATCH 4/4] Make sure QApplication is quit before changing Qt framework --- qt_helpers.py | 7 +++++++ test_switch.py | 11 +---------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/qt_helpers.py b/qt_helpers.py index 2887657..828a61e 100644 --- a/qt_helpers.py +++ b/qt_helpers.py @@ -225,8 +225,15 @@ def reload_qt(): e.g. PySide if PyQt4 is loaded). """ + # Clear any forbidden modules _import_hook._forbidden.clear() + # Quit app if active + global qapp + if qapp is not None: + qapp.quit() + qapp = None + global QtCore global QtGui diff --git a/test_switch.py b/test_switch.py index 4d9b068..57b0275 100644 --- a/test_switch.py +++ b/test_switch.py @@ -13,7 +13,7 @@ class TestQT(object): def teardown_class(cls): - for m in sys.modules.keys(): + for m in list(sys.modules.keys()): if m.startswith('PyQt4') or m.startswith('PySide'): sys.modules.pop(m) @@ -62,16 +62,13 @@ def test_load_ui_qt4(self): app = get_qapp() load_ui('test.ui') app.quit() - del app def test_load_ui_pyside(self): self._load_pyside() from qt_helpers import load_ui, get_qapp app = get_qapp() load_ui('test.ui') - app.exit() app.quit() - del app def test_submodule_import(self): self._load_qt4() @@ -140,8 +137,6 @@ def test_launch_after_reload(self): time.sleep(0.1) app.quit() - del app - os.environ['QT_API'] = qt.QT_API_PYQT4 qt.reload_qt() @@ -155,8 +150,6 @@ def test_launch_after_reload(self): time.sleep(0.1) app.quit() - del app - os.environ['QT_API'] = qt.QT_API_PYSIDE qt.reload_qt() @@ -169,5 +162,3 @@ def test_launch_after_reload(self): app.flush() time.sleep(0.1) app.quit() - - del app