1 """ Import Qt in a manner suitable for an IPython kernel. 2 3 This is the import used for the `gui=qt` or `matplotlib=qt` initialization. 4 5 Import Priority: 6 7 if Qt has been imported anywhere else: 8 use that 9 10 if matplotlib has been imported and doesn't support v2 (<= 1.0.1): 11 use PyQt4 @v1 12 13 Next, ask QT_API env variable 14 15 if QT_API not set: 16 ask matplotlib what it's using. If Qt4Agg or Qt5Agg, then use the 17 version matplotlib is configured with 18 19 else: (matplotlib said nothing) 20 # this is the default path - nobody told us anything 21 try in this order: 22 PyQt default version, PySide, PyQt5 23 else: 24 use what QT_API says 25 26 Note that %gui's implementation will always set a `QT_API`, see 27 `IPython.terminal.pt_inputhooks.get_inputhook_name_and_func` 28 29 """ 30 # NOTE: This is no longer an external, third-party module, and should be 31 # considered part of IPython. For compatibility however, it is being kept in 32 # IPython/external. 33 34 import os 35 import sys 36 37 from IPython.external.qt_loaders import ( 38 load_qt, 39 loaded_api, 40 enum_factory, 41 # QT6 42 QT_API_PYQT6, 43 QT_API_PYSIDE6, 44 # QT5 45 QT_API_PYQT5, 46 QT_API_PYSIDE2, 47 # QT4 48 QT_API_PYQT, 49 QT_API_PYSIDE, 50 # default 51 QT_API_PYQT_DEFAULT, 52 ) 53 54 _qt_apis = ( 55 # QT6 56 QT_API_PYQT6, 57 QT_API_PYSIDE6, 58 # QT5 59 QT_API_PYQT5, 60 QT_API_PYSIDE2, 61 # default 62 QT_API_PYQT_DEFAULT, 63 ) 64 65 66 def matplotlib_options(mpl): 67 """Constraints placed on an imported matplotlib.""" 68 if mpl is None: 69 return 70 backend = mpl.rcParams.get('backend', None) 71 if backend == 'Qt4Agg': 72 mpqt = mpl.rcParams.get('backend.qt4', None) 73 if mpqt is None: 74 return None 75 if mpqt.lower() == 'pyside': 76 return [QT_API_PYSIDE] 77 elif mpqt.lower() == 'pyqt4': 78 return [QT_API_PYQT_DEFAULT] 79 elif mpqt.lower() == 'pyqt4v2': 80 return [QT_API_PYQT] 81 raise ImportError("unhandled value for backend.qt4 from matplotlib: %r" % 82 mpqt) 83 elif backend == 'Qt5Agg': 84 mpqt = mpl.rcParams.get('backend.qt5', None) 85 if mpqt is None: 86 return None 87 if mpqt.lower() == 'pyqt5': 88 return [QT_API_PYQT5] 89 raise ImportError("unhandled value for backend.qt5 from matplotlib: %r" % 90 mpqt) 91 92 def get_options(): 93 """Return a list of acceptable QT APIs, in decreasing order of preference.""" 94 #already imported Qt somewhere. Use that 95 loaded = loaded_api() 96 if loaded is not None: 97 return [loaded] 98 99 mpl = sys.modules.get("matplotlib", None) 100 101 if mpl is not None and tuple(mpl.__version__.split(".")) < ("1", "0", "2"): 102 # 1.0.1 only supports PyQt4 v1 103 return [QT_API_PYQT_DEFAULT] 104 105 qt_api = os.environ.get('QT_API', None) 106 if qt_api is None: 107 #no ETS variable. Ask mpl, then use default fallback path 108 return matplotlib_options(mpl) or [ 109 QT_API_PYQT_DEFAULT, 110 QT_API_PYQT6, 111 QT_API_PYSIDE6, 112 QT_API_PYQT5, 113 QT_API_PYSIDE2, 114 ] 115 elif qt_api not in _qt_apis: 116 raise RuntimeError("Invalid Qt API %r, valid values are: %r" % 117 (qt_api, ', '.join(_qt_apis))) 118 else: 119 return [qt_api] 120 121 122 api_opts = get_options() 123 QtCore, QtGui, QtSvg, QT_API = load_qt(api_opts) 124 enum_helper = enum_factory(QT_API, QtCore) 125