##// END OF EJS Templates
Merge pull request #13247 from Kojoley/tests-handle-no-matplotlib...
Matthias Bussonnier -
r27001:7b7ea0f5 merge
parent child Browse files
Show More
@@ -1,273 +1,274
1 """Tests for pylab tools module.
1 """Tests for pylab tools module.
2 """
2 """
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7
7
8 from binascii import a2b_base64
8 from binascii import a2b_base64
9 from io import BytesIO
9 from io import BytesIO
10
10
11 import matplotlib
11 import pytest
12
13 matplotlib = pytest.importorskip("matplotlib")
12 matplotlib.use('Agg')
14 matplotlib.use('Agg')
13 from matplotlib.figure import Figure
15 from matplotlib.figure import Figure
14
16
15 from matplotlib import pyplot as plt
17 from matplotlib import pyplot as plt
16 from matplotlib_inline import backend_inline
18 from matplotlib_inline import backend_inline
17 import numpy as np
19 import numpy as np
18 import pytest
19
20
20 from IPython.core.getipython import get_ipython
21 from IPython.core.getipython import get_ipython
21 from IPython.core.interactiveshell import InteractiveShell
22 from IPython.core.interactiveshell import InteractiveShell
22 from IPython.core.display import _PNG, _JPEG
23 from IPython.core.display import _PNG, _JPEG
23 from .. import pylabtools as pt
24 from .. import pylabtools as pt
24
25
25 from IPython.testing import decorators as dec
26 from IPython.testing import decorators as dec
26
27
27
28
28 def test_figure_to_svg():
29 def test_figure_to_svg():
29 # simple empty-figure test
30 # simple empty-figure test
30 fig = plt.figure()
31 fig = plt.figure()
31 assert pt.print_figure(fig, "svg") is None
32 assert pt.print_figure(fig, "svg") is None
32
33
33 plt.close('all')
34 plt.close('all')
34
35
35 # simple check for at least svg-looking output
36 # simple check for at least svg-looking output
36 fig = plt.figure()
37 fig = plt.figure()
37 ax = fig.add_subplot(1,1,1)
38 ax = fig.add_subplot(1,1,1)
38 ax.plot([1,2,3])
39 ax.plot([1,2,3])
39 plt.draw()
40 plt.draw()
40 svg = pt.print_figure(fig, "svg")[:100].lower()
41 svg = pt.print_figure(fig, "svg")[:100].lower()
41 assert "doctype svg" in svg
42 assert "doctype svg" in svg
42
43
43
44
44 def _check_pil_jpeg_bytes():
45 def _check_pil_jpeg_bytes():
45 """Skip if PIL can't write JPEGs to BytesIO objects"""
46 """Skip if PIL can't write JPEGs to BytesIO objects"""
46 # PIL's JPEG plugin can't write to BytesIO objects
47 # PIL's JPEG plugin can't write to BytesIO objects
47 # Pillow fixes this
48 # Pillow fixes this
48 from PIL import Image
49 from PIL import Image
49 buf = BytesIO()
50 buf = BytesIO()
50 img = Image.new("RGB", (4,4))
51 img = Image.new("RGB", (4,4))
51 try:
52 try:
52 img.save(buf, 'jpeg')
53 img.save(buf, 'jpeg')
53 except Exception as e:
54 except Exception as e:
54 ename = e.__class__.__name__
55 ename = e.__class__.__name__
55 raise pytest.skip("PIL can't write JPEG to BytesIO: %s: %s" % (ename, e)) from e
56 raise pytest.skip("PIL can't write JPEG to BytesIO: %s: %s" % (ename, e)) from e
56
57
57 @dec.skip_without("PIL.Image")
58 @dec.skip_without("PIL.Image")
58 def test_figure_to_jpeg():
59 def test_figure_to_jpeg():
59 _check_pil_jpeg_bytes()
60 _check_pil_jpeg_bytes()
60 # simple check for at least jpeg-looking output
61 # simple check for at least jpeg-looking output
61 fig = plt.figure()
62 fig = plt.figure()
62 ax = fig.add_subplot(1,1,1)
63 ax = fig.add_subplot(1,1,1)
63 ax.plot([1,2,3])
64 ax.plot([1,2,3])
64 plt.draw()
65 plt.draw()
65 jpeg = pt.print_figure(fig, 'jpeg', pil_kwargs={'optimize': 50})[:100].lower()
66 jpeg = pt.print_figure(fig, 'jpeg', pil_kwargs={'optimize': 50})[:100].lower()
66 assert jpeg.startswith(_JPEG)
67 assert jpeg.startswith(_JPEG)
67
68
68 def test_retina_figure():
69 def test_retina_figure():
69 # simple empty-figure test
70 # simple empty-figure test
70 fig = plt.figure()
71 fig = plt.figure()
71 assert pt.retina_figure(fig) == None
72 assert pt.retina_figure(fig) == None
72 plt.close('all')
73 plt.close('all')
73
74
74 fig = plt.figure()
75 fig = plt.figure()
75 ax = fig.add_subplot(1,1,1)
76 ax = fig.add_subplot(1,1,1)
76 ax.plot([1,2,3])
77 ax.plot([1,2,3])
77 plt.draw()
78 plt.draw()
78 png, md = pt.retina_figure(fig)
79 png, md = pt.retina_figure(fig)
79 assert png.startswith(_PNG)
80 assert png.startswith(_PNG)
80 assert "width" in md
81 assert "width" in md
81 assert "height" in md
82 assert "height" in md
82
83
83
84
84 _fmt_mime_map = {
85 _fmt_mime_map = {
85 'png': 'image/png',
86 'png': 'image/png',
86 'jpeg': 'image/jpeg',
87 'jpeg': 'image/jpeg',
87 'pdf': 'application/pdf',
88 'pdf': 'application/pdf',
88 'retina': 'image/png',
89 'retina': 'image/png',
89 'svg': 'image/svg+xml',
90 'svg': 'image/svg+xml',
90 }
91 }
91
92
92 def test_select_figure_formats_str():
93 def test_select_figure_formats_str():
93 ip = get_ipython()
94 ip = get_ipython()
94 for fmt, active_mime in _fmt_mime_map.items():
95 for fmt, active_mime in _fmt_mime_map.items():
95 pt.select_figure_formats(ip, fmt)
96 pt.select_figure_formats(ip, fmt)
96 for mime, f in ip.display_formatter.formatters.items():
97 for mime, f in ip.display_formatter.formatters.items():
97 if mime == active_mime:
98 if mime == active_mime:
98 assert Figure in f
99 assert Figure in f
99 else:
100 else:
100 assert Figure not in f
101 assert Figure not in f
101
102
102 def test_select_figure_formats_kwargs():
103 def test_select_figure_formats_kwargs():
103 ip = get_ipython()
104 ip = get_ipython()
104 kwargs = dict(quality=10, bbox_inches='tight')
105 kwargs = dict(quality=10, bbox_inches='tight')
105 pt.select_figure_formats(ip, 'png', **kwargs)
106 pt.select_figure_formats(ip, 'png', **kwargs)
106 formatter = ip.display_formatter.formatters['image/png']
107 formatter = ip.display_formatter.formatters['image/png']
107 f = formatter.lookup_by_type(Figure)
108 f = formatter.lookup_by_type(Figure)
108 cell = f.keywords
109 cell = f.keywords
109 expected = kwargs
110 expected = kwargs
110 expected["base64"] = True
111 expected["base64"] = True
111 expected["fmt"] = "png"
112 expected["fmt"] = "png"
112 assert cell == expected
113 assert cell == expected
113
114
114 # check that the formatter doesn't raise
115 # check that the formatter doesn't raise
115 fig = plt.figure()
116 fig = plt.figure()
116 ax = fig.add_subplot(1,1,1)
117 ax = fig.add_subplot(1,1,1)
117 ax.plot([1,2,3])
118 ax.plot([1,2,3])
118 plt.draw()
119 plt.draw()
119 formatter.enabled = True
120 formatter.enabled = True
120 png = formatter(fig)
121 png = formatter(fig)
121 assert isinstance(png, str)
122 assert isinstance(png, str)
122 png_bytes = a2b_base64(png)
123 png_bytes = a2b_base64(png)
123 assert png_bytes.startswith(_PNG)
124 assert png_bytes.startswith(_PNG)
124
125
125 def test_select_figure_formats_set():
126 def test_select_figure_formats_set():
126 ip = get_ipython()
127 ip = get_ipython()
127 for fmts in [
128 for fmts in [
128 {'png', 'svg'},
129 {'png', 'svg'},
129 ['png'],
130 ['png'],
130 ('jpeg', 'pdf', 'retina'),
131 ('jpeg', 'pdf', 'retina'),
131 {'svg'},
132 {'svg'},
132 ]:
133 ]:
133 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
134 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
134 pt.select_figure_formats(ip, fmts)
135 pt.select_figure_formats(ip, fmts)
135 for mime, f in ip.display_formatter.formatters.items():
136 for mime, f in ip.display_formatter.formatters.items():
136 if mime in active_mimes:
137 if mime in active_mimes:
137 assert Figure in f
138 assert Figure in f
138 else:
139 else:
139 assert Figure not in f
140 assert Figure not in f
140
141
141 def test_select_figure_formats_bad():
142 def test_select_figure_formats_bad():
142 ip = get_ipython()
143 ip = get_ipython()
143 with pytest.raises(ValueError):
144 with pytest.raises(ValueError):
144 pt.select_figure_formats(ip, 'foo')
145 pt.select_figure_formats(ip, 'foo')
145 with pytest.raises(ValueError):
146 with pytest.raises(ValueError):
146 pt.select_figure_formats(ip, {'png', 'foo'})
147 pt.select_figure_formats(ip, {'png', 'foo'})
147 with pytest.raises(ValueError):
148 with pytest.raises(ValueError):
148 pt.select_figure_formats(ip, ['retina', 'pdf', 'bar', 'bad'])
149 pt.select_figure_formats(ip, ['retina', 'pdf', 'bar', 'bad'])
149
150
150 def test_import_pylab():
151 def test_import_pylab():
151 ns = {}
152 ns = {}
152 pt.import_pylab(ns, import_all=False)
153 pt.import_pylab(ns, import_all=False)
153 assert "plt" in ns
154 assert "plt" in ns
154 assert ns["np"] == np
155 assert ns["np"] == np
155
156
156
157
157 from traitlets.config import Config
158 from traitlets.config import Config
158
159
159
160
160 class TestPylabSwitch(object):
161 class TestPylabSwitch(object):
161 class Shell(InteractiveShell):
162 class Shell(InteractiveShell):
162 def init_history(self):
163 def init_history(self):
163 """Sets up the command history, and starts regular autosaves."""
164 """Sets up the command history, and starts regular autosaves."""
164 self.config.HistoryManager.hist_file = ":memory:"
165 self.config.HistoryManager.hist_file = ":memory:"
165 super().init_history()
166 super().init_history()
166
167
167 def enable_gui(self, gui):
168 def enable_gui(self, gui):
168 pass
169 pass
169
170
170 def setup(self):
171 def setup(self):
171 import matplotlib
172 import matplotlib
172 def act_mpl(backend):
173 def act_mpl(backend):
173 matplotlib.rcParams['backend'] = backend
174 matplotlib.rcParams['backend'] = backend
174
175
175 # Save rcParams since they get modified
176 # Save rcParams since they get modified
176 self._saved_rcParams = matplotlib.rcParams
177 self._saved_rcParams = matplotlib.rcParams
177 self._saved_rcParamsOrig = matplotlib.rcParamsOrig
178 self._saved_rcParamsOrig = matplotlib.rcParamsOrig
178 matplotlib.rcParams = dict(backend='Qt4Agg')
179 matplotlib.rcParams = dict(backend='Qt4Agg')
179 matplotlib.rcParamsOrig = dict(backend='Qt4Agg')
180 matplotlib.rcParamsOrig = dict(backend='Qt4Agg')
180
181
181 # Mock out functions
182 # Mock out functions
182 self._save_am = pt.activate_matplotlib
183 self._save_am = pt.activate_matplotlib
183 pt.activate_matplotlib = act_mpl
184 pt.activate_matplotlib = act_mpl
184 self._save_ip = pt.import_pylab
185 self._save_ip = pt.import_pylab
185 pt.import_pylab = lambda *a,**kw:None
186 pt.import_pylab = lambda *a,**kw:None
186 self._save_cis = backend_inline.configure_inline_support
187 self._save_cis = backend_inline.configure_inline_support
187 backend_inline.configure_inline_support = lambda *a, **kw: None
188 backend_inline.configure_inline_support = lambda *a, **kw: None
188
189
189 def teardown(self):
190 def teardown(self):
190 pt.activate_matplotlib = self._save_am
191 pt.activate_matplotlib = self._save_am
191 pt.import_pylab = self._save_ip
192 pt.import_pylab = self._save_ip
192 backend_inline.configure_inline_support = self._save_cis
193 backend_inline.configure_inline_support = self._save_cis
193 import matplotlib
194 import matplotlib
194 matplotlib.rcParams = self._saved_rcParams
195 matplotlib.rcParams = self._saved_rcParams
195 matplotlib.rcParamsOrig = self._saved_rcParamsOrig
196 matplotlib.rcParamsOrig = self._saved_rcParamsOrig
196
197
197 def test_qt(self):
198 def test_qt(self):
198
199
199 s = self.Shell()
200 s = self.Shell()
200 gui, backend = s.enable_matplotlib(None)
201 gui, backend = s.enable_matplotlib(None)
201 assert gui == "qt"
202 assert gui == "qt"
202 assert s.pylab_gui_select == "qt"
203 assert s.pylab_gui_select == "qt"
203
204
204 gui, backend = s.enable_matplotlib("inline")
205 gui, backend = s.enable_matplotlib("inline")
205 assert gui == "inline"
206 assert gui == "inline"
206 assert s.pylab_gui_select == "qt"
207 assert s.pylab_gui_select == "qt"
207
208
208 gui, backend = s.enable_matplotlib("qt")
209 gui, backend = s.enable_matplotlib("qt")
209 assert gui == "qt"
210 assert gui == "qt"
210 assert s.pylab_gui_select == "qt"
211 assert s.pylab_gui_select == "qt"
211
212
212 gui, backend = s.enable_matplotlib("inline")
213 gui, backend = s.enable_matplotlib("inline")
213 assert gui == "inline"
214 assert gui == "inline"
214 assert s.pylab_gui_select == "qt"
215 assert s.pylab_gui_select == "qt"
215
216
216 gui, backend = s.enable_matplotlib()
217 gui, backend = s.enable_matplotlib()
217 assert gui == "qt"
218 assert gui == "qt"
218 assert s.pylab_gui_select == "qt"
219 assert s.pylab_gui_select == "qt"
219
220
220 def test_inline(self):
221 def test_inline(self):
221 s = self.Shell()
222 s = self.Shell()
222 gui, backend = s.enable_matplotlib("inline")
223 gui, backend = s.enable_matplotlib("inline")
223 assert gui == "inline"
224 assert gui == "inline"
224 assert s.pylab_gui_select == None
225 assert s.pylab_gui_select == None
225
226
226 gui, backend = s.enable_matplotlib("inline")
227 gui, backend = s.enable_matplotlib("inline")
227 assert gui == "inline"
228 assert gui == "inline"
228 assert s.pylab_gui_select == None
229 assert s.pylab_gui_select == None
229
230
230 gui, backend = s.enable_matplotlib("qt")
231 gui, backend = s.enable_matplotlib("qt")
231 assert gui == "qt"
232 assert gui == "qt"
232 assert s.pylab_gui_select == "qt"
233 assert s.pylab_gui_select == "qt"
233
234
234 def test_inline_twice(self):
235 def test_inline_twice(self):
235 "Using '%matplotlib inline' twice should not reset formatters"
236 "Using '%matplotlib inline' twice should not reset formatters"
236
237
237 ip = self.Shell()
238 ip = self.Shell()
238 gui, backend = ip.enable_matplotlib("inline")
239 gui, backend = ip.enable_matplotlib("inline")
239 assert gui == "inline"
240 assert gui == "inline"
240
241
241 fmts = {'png'}
242 fmts = {'png'}
242 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
243 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
243 pt.select_figure_formats(ip, fmts)
244 pt.select_figure_formats(ip, fmts)
244
245
245 gui, backend = ip.enable_matplotlib("inline")
246 gui, backend = ip.enable_matplotlib("inline")
246 assert gui == "inline"
247 assert gui == "inline"
247
248
248 for mime, f in ip.display_formatter.formatters.items():
249 for mime, f in ip.display_formatter.formatters.items():
249 if mime in active_mimes:
250 if mime in active_mimes:
250 assert Figure in f
251 assert Figure in f
251 else:
252 else:
252 assert Figure not in f
253 assert Figure not in f
253
254
254 def test_qt_gtk(self):
255 def test_qt_gtk(self):
255 s = self.Shell()
256 s = self.Shell()
256 gui, backend = s.enable_matplotlib("qt")
257 gui, backend = s.enable_matplotlib("qt")
257 assert gui == "qt"
258 assert gui == "qt"
258 assert s.pylab_gui_select == "qt"
259 assert s.pylab_gui_select == "qt"
259
260
260 gui, backend = s.enable_matplotlib("gtk")
261 gui, backend = s.enable_matplotlib("gtk")
261 assert gui == "qt"
262 assert gui == "qt"
262 assert s.pylab_gui_select == "qt"
263 assert s.pylab_gui_select == "qt"
263
264
264
265
265 def test_no_gui_backends():
266 def test_no_gui_backends():
266 for k in ['agg', 'svg', 'pdf', 'ps']:
267 for k in ['agg', 'svg', 'pdf', 'ps']:
267 assert k not in pt.backend2gui
268 assert k not in pt.backend2gui
268
269
269
270
270 def test_figure_no_canvas():
271 def test_figure_no_canvas():
271 fig = Figure()
272 fig = Figure()
272 fig.canvas = None
273 fig.canvas = None
273 pt.print_figure(fig)
274 pt.print_figure(fig)
General Comments 0
You need to be logged in to leave comments. Login now