##// END OF EJS Templates
Isolate tests so state doesn't leak to other tests
Ian Thomas -
Show More
@@ -1,376 +1,375 b''
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 pytest
11 import pytest
12
12
13 matplotlib = pytest.importorskip("matplotlib")
13 matplotlib = pytest.importorskip("matplotlib")
14 matplotlib.use('Agg')
14 matplotlib.use('Agg')
15 from matplotlib.figure import Figure
15 from matplotlib.figure import Figure
16
16
17 from matplotlib import pyplot as plt
17 from matplotlib import pyplot as plt
18 from matplotlib_inline import backend_inline
18 from matplotlib_inline import backend_inline
19 import numpy as np
19 import numpy as np
20
20
21 from IPython.core.getipython import get_ipython
21 from IPython.core.getipython import get_ipython
22 from IPython.core.interactiveshell import InteractiveShell
22 from IPython.core.interactiveshell import InteractiveShell
23 from IPython.core.display import _PNG, _JPEG
23 from IPython.core.display import _PNG, _JPEG
24 from .. import pylabtools as pt
24 from .. import pylabtools as pt
25
25
26 from IPython.testing import decorators as dec
26 from IPython.testing import decorators as dec
27
27
28
28
29 def test_figure_to_svg():
29 def test_figure_to_svg():
30 # simple empty-figure test
30 # simple empty-figure test
31 fig = plt.figure()
31 fig = plt.figure()
32 assert pt.print_figure(fig, "svg") is None
32 assert pt.print_figure(fig, "svg") is None
33
33
34 plt.close('all')
34 plt.close('all')
35
35
36 # simple check for at least svg-looking output
36 # simple check for at least svg-looking output
37 fig = plt.figure()
37 fig = plt.figure()
38 ax = fig.add_subplot(1,1,1)
38 ax = fig.add_subplot(1,1,1)
39 ax.plot([1,2,3])
39 ax.plot([1,2,3])
40 plt.draw()
40 plt.draw()
41 svg = pt.print_figure(fig, "svg")[:100].lower()
41 svg = pt.print_figure(fig, "svg")[:100].lower()
42 assert "doctype svg" in svg
42 assert "doctype svg" in svg
43
43
44
44
45 def _check_pil_jpeg_bytes():
45 def _check_pil_jpeg_bytes():
46 """Skip if PIL can't write JPEGs to BytesIO objects"""
46 """Skip if PIL can't write JPEGs to BytesIO objects"""
47 # PIL's JPEG plugin can't write to BytesIO objects
47 # PIL's JPEG plugin can't write to BytesIO objects
48 # Pillow fixes this
48 # Pillow fixes this
49 from PIL import Image
49 from PIL import Image
50 buf = BytesIO()
50 buf = BytesIO()
51 img = Image.new("RGB", (4,4))
51 img = Image.new("RGB", (4,4))
52 try:
52 try:
53 img.save(buf, 'jpeg')
53 img.save(buf, 'jpeg')
54 except Exception as e:
54 except Exception as e:
55 ename = e.__class__.__name__
55 ename = e.__class__.__name__
56 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
57
57
58 @dec.skip_without("PIL.Image")
58 @dec.skip_without("PIL.Image")
59 def test_figure_to_jpeg():
59 def test_figure_to_jpeg():
60 _check_pil_jpeg_bytes()
60 _check_pil_jpeg_bytes()
61 # simple check for at least jpeg-looking output
61 # simple check for at least jpeg-looking output
62 fig = plt.figure()
62 fig = plt.figure()
63 ax = fig.add_subplot(1,1,1)
63 ax = fig.add_subplot(1,1,1)
64 ax.plot([1,2,3])
64 ax.plot([1,2,3])
65 plt.draw()
65 plt.draw()
66 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()
67 assert jpeg.startswith(_JPEG)
67 assert jpeg.startswith(_JPEG)
68
68
69 def test_retina_figure():
69 def test_retina_figure():
70 # simple empty-figure test
70 # simple empty-figure test
71 fig = plt.figure()
71 fig = plt.figure()
72 assert pt.retina_figure(fig) == None
72 assert pt.retina_figure(fig) == None
73 plt.close('all')
73 plt.close('all')
74
74
75 fig = plt.figure()
75 fig = plt.figure()
76 ax = fig.add_subplot(1,1,1)
76 ax = fig.add_subplot(1,1,1)
77 ax.plot([1,2,3])
77 ax.plot([1,2,3])
78 plt.draw()
78 plt.draw()
79 png, md = pt.retina_figure(fig)
79 png, md = pt.retina_figure(fig)
80 assert png.startswith(_PNG)
80 assert png.startswith(_PNG)
81 assert "width" in md
81 assert "width" in md
82 assert "height" in md
82 assert "height" in md
83
83
84
84
85 _fmt_mime_map = {
85 _fmt_mime_map = {
86 'png': 'image/png',
86 'png': 'image/png',
87 'jpeg': 'image/jpeg',
87 'jpeg': 'image/jpeg',
88 'pdf': 'application/pdf',
88 'pdf': 'application/pdf',
89 'retina': 'image/png',
89 'retina': 'image/png',
90 'svg': 'image/svg+xml',
90 'svg': 'image/svg+xml',
91 }
91 }
92
92
93 def test_select_figure_formats_str():
93 def test_select_figure_formats_str():
94 ip = get_ipython()
94 ip = get_ipython()
95 for fmt, active_mime in _fmt_mime_map.items():
95 for fmt, active_mime in _fmt_mime_map.items():
96 pt.select_figure_formats(ip, fmt)
96 pt.select_figure_formats(ip, fmt)
97 for mime, f in ip.display_formatter.formatters.items():
97 for mime, f in ip.display_formatter.formatters.items():
98 if mime == active_mime:
98 if mime == active_mime:
99 assert Figure in f
99 assert Figure in f
100 else:
100 else:
101 assert Figure not in f
101 assert Figure not in f
102
102
103 def test_select_figure_formats_kwargs():
103 def test_select_figure_formats_kwargs():
104 ip = get_ipython()
104 ip = get_ipython()
105 kwargs = dict(bbox_inches="tight")
105 kwargs = dict(bbox_inches="tight")
106 pt.select_figure_formats(ip, "png", **kwargs)
106 pt.select_figure_formats(ip, "png", **kwargs)
107 formatter = ip.display_formatter.formatters["image/png"]
107 formatter = ip.display_formatter.formatters["image/png"]
108 f = formatter.lookup_by_type(Figure)
108 f = formatter.lookup_by_type(Figure)
109 cell = f.keywords
109 cell = f.keywords
110 expected = kwargs
110 expected = kwargs
111 expected["base64"] = True
111 expected["base64"] = True
112 expected["fmt"] = "png"
112 expected["fmt"] = "png"
113 assert cell == expected
113 assert cell == expected
114
114
115 # check that the formatter doesn't raise
115 # check that the formatter doesn't raise
116 fig = plt.figure()
116 fig = plt.figure()
117 ax = fig.add_subplot(1,1,1)
117 ax = fig.add_subplot(1,1,1)
118 ax.plot([1,2,3])
118 ax.plot([1,2,3])
119 plt.draw()
119 plt.draw()
120 formatter.enabled = True
120 formatter.enabled = True
121 png = formatter(fig)
121 png = formatter(fig)
122 assert isinstance(png, str)
122 assert isinstance(png, str)
123 png_bytes = a2b_base64(png)
123 png_bytes = a2b_base64(png)
124 assert png_bytes.startswith(_PNG)
124 assert png_bytes.startswith(_PNG)
125
125
126 def test_select_figure_formats_set():
126 def test_select_figure_formats_set():
127 ip = get_ipython()
127 ip = get_ipython()
128 for fmts in [
128 for fmts in [
129 {'png', 'svg'},
129 {'png', 'svg'},
130 ['png'],
130 ['png'],
131 ('jpeg', 'pdf', 'retina'),
131 ('jpeg', 'pdf', 'retina'),
132 {'svg'},
132 {'svg'},
133 ]:
133 ]:
134 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
134 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
135 pt.select_figure_formats(ip, fmts)
135 pt.select_figure_formats(ip, fmts)
136 for mime, f in ip.display_formatter.formatters.items():
136 for mime, f in ip.display_formatter.formatters.items():
137 if mime in active_mimes:
137 if mime in active_mimes:
138 assert Figure in f
138 assert Figure in f
139 else:
139 else:
140 assert Figure not in f
140 assert Figure not in f
141
141
142 def test_select_figure_formats_bad():
142 def test_select_figure_formats_bad():
143 ip = get_ipython()
143 ip = get_ipython()
144 with pytest.raises(ValueError):
144 with pytest.raises(ValueError):
145 pt.select_figure_formats(ip, 'foo')
145 pt.select_figure_formats(ip, 'foo')
146 with pytest.raises(ValueError):
146 with pytest.raises(ValueError):
147 pt.select_figure_formats(ip, {'png', 'foo'})
147 pt.select_figure_formats(ip, {'png', 'foo'})
148 with pytest.raises(ValueError):
148 with pytest.raises(ValueError):
149 pt.select_figure_formats(ip, ['retina', 'pdf', 'bar', 'bad'])
149 pt.select_figure_formats(ip, ['retina', 'pdf', 'bar', 'bad'])
150
150
151 def test_import_pylab():
151 def test_import_pylab():
152 ns = {}
152 ns = {}
153 pt.import_pylab(ns, import_all=False)
153 pt.import_pylab(ns, import_all=False)
154 assert "plt" in ns
154 assert "plt" in ns
155 assert ns["np"] == np
155 assert ns["np"] == np
156
156
157
157
158 class TestPylabSwitch(object):
158 class TestPylabSwitch(object):
159 class Shell(InteractiveShell):
159 class Shell(InteractiveShell):
160 def init_history(self):
160 def init_history(self):
161 """Sets up the command history, and starts regular autosaves."""
161 """Sets up the command history, and starts regular autosaves."""
162 self.config.HistoryManager.hist_file = ":memory:"
162 self.config.HistoryManager.hist_file = ":memory:"
163 super().init_history()
163 super().init_history()
164
164
165 def enable_gui(self, gui):
165 def enable_gui(self, gui):
166 pass
166 pass
167
167
168 def setup_method(self):
168 def setup_method(self):
169 import matplotlib
169 import matplotlib
170 def act_mpl(backend):
170 def act_mpl(backend):
171 matplotlib.rcParams['backend'] = backend
171 matplotlib.rcParams['backend'] = backend
172
172
173 # Save rcParams since they get modified
173 # Save rcParams since they get modified
174 self._saved_rcParams = matplotlib.rcParams
174 self._saved_rcParams = matplotlib.rcParams
175 self._saved_rcParamsOrig = matplotlib.rcParamsOrig
175 self._saved_rcParamsOrig = matplotlib.rcParamsOrig
176 matplotlib.rcParams = dict(backend="QtAgg")
176 matplotlib.rcParams = dict(backend="QtAgg")
177 matplotlib.rcParamsOrig = dict(backend="QtAgg")
177 matplotlib.rcParamsOrig = dict(backend="QtAgg")
178
178
179 # Mock out functions
179 # Mock out functions
180 self._save_am = pt.activate_matplotlib
180 self._save_am = pt.activate_matplotlib
181 pt.activate_matplotlib = act_mpl
181 pt.activate_matplotlib = act_mpl
182 self._save_ip = pt.import_pylab
182 self._save_ip = pt.import_pylab
183 pt.import_pylab = lambda *a,**kw:None
183 pt.import_pylab = lambda *a,**kw:None
184 self._save_cis = backend_inline.configure_inline_support
184 self._save_cis = backend_inline.configure_inline_support
185 backend_inline.configure_inline_support = lambda *a, **kw: None
185 backend_inline.configure_inline_support = lambda *a, **kw: None
186
186
187 def teardown_method(self):
187 def teardown_method(self):
188 pt.activate_matplotlib = self._save_am
188 pt.activate_matplotlib = self._save_am
189 pt.import_pylab = self._save_ip
189 pt.import_pylab = self._save_ip
190 backend_inline.configure_inline_support = self._save_cis
190 backend_inline.configure_inline_support = self._save_cis
191 import matplotlib
191 import matplotlib
192 matplotlib.rcParams = self._saved_rcParams
192 matplotlib.rcParams = self._saved_rcParams
193 matplotlib.rcParamsOrig = self._saved_rcParamsOrig
193 matplotlib.rcParamsOrig = self._saved_rcParamsOrig
194
194
195 def test_qt(self):
195 def test_qt(self):
196 s = self.Shell()
196 s = self.Shell()
197 gui, backend = s.enable_matplotlib(None)
197 gui, backend = s.enable_matplotlib(None)
198 assert gui == "qt"
198 assert gui == "qt"
199 assert s.pylab_gui_select == "qt"
199 assert s.pylab_gui_select == "qt"
200
200
201 gui, backend = s.enable_matplotlib("inline")
201 gui, backend = s.enable_matplotlib("inline")
202 assert gui is None
202 assert gui is None
203 assert s.pylab_gui_select == "qt"
203 assert s.pylab_gui_select == "qt"
204
204
205 gui, backend = s.enable_matplotlib("qt")
205 gui, backend = s.enable_matplotlib("qt")
206 assert gui == "qt"
206 assert gui == "qt"
207 assert s.pylab_gui_select == "qt"
207 assert s.pylab_gui_select == "qt"
208
208
209 gui, backend = s.enable_matplotlib("inline")
209 gui, backend = s.enable_matplotlib("inline")
210 assert gui is None
210 assert gui is None
211 assert s.pylab_gui_select == "qt"
211 assert s.pylab_gui_select == "qt"
212
212
213 gui, backend = s.enable_matplotlib()
213 gui, backend = s.enable_matplotlib()
214 assert gui == "qt"
214 assert gui == "qt"
215 assert s.pylab_gui_select == "qt"
215 assert s.pylab_gui_select == "qt"
216
216
217 def test_inline(self):
217 def test_inline(self):
218 s = self.Shell()
218 s = self.Shell()
219 gui, backend = s.enable_matplotlib("inline")
219 gui, backend = s.enable_matplotlib("inline")
220 assert gui is None
220 assert gui is None
221 assert s.pylab_gui_select == None
221 assert s.pylab_gui_select == None
222
222
223 gui, backend = s.enable_matplotlib("inline")
223 gui, backend = s.enable_matplotlib("inline")
224 assert gui is None
224 assert gui is None
225 assert s.pylab_gui_select == None
225 assert s.pylab_gui_select == None
226
226
227 gui, backend = s.enable_matplotlib("qt")
227 gui, backend = s.enable_matplotlib("qt")
228 assert gui == "qt"
228 assert gui == "qt"
229 assert s.pylab_gui_select == "qt"
229 assert s.pylab_gui_select == "qt"
230
230
231 def test_inline_twice(self):
231 def test_inline_twice(self):
232 "Using '%matplotlib inline' twice should not reset formatters"
232 "Using '%matplotlib inline' twice should not reset formatters"
233
233
234 ip = self.Shell()
234 ip = self.Shell()
235 gui, backend = ip.enable_matplotlib("inline")
235 gui, backend = ip.enable_matplotlib("inline")
236 assert gui is None
236 assert gui is None
237
237
238 fmts = {'png'}
238 fmts = {'png'}
239 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
239 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
240 pt.select_figure_formats(ip, fmts)
240 pt.select_figure_formats(ip, fmts)
241
241
242 gui, backend = ip.enable_matplotlib("inline")
242 gui, backend = ip.enable_matplotlib("inline")
243 assert gui is None
243 assert gui is None
244
244
245 for mime, f in ip.display_formatter.formatters.items():
245 for mime, f in ip.display_formatter.formatters.items():
246 if mime in active_mimes:
246 if mime in active_mimes:
247 assert Figure in f
247 assert Figure in f
248 else:
248 else:
249 assert Figure not in f
249 assert Figure not in f
250
250
251 def test_qt_gtk(self):
251 def test_qt_gtk(self):
252 s = self.Shell()
252 s = self.Shell()
253 gui, backend = s.enable_matplotlib("qt")
253 gui, backend = s.enable_matplotlib("qt")
254 assert gui == "qt"
254 assert gui == "qt"
255 assert s.pylab_gui_select == "qt"
255 assert s.pylab_gui_select == "qt"
256
256
257 gui, backend = s.enable_matplotlib("gtk3")
257 gui, backend = s.enable_matplotlib("gtk3")
258 assert gui == "qt"
258 assert gui == "qt"
259 assert s.pylab_gui_select == "qt"
259 assert s.pylab_gui_select == "qt"
260
260
261 @dec.skipif(not pt._matplotlib_manages_backends())
262 def test_backend_module_name_case_sensitive(self):
263 # Matplotlib backend names are case insensitive unless explicitly specified using
264 # "module://some_module.some_name" syntax which are case sensitive for mpl >= 3.9.1
265 all_lowercase = "module://matplotlib_inline.backend_inline"
266 some_uppercase = "module://matplotlib_inline.Backend_inline"
267 mpl3_9_1 = matplotlib.__version_info__ >= (3, 9, 1)
268
269 s = self.Shell()
270 s.enable_matplotlib(all_lowercase)
271 if mpl3_9_1:
272 with pytest.raises(RuntimeError):
273 s.enable_matplotlib(some_uppercase)
274 else:
275 s.enable_matplotlib(some_uppercase)
276
277 s.run_line_magic("matplotlib", all_lowercase)
278 if mpl3_9_1:
279 with pytest.raises(RuntimeError):
280 s.run_line_magic("matplotlib", some_uppercase)
281 else:
282 s.run_line_magic("matplotlib", some_uppercase)
283
261
284
262 def test_no_gui_backends():
285 def test_no_gui_backends():
263 for k in ['agg', 'svg', 'pdf', 'ps']:
286 for k in ['agg', 'svg', 'pdf', 'ps']:
264 assert k not in pt.backend2gui
287 assert k not in pt.backend2gui
265
288
266
289
267 def test_figure_no_canvas():
290 def test_figure_no_canvas():
268 fig = Figure()
291 fig = Figure()
269 fig.canvas = None
292 fig.canvas = None
270 pt.print_figure(fig)
293 pt.print_figure(fig)
271
294
272
295
273 @pytest.mark.parametrize(
296 @pytest.mark.parametrize(
274 "name, expected_gui, expected_backend",
297 "name, expected_gui, expected_backend",
275 [
298 [
276 # name is gui
299 # name is gui
277 ("gtk3", "gtk3", "gtk3agg"),
300 ("gtk3", "gtk3", "gtk3agg"),
278 ("gtk4", "gtk4", "gtk4agg"),
301 ("gtk4", "gtk4", "gtk4agg"),
279 ("headless", None, "agg"),
302 ("headless", None, "agg"),
280 ("osx", "osx", "macosx"),
303 ("osx", "osx", "macosx"),
281 ("qt", "qt", "qtagg"),
304 ("qt", "qt", "qtagg"),
282 ("qt5", "qt5", "qt5agg"),
305 ("qt5", "qt5", "qt5agg"),
283 ("qt6", "qt6", "qtagg"),
306 ("qt6", "qt6", "qtagg"),
284 ("tk", "tk", "tkagg"),
307 ("tk", "tk", "tkagg"),
285 ("wx", "wx", "wxagg"),
308 ("wx", "wx", "wxagg"),
286 # name is backend
309 # name is backend
287 ("agg", None, "agg"),
310 ("agg", None, "agg"),
288 ("cairo", None, "cairo"),
311 ("cairo", None, "cairo"),
289 ("pdf", None, "pdf"),
312 ("pdf", None, "pdf"),
290 ("ps", None, "ps"),
313 ("ps", None, "ps"),
291 ("svg", None, "svg"),
314 ("svg", None, "svg"),
292 ("template", None, "template"),
315 ("template", None, "template"),
293 ("gtk3agg", "gtk3", "gtk3agg"),
316 ("gtk3agg", "gtk3", "gtk3agg"),
294 ("gtk3cairo", "gtk3", "gtk3cairo"),
317 ("gtk3cairo", "gtk3", "gtk3cairo"),
295 ("gtk4agg", "gtk4", "gtk4agg"),
318 ("gtk4agg", "gtk4", "gtk4agg"),
296 ("gtk4cairo", "gtk4", "gtk4cairo"),
319 ("gtk4cairo", "gtk4", "gtk4cairo"),
297 ("macosx", "osx", "macosx"),
320 ("macosx", "osx", "macosx"),
298 ("nbagg", "nbagg", "nbagg"),
321 ("nbagg", "nbagg", "nbagg"),
299 ("notebook", "nbagg", "notebook"),
322 ("notebook", "nbagg", "notebook"),
300 ("qtagg", "qt", "qtagg"),
323 ("qtagg", "qt", "qtagg"),
301 ("qtcairo", "qt", "qtcairo"),
324 ("qtcairo", "qt", "qtcairo"),
302 ("qt5agg", "qt5", "qt5agg"),
325 ("qt5agg", "qt5", "qt5agg"),
303 ("qt5cairo", "qt5", "qt5cairo"),
326 ("qt5cairo", "qt5", "qt5cairo"),
304 ("tkagg", "tk", "tkagg"),
327 ("tkagg", "tk", "tkagg"),
305 ("tkcairo", "tk", "tkcairo"),
328 ("tkcairo", "tk", "tkcairo"),
306 ("webagg", "webagg", "webagg"),
329 ("webagg", "webagg", "webagg"),
307 ("wxagg", "wx", "wxagg"),
330 ("wxagg", "wx", "wxagg"),
308 ("wxcairo", "wx", "wxcairo"),
331 ("wxcairo", "wx", "wxcairo"),
309 ],
332 ],
310 )
333 )
311 def test_backend_builtin(name, expected_gui, expected_backend):
334 def test_backend_builtin(name, expected_gui, expected_backend):
312 # Test correct identification of Matplotlib built-in backends without importing and using them,
335 # Test correct identification of Matplotlib built-in backends without importing and using them,
313 # otherwise we would need to ensure all the complex dependencies such as windowing toolkits are
336 # otherwise we would need to ensure all the complex dependencies such as windowing toolkits are
314 # installed.
337 # installed.
315
338
316 mpl_manages_backends = pt._matplotlib_manages_backends()
339 mpl_manages_backends = pt._matplotlib_manages_backends()
317 if not mpl_manages_backends:
340 if not mpl_manages_backends:
318 # Backends not supported before _matplotlib_manages_backends or supported
341 # Backends not supported before _matplotlib_manages_backends or supported
319 # but with different expected_gui or expected_backend.
342 # but with different expected_gui or expected_backend.
320 if (
343 if (
321 name.endswith("agg")
344 name.endswith("agg")
322 or name.endswith("cairo")
345 or name.endswith("cairo")
323 or name in ("headless", "macosx", "pdf", "ps", "svg", "template")
346 or name in ("headless", "macosx", "pdf", "ps", "svg", "template")
324 ):
347 ):
325 pytest.skip()
348 pytest.skip()
326 elif name == "qt6":
349 elif name == "qt6":
327 expected_backend = "qtagg"
350 expected_backend = "qtagg"
328 elif name == "notebook":
351 elif name == "notebook":
329 expected_backend, expected_gui = expected_gui, expected_backend
352 expected_backend, expected_gui = expected_gui, expected_backend
330
353
331 gui, backend = pt.find_gui_and_backend(name)
354 gui, backend = pt.find_gui_and_backend(name)
332 if not mpl_manages_backends:
355 if not mpl_manages_backends:
333 gui = gui.lower() if gui else None
356 gui = gui.lower() if gui else None
334 backend = backend.lower() if backend else None
357 backend = backend.lower() if backend else None
335 assert gui == expected_gui
358 assert gui == expected_gui
336 assert backend == expected_backend
359 assert backend == expected_backend
337
360
338
361
339 def test_backend_entry_point():
362 def test_backend_entry_point():
340 gui, backend = pt.find_gui_and_backend("inline")
363 gui, backend = pt.find_gui_and_backend("inline")
341 assert gui is None
364 assert gui is None
342 expected_backend = (
365 expected_backend = (
343 "inline"
366 "inline"
344 if pt._matplotlib_manages_backends()
367 if pt._matplotlib_manages_backends()
345 else "module://matplotlib_inline.backend_inline"
368 else "module://matplotlib_inline.backend_inline"
346 )
369 )
347 assert backend == expected_backend
370 assert backend == expected_backend
348
371
349
372
350 def test_backend_unknown():
373 def test_backend_unknown():
351 with pytest.raises(RuntimeError if pt._matplotlib_manages_backends() else KeyError):
374 with pytest.raises(RuntimeError if pt._matplotlib_manages_backends() else KeyError):
352 pt.find_gui_and_backend("name-does-not-exist")
375 pt.find_gui_and_backend("name-does-not-exist")
353
354
355 @dec.skipif(not pt._matplotlib_manages_backends())
356 def test_backend_module_name_case_sensitive():
357 # Matplotlib backend names are case insensitive unless explicitly specified using
358 # "module://some_module.some_name" syntax which are case sensitive for mpl >= 3.9.1
359 all_lowercase = "module://matplotlib_inline.backend_inline"
360 some_uppercase = "module://matplotlib_inline.Backend_inline"
361 ip = get_ipython()
362 mpl3_9_1 = matplotlib.__version_info__ >= (3, 9, 1)
363
364 ip.enable_matplotlib(all_lowercase)
365 if mpl3_9_1:
366 with pytest.raises(RuntimeError):
367 ip.enable_matplotlib(some_uppercase)
368 else:
369 ip.enable_matplotlib(some_uppercase)
370
371 ip.run_line_magic("matplotlib", all_lowercase)
372 if mpl3_9_1:
373 with pytest.raises(RuntimeError):
374 ip.run_line_magic("matplotlib", some_uppercase)
375 else:
376 ip.run_line_magic("matplotlib", some_uppercase)
General Comments 0
You need to be logged in to leave comments. Login now