##// END OF EJS Templates
MNT: ensure we can show un-pickled figures...
Thomas A Caswell -
Show More
@@ -1,415 +1,419 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Pylab (matplotlib) support utilities."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 from io import BytesIO
8 8
9 9 from IPython.core.display import _pngxy
10 10 from IPython.utils.decorators import flag_calls
11 11
12 12 # If user specifies a GUI, that dictates the backend, otherwise we read the
13 13 # user's mpl default from the mpl rc structure
14 14 backends = {'tk': 'TkAgg',
15 15 'gtk': 'GTKAgg',
16 16 'gtk3': 'GTK3Agg',
17 17 'wx': 'WXAgg',
18 18 'qt4': 'Qt4Agg',
19 19 'qt5': 'Qt5Agg',
20 20 'qt': 'Qt5Agg',
21 21 'osx': 'MacOSX',
22 22 'nbagg': 'nbAgg',
23 23 'notebook': 'nbAgg',
24 24 'agg': 'agg',
25 25 'svg': 'svg',
26 26 'pdf': 'pdf',
27 27 'ps': 'ps',
28 28 'inline': 'module://ipykernel.pylab.backend_inline',
29 29 'ipympl': 'module://ipympl.backend_nbagg',
30 30 'widget': 'module://ipympl.backend_nbagg',
31 31 }
32 32
33 33 # We also need a reverse backends2guis mapping that will properly choose which
34 34 # GUI support to activate based on the desired matplotlib backend. For the
35 35 # most part it's just a reverse of the above dict, but we also need to add a
36 36 # few others that map to the same GUI manually:
37 37 backend2gui = dict(zip(backends.values(), backends.keys()))
38 38 # Our tests expect backend2gui to just return 'qt'
39 39 backend2gui['Qt4Agg'] = 'qt'
40 40 # In the reverse mapping, there are a few extra valid matplotlib backends that
41 41 # map to the same GUI support
42 42 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
43 43 backend2gui['GTK3Cairo'] = 'gtk3'
44 44 backend2gui['WX'] = 'wx'
45 45 backend2gui['CocoaAgg'] = 'osx'
46 46 # And some backends that don't need GUI integration
47 47 del backend2gui['nbAgg']
48 48 del backend2gui['agg']
49 49 del backend2gui['svg']
50 50 del backend2gui['pdf']
51 51 del backend2gui['ps']
52 52 del backend2gui['module://ipykernel.pylab.backend_inline']
53 53
54 54 #-----------------------------------------------------------------------------
55 55 # Matplotlib utilities
56 56 #-----------------------------------------------------------------------------
57 57
58 58
59 59 def getfigs(*fig_nums):
60 60 """Get a list of matplotlib figures by figure numbers.
61 61
62 62 If no arguments are given, all available figures are returned. If the
63 63 argument list contains references to invalid figures, a warning is printed
64 64 but the function continues pasting further figures.
65 65
66 66 Parameters
67 67 ----------
68 68 figs : tuple
69 69 A tuple of ints giving the figure numbers of the figures to return.
70 70 """
71 71 from matplotlib._pylab_helpers import Gcf
72 72 if not fig_nums:
73 73 fig_managers = Gcf.get_all_fig_managers()
74 74 return [fm.canvas.figure for fm in fig_managers]
75 75 else:
76 76 figs = []
77 77 for num in fig_nums:
78 78 f = Gcf.figs.get(num)
79 79 if f is None:
80 80 print('Warning: figure %s not available.' % num)
81 81 else:
82 82 figs.append(f.canvas.figure)
83 83 return figs
84 84
85 85
86 86 def figsize(sizex, sizey):
87 87 """Set the default figure size to be [sizex, sizey].
88 88
89 89 This is just an easy to remember, convenience wrapper that sets::
90 90
91 91 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
92 92 """
93 93 import matplotlib
94 94 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
95 95
96 96
97 97 def print_figure(fig, fmt='png', bbox_inches='tight', **kwargs):
98 98 """Print a figure to an image, and return the resulting file data
99 99
100 100 Returned data will be bytes unless ``fmt='svg'``,
101 101 in which case it will be unicode.
102 102
103 103 Any keyword args are passed to fig.canvas.print_figure,
104 104 such as ``quality`` or ``bbox_inches``.
105 105 """
106 106 # When there's an empty figure, we shouldn't return anything, otherwise we
107 107 # get big blank areas in the qt console.
108 108 if not fig.axes and not fig.lines:
109 109 return
110 110
111 111 dpi = fig.dpi
112 112 if fmt == 'retina':
113 113 dpi = dpi * 2
114 114 fmt = 'png'
115 115
116 116 # build keyword args
117 117 kw = {
118 118 "format":fmt,
119 119 "facecolor":fig.get_facecolor(),
120 120 "edgecolor":fig.get_edgecolor(),
121 121 "dpi":dpi,
122 122 "bbox_inches":bbox_inches,
123 123 }
124 124 # **kwargs get higher priority
125 125 kw.update(kwargs)
126
126
127 127 bytes_io = BytesIO()
128 if fig.canvas is None:
129 from matplotlib.backend_bases import FigureCanvasBase
130 FigureCanvasBase(fig)
131
128 132 fig.canvas.print_figure(bytes_io, **kw)
129 133 data = bytes_io.getvalue()
130 134 if fmt == 'svg':
131 135 data = data.decode('utf-8')
132 136 return data
133
137
134 138 def retina_figure(fig, **kwargs):
135 139 """format a figure as a pixel-doubled (retina) PNG"""
136 140 pngdata = print_figure(fig, fmt='retina', **kwargs)
137 141 # Make sure that retina_figure acts just like print_figure and returns
138 142 # None when the figure is empty.
139 143 if pngdata is None:
140 144 return
141 145 w, h = _pngxy(pngdata)
142 146 metadata = {"width": w//2, "height":h//2}
143 147 return pngdata, metadata
144 148
145 149 # We need a little factory function here to create the closure where
146 150 # safe_execfile can live.
147 151 def mpl_runner(safe_execfile):
148 152 """Factory to return a matplotlib-enabled runner for %run.
149 153
150 154 Parameters
151 155 ----------
152 156 safe_execfile : function
153 157 This must be a function with the same interface as the
154 158 :meth:`safe_execfile` method of IPython.
155 159
156 160 Returns
157 161 -------
158 162 A function suitable for use as the ``runner`` argument of the %run magic
159 163 function.
160 164 """
161 165
162 166 def mpl_execfile(fname,*where,**kw):
163 167 """matplotlib-aware wrapper around safe_execfile.
164 168
165 169 Its interface is identical to that of the :func:`execfile` builtin.
166 170
167 171 This is ultimately a call to execfile(), but wrapped in safeties to
168 172 properly handle interactive rendering."""
169 173
170 174 import matplotlib
171 175 import matplotlib.pyplot as plt
172 176
173 177 #print '*** Matplotlib runner ***' # dbg
174 178 # turn off rendering until end of script
175 179 is_interactive = matplotlib.rcParams['interactive']
176 180 matplotlib.interactive(False)
177 181 safe_execfile(fname,*where,**kw)
178 182 matplotlib.interactive(is_interactive)
179 183 # make rendering call now, if the user tried to do it
180 184 if plt.draw_if_interactive.called:
181 185 plt.draw()
182 186 plt.draw_if_interactive.called = False
183 187
184 188 # re-draw everything that is stale
185 189 try:
186 190 da = plt.draw_all
187 191 except AttributeError:
188 192 pass
189 193 else:
190 194 da()
191 195
192 196 return mpl_execfile
193 197
194 198
195 199 def _reshow_nbagg_figure(fig):
196 200 """reshow an nbagg figure"""
197 201 try:
198 202 reshow = fig.canvas.manager.reshow
199 203 except AttributeError:
200 204 raise NotImplementedError()
201 205 else:
202 206 reshow()
203 207
204 208
205 209 def select_figure_formats(shell, formats, **kwargs):
206 210 """Select figure formats for the inline backend.
207 211
208 212 Parameters
209 213 ==========
210 214 shell : InteractiveShell
211 215 The main IPython instance.
212 216 formats : str or set
213 217 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
214 218 **kwargs : any
215 219 Extra keyword arguments to be passed to fig.canvas.print_figure.
216 220 """
217 221 import matplotlib
218 222 from matplotlib.figure import Figure
219 223
220 224 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
221 225 png_formatter = shell.display_formatter.formatters['image/png']
222 226 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
223 227 pdf_formatter = shell.display_formatter.formatters['application/pdf']
224 228
225 229 if isinstance(formats, str):
226 230 formats = {formats}
227 231 # cast in case of list / tuple
228 232 formats = set(formats)
229 233
230 234 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
231 235 mplbackend = matplotlib.get_backend().lower()
232 236 if mplbackend == 'nbagg' or mplbackend == 'module://ipympl.backend_nbagg':
233 237 formatter = shell.display_formatter.ipython_display_formatter
234 238 formatter.for_type(Figure, _reshow_nbagg_figure)
235 239
236 240 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
237 241 bad = formats.difference(supported)
238 242 if bad:
239 243 bs = "%s" % ','.join([repr(f) for f in bad])
240 244 gs = "%s" % ','.join([repr(f) for f in supported])
241 245 raise ValueError("supported formats are: %s not %s" % (gs, bs))
242 246
243 247 if 'png' in formats:
244 248 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
245 249 if 'retina' in formats or 'png2x' in formats:
246 250 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))
247 251 if 'jpg' in formats or 'jpeg' in formats:
248 252 jpg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'jpg', **kwargs))
249 253 if 'svg' in formats:
250 254 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg', **kwargs))
251 255 if 'pdf' in formats:
252 256 pdf_formatter.for_type(Figure, lambda fig: print_figure(fig, 'pdf', **kwargs))
253 257
254 258 #-----------------------------------------------------------------------------
255 259 # Code for initializing matplotlib and importing pylab
256 260 #-----------------------------------------------------------------------------
257 261
258 262
259 263 def find_gui_and_backend(gui=None, gui_select=None):
260 264 """Given a gui string return the gui and mpl backend.
261 265
262 266 Parameters
263 267 ----------
264 268 gui : str
265 269 Can be one of ('tk','gtk','wx','qt','qt4','inline','agg').
266 270 gui_select : str
267 271 Can be one of ('tk','gtk','wx','qt','qt4','inline').
268 272 This is any gui already selected by the shell.
269 273
270 274 Returns
271 275 -------
272 276 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
273 277 'WXAgg','Qt4Agg','module://ipykernel.pylab.backend_inline','agg').
274 278 """
275 279
276 280 import matplotlib
277 281
278 282 if gui and gui != 'auto':
279 283 # select backend based on requested gui
280 284 backend = backends[gui]
281 285 if gui == 'agg':
282 286 gui = None
283 287 else:
284 288 # We need to read the backend from the original data structure, *not*
285 289 # from mpl.rcParams, since a prior invocation of %matplotlib may have
286 290 # overwritten that.
287 291 # WARNING: this assumes matplotlib 1.1 or newer!!
288 292 backend = matplotlib.rcParamsOrig['backend']
289 293 # In this case, we need to find what the appropriate gui selection call
290 294 # should be for IPython, so we can activate inputhook accordingly
291 295 gui = backend2gui.get(backend, None)
292 296
293 297 # If we have already had a gui active, we need it and inline are the
294 298 # ones allowed.
295 299 if gui_select and gui != gui_select:
296 300 gui = gui_select
297 301 backend = backends[gui]
298 302
299 303 return gui, backend
300 304
301 305
302 306 def activate_matplotlib(backend):
303 307 """Activate the given backend and set interactive to True."""
304 308
305 309 import matplotlib
306 310 matplotlib.interactive(True)
307 311
308 312 # Matplotlib had a bug where even switch_backend could not force
309 313 # the rcParam to update. This needs to be set *before* the module
310 314 # magic of switch_backend().
311 315 matplotlib.rcParams['backend'] = backend
312 316
313 317 # Due to circular imports, pyplot may be only partially initialised
314 318 # when this function runs.
315 319 # So avoid needing matplotlib attribute-lookup to access pyplot.
316 320 from matplotlib import pyplot as plt
317 321
318 322 plt.switch_backend(backend)
319 323
320 324 plt.show._needmain = False
321 325 # We need to detect at runtime whether show() is called by the user.
322 326 # For this, we wrap it into a decorator which adds a 'called' flag.
323 327 plt.draw_if_interactive = flag_calls(plt.draw_if_interactive)
324 328
325 329
326 330 def import_pylab(user_ns, import_all=True):
327 331 """Populate the namespace with pylab-related values.
328 332
329 333 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
330 334
331 335 Also imports a few names from IPython (figsize, display, getfigs)
332 336
333 337 """
334 338
335 339 # Import numpy as np/pyplot as plt are conventions we're trying to
336 340 # somewhat standardize on. Making them available to users by default
337 341 # will greatly help this.
338 342 s = ("import numpy\n"
339 343 "import matplotlib\n"
340 344 "from matplotlib import pylab, mlab, pyplot\n"
341 345 "np = numpy\n"
342 346 "plt = pyplot\n"
343 347 )
344 348 exec(s, user_ns)
345 349
346 350 if import_all:
347 351 s = ("from matplotlib.pylab import *\n"
348 352 "from numpy import *\n")
349 353 exec(s, user_ns)
350 354
351 355 # IPython symbols to add
352 356 user_ns['figsize'] = figsize
353 357 from IPython.core.display import display
354 358 # Add display and getfigs to the user's namespace
355 359 user_ns['display'] = display
356 360 user_ns['getfigs'] = getfigs
357 361
358 362
359 363 def configure_inline_support(shell, backend):
360 364 """Configure an IPython shell object for matplotlib use.
361 365
362 366 Parameters
363 367 ----------
364 368 shell : InteractiveShell instance
365 369
366 370 backend : matplotlib backend
367 371 """
368 372 # If using our svg payload backend, register the post-execution
369 373 # function that will pick up the results for display. This can only be
370 374 # done with access to the real shell object.
371 375
372 376 # Note: if we can't load the inline backend, then there's no point
373 377 # continuing (such as in terminal-only shells in environments without
374 378 # zeromq available).
375 379 try:
376 380 from ipykernel.pylab.backend_inline import InlineBackend
377 381 except ImportError:
378 382 return
379 383 import matplotlib
380 384
381 385 cfg = InlineBackend.instance(parent=shell)
382 386 cfg.shell = shell
383 387 if cfg not in shell.configurables:
384 388 shell.configurables.append(cfg)
385 389
386 390 if backend == backends['inline']:
387 391 from ipykernel.pylab.backend_inline import flush_figures
388 392 shell.events.register('post_execute', flush_figures)
389 393
390 394 # Save rcParams that will be overwrittern
391 395 shell._saved_rcParams = {}
392 396 for k in cfg.rc:
393 397 shell._saved_rcParams[k] = matplotlib.rcParams[k]
394 398 # load inline_rc
395 399 matplotlib.rcParams.update(cfg.rc)
396 400 new_backend_name = "inline"
397 401 else:
398 402 from ipykernel.pylab.backend_inline import flush_figures
399 403 try:
400 404 shell.events.unregister('post_execute', flush_figures)
401 405 except ValueError:
402 406 pass
403 407 if hasattr(shell, '_saved_rcParams'):
404 408 matplotlib.rcParams.update(shell._saved_rcParams)
405 409 del shell._saved_rcParams
406 410 new_backend_name = "other"
407 411
408 412 # only enable the formats once -> don't change the enabled formats (which the user may
409 413 # has changed) when getting another "%matplotlib inline" call.
410 414 # See https://github.com/ipython/ipykernel/issues/29
411 415 cur_backend = getattr(configure_inline_support, "current_backend", "unset")
412 416 if new_backend_name != cur_backend:
413 417 # Setup the default figure format
414 418 select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs)
415 419 configure_inline_support.current_backend = new_backend_name
@@ -1,250 +1,256 b''
1 1 """Tests for pylab tools module.
2 2 """
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7
8 8 from io import UnsupportedOperation, BytesIO
9 9
10 10 import matplotlib
11 11 matplotlib.use('Agg')
12 12 from matplotlib.figure import Figure
13 13
14 14 from nose import SkipTest
15 15 import nose.tools as nt
16 16
17 17 from matplotlib import pyplot as plt
18 18 import numpy as np
19 19
20 20 from IPython.core.getipython import get_ipython
21 21 from IPython.core.interactiveshell import InteractiveShell
22 22 from IPython.core.display import _PNG, _JPEG
23 23 from .. import pylabtools as pt
24 24
25 25 from IPython.testing import decorators as dec
26 26
27 27
28 28 def test_figure_to_svg():
29 29 # simple empty-figure test
30 30 fig = plt.figure()
31 31 nt.assert_equal(pt.print_figure(fig, 'svg'), None)
32 32
33 33 plt.close('all')
34 34
35 35 # simple check for at least svg-looking output
36 36 fig = plt.figure()
37 37 ax = fig.add_subplot(1,1,1)
38 38 ax.plot([1,2,3])
39 39 plt.draw()
40 40 svg = pt.print_figure(fig, 'svg')[:100].lower()
41 41 nt.assert_in(u'doctype svg', svg)
42 42
43 43 def _check_pil_jpeg_bytes():
44 44 """Skip if PIL can't write JPEGs to BytesIO objects"""
45 45 # PIL's JPEG plugin can't write to BytesIO objects
46 46 # Pillow fixes this
47 47 from PIL import Image
48 48 buf = BytesIO()
49 49 img = Image.new("RGB", (4,4))
50 50 try:
51 51 img.save(buf, 'jpeg')
52 52 except Exception as e:
53 53 ename = e.__class__.__name__
54 54 raise SkipTest("PIL can't write JPEG to BytesIO: %s: %s" % (ename, e))
55 55
56 56 @dec.skip_without("PIL.Image")
57 57 def test_figure_to_jpeg():
58 58 _check_pil_jpeg_bytes()
59 59 # simple check for at least jpeg-looking output
60 60 fig = plt.figure()
61 61 ax = fig.add_subplot(1,1,1)
62 62 ax.plot([1,2,3])
63 63 plt.draw()
64 64 jpeg = pt.print_figure(fig, 'jpeg', quality=50)[:100].lower()
65 65 assert jpeg.startswith(_JPEG)
66 66
67 67 def test_retina_figure():
68 68 # simple empty-figure test
69 69 fig = plt.figure()
70 70 nt.assert_equal(pt.retina_figure(fig), None)
71 71 plt.close('all')
72 72
73 73 fig = plt.figure()
74 74 ax = fig.add_subplot(1,1,1)
75 75 ax.plot([1,2,3])
76 76 plt.draw()
77 77 png, md = pt.retina_figure(fig)
78 78 assert png.startswith(_PNG)
79 79 nt.assert_in('width', md)
80 80 nt.assert_in('height', md)
81 81
82 82 _fmt_mime_map = {
83 83 'png': 'image/png',
84 84 'jpeg': 'image/jpeg',
85 85 'pdf': 'application/pdf',
86 86 'retina': 'image/png',
87 87 'svg': 'image/svg+xml',
88 88 }
89 89
90 90 def test_select_figure_formats_str():
91 91 ip = get_ipython()
92 92 for fmt, active_mime in _fmt_mime_map.items():
93 93 pt.select_figure_formats(ip, fmt)
94 94 for mime, f in ip.display_formatter.formatters.items():
95 95 if mime == active_mime:
96 96 nt.assert_in(Figure, f)
97 97 else:
98 98 nt.assert_not_in(Figure, f)
99 99
100 100 def test_select_figure_formats_kwargs():
101 101 ip = get_ipython()
102 102 kwargs = dict(quality=10, bbox_inches='tight')
103 103 pt.select_figure_formats(ip, 'png', **kwargs)
104 104 formatter = ip.display_formatter.formatters['image/png']
105 105 f = formatter.lookup_by_type(Figure)
106 106 cell = f.__closure__[0].cell_contents
107 107 nt.assert_equal(cell, kwargs)
108 108
109 109 # check that the formatter doesn't raise
110 110 fig = plt.figure()
111 111 ax = fig.add_subplot(1,1,1)
112 112 ax.plot([1,2,3])
113 113 plt.draw()
114 114 formatter.enabled = True
115 115 png = formatter(fig)
116 116 assert png.startswith(_PNG)
117 117
118 118 def test_select_figure_formats_set():
119 119 ip = get_ipython()
120 120 for fmts in [
121 121 {'png', 'svg'},
122 122 ['png'],
123 123 ('jpeg', 'pdf', 'retina'),
124 124 {'svg'},
125 125 ]:
126 126 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
127 127 pt.select_figure_formats(ip, fmts)
128 128 for mime, f in ip.display_formatter.formatters.items():
129 129 if mime in active_mimes:
130 130 nt.assert_in(Figure, f)
131 131 else:
132 132 nt.assert_not_in(Figure, f)
133 133
134 134 def test_select_figure_formats_bad():
135 135 ip = get_ipython()
136 136 with nt.assert_raises(ValueError):
137 137 pt.select_figure_formats(ip, 'foo')
138 138 with nt.assert_raises(ValueError):
139 139 pt.select_figure_formats(ip, {'png', 'foo'})
140 140 with nt.assert_raises(ValueError):
141 141 pt.select_figure_formats(ip, ['retina', 'pdf', 'bar', 'bad'])
142 142
143 143 def test_import_pylab():
144 144 ns = {}
145 145 pt.import_pylab(ns, import_all=False)
146 146 nt.assert_true('plt' in ns)
147 147 nt.assert_equal(ns['np'], np)
148 148
149 149 class TestPylabSwitch(object):
150 150 class Shell(InteractiveShell):
151 151 def enable_gui(self, gui):
152 152 pass
153 153
154 154 def setup(self):
155 155 import matplotlib
156 156 def act_mpl(backend):
157 157 matplotlib.rcParams['backend'] = backend
158 158
159 159 # Save rcParams since they get modified
160 160 self._saved_rcParams = matplotlib.rcParams
161 161 self._saved_rcParamsOrig = matplotlib.rcParamsOrig
162 162 matplotlib.rcParams = dict(backend='Qt4Agg')
163 163 matplotlib.rcParamsOrig = dict(backend='Qt4Agg')
164 164
165 165 # Mock out functions
166 166 self._save_am = pt.activate_matplotlib
167 167 pt.activate_matplotlib = act_mpl
168 168 self._save_ip = pt.import_pylab
169 169 pt.import_pylab = lambda *a,**kw:None
170 170 self._save_cis = pt.configure_inline_support
171 171 pt.configure_inline_support = lambda *a,**kw:None
172 172
173 173 def teardown(self):
174 174 pt.activate_matplotlib = self._save_am
175 175 pt.import_pylab = self._save_ip
176 176 pt.configure_inline_support = self._save_cis
177 177 import matplotlib
178 178 matplotlib.rcParams = self._saved_rcParams
179 179 matplotlib.rcParamsOrig = self._saved_rcParamsOrig
180 180
181 181 def test_qt(self):
182 182 s = self.Shell()
183 183 gui, backend = s.enable_matplotlib(None)
184 184 nt.assert_equal(gui, 'qt')
185 185 nt.assert_equal(s.pylab_gui_select, 'qt')
186 186
187 187 gui, backend = s.enable_matplotlib('inline')
188 188 nt.assert_equal(gui, 'inline')
189 189 nt.assert_equal(s.pylab_gui_select, 'qt')
190 190
191 191 gui, backend = s.enable_matplotlib('qt')
192 192 nt.assert_equal(gui, 'qt')
193 193 nt.assert_equal(s.pylab_gui_select, 'qt')
194 194
195 195 gui, backend = s.enable_matplotlib('inline')
196 196 nt.assert_equal(gui, 'inline')
197 197 nt.assert_equal(s.pylab_gui_select, 'qt')
198 198
199 199 gui, backend = s.enable_matplotlib()
200 200 nt.assert_equal(gui, 'qt')
201 201 nt.assert_equal(s.pylab_gui_select, 'qt')
202 202
203 203 def test_inline(self):
204 204 s = self.Shell()
205 205 gui, backend = s.enable_matplotlib('inline')
206 206 nt.assert_equal(gui, 'inline')
207 207 nt.assert_equal(s.pylab_gui_select, None)
208 208
209 209 gui, backend = s.enable_matplotlib('inline')
210 210 nt.assert_equal(gui, 'inline')
211 211 nt.assert_equal(s.pylab_gui_select, None)
212 212
213 213 gui, backend = s.enable_matplotlib('qt')
214 214 nt.assert_equal(gui, 'qt')
215 215 nt.assert_equal(s.pylab_gui_select, 'qt')
216 216
217 217 def test_inline_twice(self):
218 218 "Using '%matplotlib inline' twice should not reset formatters"
219 219
220 220 ip = self.Shell()
221 221 gui, backend = ip.enable_matplotlib('inline')
222 222 nt.assert_equal(gui, 'inline')
223 223
224 224 fmts = {'png'}
225 225 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
226 226 pt.select_figure_formats(ip, fmts)
227 227
228 228 gui, backend = ip.enable_matplotlib('inline')
229 229 nt.assert_equal(gui, 'inline')
230 230
231 231 for mime, f in ip.display_formatter.formatters.items():
232 232 if mime in active_mimes:
233 233 nt.assert_in(Figure, f)
234 234 else:
235 235 nt.assert_not_in(Figure, f)
236 236
237 237 def test_qt_gtk(self):
238 238 s = self.Shell()
239 239 gui, backend = s.enable_matplotlib('qt')
240 240 nt.assert_equal(gui, 'qt')
241 241 nt.assert_equal(s.pylab_gui_select, 'qt')
242 242
243 243 gui, backend = s.enable_matplotlib('gtk')
244 244 nt.assert_equal(gui, 'qt')
245 245 nt.assert_equal(s.pylab_gui_select, 'qt')
246 246
247 247
248 248 def test_no_gui_backends():
249 249 for k in ['agg', 'svg', 'pdf', 'ps']:
250 250 assert k not in pt.backend2gui
251
252
253 def test_figure_no_canvas():
254 fig = Figure()
255 fig.canvas = None
256 pt.print_figure(fig)
General Comments 0
You need to be logged in to leave comments. Login now