Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 93ebee6

Browse files
committed
Add private API retrieving the current event loop and backend GUI info.
Work towards implementation of backend switching. Note that the API is kept private for now as the lack of extensibility is a bit unsatisfying; perhaps we'll figure out a better way to do it if other custom implementers (e.g., code editors?) get interested in looking into it. The `required_event_loop` variable could be made private for now, or not...
1 parent a0994d3 commit 93ebee6

File tree

9 files changed

+78
-1
lines changed

9 files changed

+78
-1
lines changed

doc/api/next_api_changes/2018-06-27-AL.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,10 @@ Changes to backend loading
44
Failure to load backend modules (``macosx`` on non-framework builds and
55
``gtk3`` when running headless) now raises `ImportError` (instead of
66
`RuntimeError` and `TypeError`, respectively.
7+
8+
Third-party backends that integrate with an interactive framework are now
9+
encouraged to define the ``required_interactive_framework`` global value to one
10+
of the following values: "qt5", "qt4", "gtk3", "wx", "tk", or "macosx". This
11+
information will be used to determine whether it is possible to switch from a
12+
backend to another (specifically, whether they use the same interactive
13+
framework).

lib/matplotlib/backends/__init__.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import importlib
22
import logging
3+
import os
4+
import sys
35
import traceback
46

57
import matplotlib
@@ -14,6 +16,54 @@
1416
if not line.startswith(' File "<frozen importlib._bootstrap'))
1517

1618

19+
def _get_running_interactive_framework():
20+
"""
21+
Return the interactive framework whose event loop is currently running, if
22+
any, or "headless" if no event loop can be started, or None.
23+
24+
Returns
25+
-------
26+
Optional[str]
27+
One of the following values: "qt5", "qt4", "gtk3", "wx", "tk",
28+
"macosx", "headless", ``None``.
29+
"""
30+
QtWidgets = (sys.modules.get("PyQt5.QtWidgets")
31+
or sys.modules.get("PySide2.QtWidgets"))
32+
if QtWidgets and QtWidgets.QApplication.instance():
33+
return "qt5"
34+
QtGui = (sys.modules.get("PyQt4.QtGui")
35+
or sys.modules.get("PySide.QtGui"))
36+
if QtGui and QtGui.QApplication.instance():
37+
return "qt4"
38+
Gtk = (sys.modules.get("gi.repository.Gtk")
39+
or sys.modules.get("pgi.repository.Gtk"))
40+
if Gtk and Gtk.main_level():
41+
return "gtk3"
42+
wx = sys.modules.get("wx")
43+
if wx and wx.GetApp():
44+
return "wx"
45+
tkinter = sys.modules.get("tkinter")
46+
if tkinter:
47+
for frame in sys._current_frames().values():
48+
while frame:
49+
if frame.f_code == tkinter.mainloop.__code__:
50+
return "tk"
51+
frame = frame.f_back
52+
try:
53+
from matplotlib.backends import _macosx
54+
except ImportError:
55+
pass
56+
else:
57+
# Note that the NSApp event loop is also running when a non-native
58+
# toolkit (e.g. Qt5) is active, but in that case we want to report the
59+
# other toolkit; thus, this check comes after the other toolkits.
60+
if _macosx.event_loop_is_running():
61+
return "macosx"
62+
if sys.platform.startswith("linux") and not os.environ.get("DISPLAY"):
63+
return "headless"
64+
return None
65+
66+
1767
def pylab_setup(name=None):
1868
"""
1969
Return new_figure_manager, draw_if_interactive and show for pyplot.

lib/matplotlib/backends/_backend_tk.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,7 @@ def trigger(self, *args):
994994

995995
@_Backend.export
996996
class _BackendTk(_Backend):
997+
required_interactive_framework = "tk"
997998
FigureManager = FigureManagerTk
998999

9991000
@classmethod

lib/matplotlib/backends/backend_gtk3.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ def error_msg_gtk(msg, parent=None):
976976

977977
@_Backend.export
978978
class _BackendGTK3(_Backend):
979+
required_interactive_framework = "gtk3"
979980
FigureCanvas = FigureCanvasGTK3
980981
FigureManager = FigureManagerGTK3
981982

lib/matplotlib/backends/backend_macosx.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ def set_message(self, message):
185185

186186
@_Backend.export
187187
class _BackendMac(_Backend):
188+
required_interactive_framework = "macosx"
188189
FigureCanvas = FigureCanvasMac
189190
FigureManager = FigureManagerMac
190191

lib/matplotlib/backends/backend_qt4.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77

88
@_BackendQT5.export
99
class _BackendQT4(_BackendQT5):
10-
pass
10+
required_interactive_framework = "qt4"

lib/matplotlib/backends/backend_qt5.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,7 @@ def exception_handler(type, value, tb):
11091109

11101110
@_Backend.export
11111111
class _BackendQT5(_Backend):
1112+
required_interactive_framework = "qt5"
11121113
FigureCanvas = FigureCanvasQT
11131114
FigureManager = FigureManagerQT
11141115

lib/matplotlib/backends/backend_wx.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1930,6 +1930,7 @@ def OnPrintPage(self, page):
19301930

19311931
@_Backend.export
19321932
class _BackendWx(_Backend):
1933+
required_interactive_framework = "wx"
19331934
FigureCanvas = FigureCanvasWx
19341935
FigureManager = FigureManagerWx
19351936
_frame_class = FigureFrameWx

src/_macosx.m

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2789,6 +2789,16 @@ - (int)index
27892789
}
27902790
@end
27912791

2792+
static PyObject*
2793+
event_loop_is_running(PyObject* self)
2794+
{
2795+
if ([NSApp isRunning]) {
2796+
Py_RETURN_TRUE;
2797+
} else {
2798+
Py_RETURN_FALSE;
2799+
}
2800+
}
2801+
27922802
static PyObject*
27932803
show(PyObject* self)
27942804
{
@@ -3038,6 +3048,11 @@ static bool verify_framework(void)
30383048
}
30393049

30403050
static struct PyMethodDef methods[] = {
3051+
{"event_loop_is_running",
3052+
(PyCFunction)event_loop_is_running,
3053+
METH_NOARGS,
3054+
"Return whether the NSApp main event loop is currently running."
3055+
},
30413056
{"show",
30423057
(PyCFunction)show,
30433058
METH_NOARGS,

0 commit comments

Comments
 (0)