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

Skip to content

Commit f0f351c

Browse files
committed
Fix backend detection in headless mode.
1 parent a9dc566 commit f0f351c

File tree

6 files changed

+36
-27
lines changed

6 files changed

+36
-27
lines changed

lib/matplotlib/backends/__init__.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import importlib
77
import logging
8+
import os
89
import sys
910
import traceback
1011

@@ -17,12 +18,14 @@
1718

1819

1920
def _get_current_event_loop():
20-
"""Return the currently running event loop if any, or None.
21+
"""Return the currently running event loop if any, or "headless", or None.
22+
23+
"headless" indicates that no event loop can be started.
2124
2225
Returns
2326
-------
2427
Optional[str]
25-
A value in {"qt5", "qt4", "gtk3", "gtk2", "tk", None}
28+
A value in {"qt5", "qt4", "gtk3", "gtk2", "tk", "headless", None}
2629
"""
2730
# FIXME Add detection of OSX event loop.
2831
QtWidgets = sys.modules.get("PyQt5.QtWidgets")
@@ -43,6 +46,8 @@ def _get_current_event_loop():
4346
and frame.f_code.co_name == "mainloop"
4447
for frame in sys._current_frames().values()):
4548
return "tk"
49+
if sys.platform.startswith("linux") and not os.environ.get("DISPLAY"):
50+
return "headless"
4651

4752

4853
def pylab_setup(name=None):
@@ -85,9 +90,10 @@ def pylab_setup(name=None):
8590
if isinstance(name, list):
8691
for n in name:
8792
try:
93+
_log.info("Trying to load backend %s.", n)
8894
return pylab_setup(n)
89-
except ImportError:
90-
pass
95+
except ImportError as exc:
96+
_log.info("Loading backend %s failed: %s", n, exc)
9197
else:
9298
raise ValueError("No suitable backend among {}".format(name))
9399

@@ -96,7 +102,7 @@ def pylab_setup(name=None):
96102

97103
backend_mod = importlib.import_module(backend_name)
98104
Backend = type(str("Backend"), (_Backend,), vars(backend_mod))
99-
_log.info('backend %s version %s', name, Backend.backend_version)
105+
_log.info("Loaded backend %s version %s.", name, Backend.backend_version)
100106

101107
required_event_loop = Backend.required_event_loop
102108
current_event_loop = _get_current_event_loop()

lib/matplotlib/backends/backend_gtk.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
import gobject
1818
import gtk; gdk = gtk.gdk
1919
import pango
20-
except ImportError:
20+
except (ImportError, AttributeError):
21+
# AttributeError occurs when getting gtk.gdk if gi is already imported.
2122
raise ImportError("Gtk* backend requires pygtk to be installed.")
2223

2324
pygtk_version_required = (2,4,0)

lib/matplotlib/backends/backend_gtk3.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,18 @@
5050
# see http://groups.google.com/groups?q=screen+dpi+x11&hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=7077.26e81ad5%40swift.cs.tcd.ie&rnum=5 for some info about screen dpi
5151
PIXELS_PER_INCH = 96
5252

53-
cursord = {
54-
cursors.MOVE : Gdk.Cursor.new(Gdk.CursorType.FLEUR),
55-
cursors.HAND : Gdk.Cursor.new(Gdk.CursorType.HAND2),
56-
cursors.POINTER : Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR),
57-
cursors.SELECT_REGION : Gdk.Cursor.new(Gdk.CursorType.TCROSS),
58-
cursors.WAIT : Gdk.Cursor.new(Gdk.CursorType.WATCH),
59-
}
53+
try:
54+
cursord = {
55+
cursors.MOVE : Gdk.Cursor.new(Gdk.CursorType.FLEUR),
56+
cursors.HAND : Gdk.Cursor.new(Gdk.CursorType.HAND2),
57+
cursors.POINTER : Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR),
58+
cursors.SELECT_REGION : Gdk.Cursor.new(Gdk.CursorType.TCROSS),
59+
cursors.WAIT : Gdk.Cursor.new(Gdk.CursorType.WATCH),
60+
}
61+
except TypeError as exc:
62+
# Happens when running headless. Convert to ImportError to cooperate with
63+
# backend switching.
64+
raise ImportError(exc)
6065

6166

6267
class TimerGTK3(TimerBase):

lib/matplotlib/backends/backend_qt5.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import functools
66
import os
7-
import re
87
import signal
98
import sys
109
from six import unichr
@@ -116,10 +115,8 @@ def _create_qApp():
116115
is_x11_build = False
117116
else:
118117
is_x11_build = hasattr(QtGui, "QX11Info")
119-
if is_x11_build:
120-
display = os.environ.get('DISPLAY')
121-
if display is None or not re.search(r':\d', display):
122-
raise RuntimeError('Invalid DISPLAY variable')
118+
if is_x11_build and not os.environ.get("DISPLAY"):
119+
raise RuntimeError("No DISPLAY variable")
123120

124121
qApp = QtWidgets.QApplication([b"matplotlib"])
125122
qApp.lastWindowClosed.connect(qApp.quit)

lib/matplotlib/backends/qt_compat.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,17 @@
112112
QT_API = QT_API_PYSIDE2
113113
else:
114114
QT_API = QT_API_PYSIDE
115-
cond = ("Could not import sip; falling back on PySide\n"
116-
"in place of PyQt4 or PyQt5.\n")
115+
cond = ("Could not import sip; falling back on PySide in place of "
116+
"PyQt4 or PyQt5.")
117117
_log.info(cond)
118118

119119
if _sip_imported:
120120
if QT_API == QT_API_PYQTv2:
121121
if QT_API_ENV == 'pyqt':
122122
cond = ("Found 'QT_API=pyqt' environment variable. "
123-
"Setting PyQt4 API accordingly.\n")
123+
"Setting PyQt4 API accordingly. ")
124124
else:
125-
cond = "PyQt API v2 specified."
125+
cond = "PyQt API v2 specified. "
126126
try:
127127
sip.setapi('QString', 2)
128128
except:
@@ -201,7 +201,7 @@ def _getSaveFileName(*args, **kwargs):
201201
from PySide import QtCore, QtGui, __version__, __version_info__
202202
except ImportError:
203203
raise ImportError(
204-
"Matplotlib qt-based backends require an external PyQt4, PyQt5,\n"
204+
"Matplotlib qt-based backends require an external PyQt4, PyQt5, "
205205
"PySide or PySide2 package to be installed, but it was not found.")
206206

207207
if __version_info__ < (1, 0, 3):

src/_macosx.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3056,15 +3056,15 @@ static bool verify_framework(void)
30563056
&& GetCurrentProcess(&psn)==noErr
30573057
&& SetFrontProcess(&psn)==noErr) return true;
30583058
#endif
3059-
PyErr_SetString(PyExc_RuntimeError,
3059+
PyErr_SetString(PyExc_ImportError,
30603060
"Python is not installed as a framework. The Mac OS X backend will "
30613061
"not be able to function correctly if Python is not installed as a "
30623062
"framework. See the Python documentation for more information on "
30633063
"installing Python as a framework on Mac OS X. Please either reinstall "
30643064
"Python as a framework, or try one of the other backends. If you are "
3065-
"using (Ana)Conda please install python.app and replace the use of 'python' "
3066-
"with 'pythonw'. See 'Working with Matplotlib on OSX' "
3067-
"in the Matplotlib FAQ for more information.");
3065+
"using (Ana)Conda please install python.app and replace the use of "
3066+
"'python' with 'pythonw'. See 'Working with Matplotlib on OSX' in the "
3067+
"Matplotlib FAQ for more information.");
30683068
return false;
30693069
}
30703070

0 commit comments

Comments
 (0)