##// END OF EJS Templates
Formatting
Emilio Graff -
Show More
@@ -1,147 +1,147 b''
1 import importlib
1 import importlib
2 import os
2 import os
3
3
4 aliases = {
4 aliases = {
5 'qt4': 'qt',
5 'qt4': 'qt',
6 'gtk2': 'gtk',
6 'gtk2': 'gtk',
7 }
7 }
8
8
9 backends = [
9 backends = [
10 "qt",
10 "qt",
11 "qt4",
11 "qt4",
12 "qt5",
12 "qt5",
13 "qt6",
13 "qt6",
14 "gtk",
14 "gtk",
15 "gtk2",
15 "gtk2",
16 "gtk3",
16 "gtk3",
17 "gtk4",
17 "gtk4",
18 "tk",
18 "tk",
19 "wx",
19 "wx",
20 "pyglet",
20 "pyglet",
21 "glut",
21 "glut",
22 "osx",
22 "osx",
23 "asyncio",
23 "asyncio",
24 ]
24 ]
25
25
26 registered = {}
26 registered = {}
27
27
28 def register(name, inputhook):
28 def register(name, inputhook):
29 """Register the function *inputhook* as an event loop integration."""
29 """Register the function *inputhook* as an event loop integration."""
30 registered[name] = inputhook
30 registered[name] = inputhook
31
31
32
32
33 class UnknownBackend(KeyError):
33 class UnknownBackend(KeyError):
34 def __init__(self, name):
34 def __init__(self, name):
35 self.name = name
35 self.name = name
36
36
37 def __str__(self):
37 def __str__(self):
38 return ("No event loop integration for {!r}. "
38 return ("No event loop integration for {!r}. "
39 "Supported event loops are: {}").format(self.name,
39 "Supported event loops are: {}").format(self.name,
40 ', '.join(backends + sorted(registered)))
40 ', '.join(backends + sorted(registered)))
41
41
42
42
43 def set_qt_api(gui):
43 def set_qt_api(gui):
44 """Sets the `QT_API` environment variable if it isn't already set."""
44 """Sets the `QT_API` environment variable if it isn't already set."""
45
45
46 qt_api = os.environ.get("QT_API", None)
46 qt_api = os.environ.get("QT_API", None)
47
47
48 from IPython.external.qt_loaders import (
48 from IPython.external.qt_loaders import (
49 QT_API_PYQT,
49 QT_API_PYQT,
50 QT_API_PYQT5,
50 QT_API_PYQT5,
51 QT_API_PYQT6,
51 QT_API_PYQT6,
52 QT_API_PYSIDE,
52 QT_API_PYSIDE,
53 QT_API_PYSIDE2,
53 QT_API_PYSIDE2,
54 QT_API_PYSIDE6,
54 QT_API_PYSIDE6,
55 QT_API_PYQTv1,
55 QT_API_PYQTv1,
56 loaded_api,
56 loaded_api,
57 )
57 )
58
58
59 loaded = loaded_api()
59 loaded = loaded_api()
60
60
61 qt_env2gui = {
61 qt_env2gui = {
62 QT_API_PYSIDE: 'qt4',
62 QT_API_PYSIDE: "qt4",
63 QT_API_PYQTv1: 'qt4',
63 QT_API_PYQTv1: "qt4",
64 QT_API_PYQT: 'qt4',
64 QT_API_PYQT: "qt4",
65 QT_API_PYSIDE2: 'qt5',
65 QT_API_PYSIDE2: "qt5",
66 QT_API_PYQT5: 'qt5',
66 QT_API_PYQT5: "qt5",
67 QT_API_PYSIDE6: 'qt6',
67 QT_API_PYSIDE6: "qt6",
68 QT_API_PYQT6: 'qt6',
68 QT_API_PYQT6: "qt6",
69 }
69 }
70 if loaded is not None and gui != 'qt':
70 if loaded is not None and gui != "qt":
71 if qt_env2gui[loaded] != gui:
71 if qt_env2gui[loaded] != gui:
72 raise ImportError(
72 raise ImportError(
73 f'Cannot switch Qt versions for this session; must use {qt_env2gui[loaded]}.'
73 f"Cannot switch Qt versions for this session; must use {qt_env2gui[loaded]}."
74 )
74 )
75
75
76 if qt_api is not None and gui != 'qt':
76 if qt_api is not None and gui != "qt":
77 if qt_env2gui[qt_api] != gui:
77 if qt_env2gui[qt_api] != gui:
78 print(
78 print(
79 f'Request for "{gui}" will be ignored because `QT_API` '
79 f'Request for "{gui}" will be ignored because `QT_API` '
80 f'environment variable is set to "{qt_api}"'
80 f'environment variable is set to "{qt_api}"'
81 )
81 )
82 else:
82 else:
83 # NOTE: 'qt4' is not selectable because it's set as an alias for 'qt'; see `aliases` above.
83 # NOTE: 'qt4' is not selectable because it's set as an alias for 'qt'; see `aliases` above.
84 if gui == "qt4":
84 if gui == "qt4":
85 try:
85 try:
86 import PyQt # noqa
86 import PyQt # noqa
87
87
88 os.environ["QT_API"] = "pyqt"
88 os.environ["QT_API"] = "pyqt"
89 except ImportError:
89 except ImportError:
90 try:
90 try:
91 import PySide # noqa
91 import PySide # noqa
92
92
93 os.environ["QT_API"] = "pyside"
93 os.environ["QT_API"] = "pyside"
94 except ImportError:
94 except ImportError:
95 # Neither implementation installed; set it to something so IPython gives an error
95 # Neither implementation installed; set it to something so IPython gives an error
96 os.environ["QT_API"] = "pyqt"
96 os.environ["QT_API"] = "pyqt"
97 elif gui == "qt5":
97 elif gui == "qt5":
98 try:
98 try:
99 import PyQt5 # noqa
99 import PyQt5 # noqa
100
100
101 os.environ["QT_API"] = "pyqt5"
101 os.environ["QT_API"] = "pyqt5"
102 except ImportError:
102 except ImportError:
103 try:
103 try:
104 import PySide2 # noqa
104 import PySide2 # noqa
105
105
106 os.environ["QT_API"] = "pyside2"
106 os.environ["QT_API"] = "pyside2"
107 except ImportError:
107 except ImportError:
108 os.environ["QT_API"] = "pyqt5"
108 os.environ["QT_API"] = "pyqt5"
109 elif gui == "qt6":
109 elif gui == "qt6":
110 try:
110 try:
111 import PyQt6 # noqa
111 import PyQt6 # noqa
112
112
113 os.environ["QT_API"] = "pyqt6"
113 os.environ["QT_API"] = "pyqt6"
114 except ImportError:
114 except ImportError:
115 try:
115 try:
116 import PySide6 # noqa
116 import PySide6 # noqa
117
117
118 os.environ["QT_API"] = "pyside6"
118 os.environ["QT_API"] = "pyside6"
119 except ImportError:
119 except ImportError:
120 os.environ["QT_API"] = "pyqt6"
120 os.environ["QT_API"] = "pyqt6"
121 elif gui == "qt":
121 elif gui == "qt":
122 # Don't set QT_API; let IPython logic choose the version.
122 # Don't set QT_API; let IPython logic choose the version.
123 if "QT_API" in os.environ.keys():
123 if "QT_API" in os.environ.keys():
124 del os.environ["QT_API"]
124 del os.environ["QT_API"]
125 else:
125 else:
126 raise ValueError(
126 raise ValueError(
127 f'Unrecognized Qt version: {gui}. Should be "qt4", "qt5", "qt6", or "qt".'
127 f'Unrecognized Qt version: {gui}. Should be "qt4", "qt5", "qt6", or "qt".'
128 )
128 )
129
129
130
130
131 def get_inputhook_name_and_func(gui):
131 def get_inputhook_name_and_func(gui):
132 if gui in registered:
132 if gui in registered:
133 return gui, registered[gui]
133 return gui, registered[gui]
134
134
135 if gui not in backends:
135 if gui not in backends:
136 raise UnknownBackend(gui)
136 raise UnknownBackend(gui)
137
137
138 if gui in aliases:
138 if gui in aliases:
139 return get_inputhook_name_and_func(aliases[gui])
139 return get_inputhook_name_and_func(aliases[gui])
140
140
141 gui_mod = gui
141 gui_mod = gui
142 if gui.startswith("qt"):
142 if gui.startswith("qt"):
143 set_qt_api(gui)
143 set_qt_api(gui)
144 gui_mod = "qt"
144 gui_mod = "qt"
145
145
146 mod = importlib.import_module("IPython.terminal.pt_inputhooks." + gui_mod)
146 mod = importlib.import_module("IPython.terminal.pt_inputhooks." + gui_mod)
147 return gui, mod.inputhook
147 return gui, mod.inputhook
@@ -1,48 +1,50 b''
1 import os
1 import os
2 import importlib
2 import importlib
3
3
4 import pytest
4 import pytest
5
5
6 from IPython.terminal.pt_inputhooks import set_qt_api, get_inputhook_name_and_func
6 from IPython.terminal.pt_inputhooks import set_qt_api, get_inputhook_name_and_func
7
7
8
8
9 guis_avail = []
9 guis_avail = []
10
10
11
11
12 def _get_qt_vers():
12 def _get_qt_vers():
13 """If any version of Qt is available, this will populate `guis_avail` with 'qt' and 'qtx'. Due
13 """If any version of Qt is available, this will populate `guis_avail` with 'qt' and 'qtx'. Due
14 to the import mechanism, we can't import multiple versions of Qt in one session."""
14 to the import mechanism, we can't import multiple versions of Qt in one session."""
15 for gui in ['qt', 'qt6', 'qt5', 'qt4']:
15 for gui in ["qt", "qt6", "qt5", "qt4"]:
16 print(f'Trying {gui}')
16 print(f"Trying {gui}")
17 try:
17 try:
18 set_qt_api(gui)
18 set_qt_api(gui)
19 importlib.import_module("IPython.terminal.pt_inputhooks.qt")
19 importlib.import_module("IPython.terminal.pt_inputhooks.qt")
20 guis_avail.append(gui)
20 guis_avail.append(gui)
21 if 'QT_API' in os.environ.keys():
21 if "QT_API" in os.environ.keys():
22 del os.environ['QT_API']
22 del os.environ["QT_API"]
23 except ImportError:
23 except ImportError:
24 pass # that version of Qt isn't available.
24 pass # that version of Qt isn't available.
25 except RuntimeError:
25 except RuntimeError:
26 pass # the version of IPython doesn't know what to do with this Qt version.
26 pass # the version of IPython doesn't know what to do with this Qt version.
27
27
28
28
29 _get_qt_vers()
29 _get_qt_vers()
30
30
31
31
32 @pytest.mark.skipif(len(guis_avail) == 0, reason='No viable version of PyQt or PySide installed.')
32 @pytest.mark.skipif(
33 len(guis_avail) == 0, reason="No viable version of PyQt or PySide installed."
34 )
33 def test_inputhook_qt():
35 def test_inputhook_qt():
34 gui = guis_avail[0]
36 gui = guis_avail[0]
35
37
36 # Choose a qt version and get the input hook function. This will import Qt...
38 # Choose a qt version and get the input hook function. This will import Qt...
37 get_inputhook_name_and_func(gui)
39 get_inputhook_name_and_func(gui)
38
40
39 # ...and now we're stuck with this version of Qt for good; can't switch.
41 # ...and now we're stuck with this version of Qt for good; can't switch.
40 for not_gui in ['qt6', 'qt5', 'qt4']:
42 for not_gui in ["qt6", "qt5", "qt4"]:
41 if not_gui not in guis_avail:
43 if not_gui not in guis_avail:
42 break
44 break
43
45
44 with pytest.raises(ImportError):
46 with pytest.raises(ImportError):
45 get_inputhook_name_and_func(not_gui)
47 get_inputhook_name_and_func(not_gui)
46
48
47 # A gui of 'qt' means "best available", or in this case, the last one that was used.
49 # A gui of 'qt' means "best available", or in this case, the last one that was used.
48 get_inputhook_name_and_func('qt')
50 get_inputhook_name_and_func("qt")
General Comments 0
You need to be logged in to leave comments. Login now