##// END OF EJS Templates
another pass on formatter lookup...
MinRK -
Show More
@@ -1,758 +1,791 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Display formatters.
2 """Display formatters.
3
3
4 Inheritance diagram:
4 Inheritance diagram:
5
5
6 .. inheritance-diagram:: IPython.core.formatters
6 .. inheritance-diagram:: IPython.core.formatters
7 :parts: 3
7 :parts: 3
8
8
9 Authors:
9 Authors:
10
10
11 * Robert Kern
11 * Robert Kern
12 * Brian Granger
12 * Brian Granger
13 """
13 """
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Copyright (C) 2010-2011, IPython Development Team.
15 # Copyright (C) 2010-2011, IPython Development Team.
16 #
16 #
17 # Distributed under the terms of the Modified BSD License.
17 # Distributed under the terms of the Modified BSD License.
18 #
18 #
19 # The full license is in the file COPYING.txt, distributed with this software.
19 # The full license is in the file COPYING.txt, distributed with this software.
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 # Stdlib imports
26 # Stdlib imports
27 import abc
27 import abc
28 import sys
28 import sys
29 import warnings
29 import warnings
30
30
31 # Our own imports
31 # Our own imports
32 from IPython.config.configurable import Configurable
32 from IPython.config.configurable import Configurable
33 from IPython.lib import pretty
33 from IPython.lib import pretty
34 from IPython.utils.traitlets import (
34 from IPython.utils.traitlets import (
35 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
35 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
36 )
36 )
37 from IPython.utils.py3compat import (
37 from IPython.utils.py3compat import (
38 unicode_to_str, with_metaclass, PY3, string_types,
38 unicode_to_str, with_metaclass, PY3, string_types,
39 )
39 )
40
40
41 if PY3:
41 if PY3:
42 from io import StringIO
42 from io import StringIO
43 else:
43 else:
44 from StringIO import StringIO
44 from StringIO import StringIO
45
45
46
46
47 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
48 # The main DisplayFormatter class
48 # The main DisplayFormatter class
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50
50
51 class DisplayFormatter(Configurable):
51 class DisplayFormatter(Configurable):
52
52
53 # When set to true only the default plain text formatter will be used.
53 # When set to true only the default plain text formatter will be used.
54 plain_text_only = Bool(False, config=True)
54 plain_text_only = Bool(False, config=True)
55 def _plain_text_only_changed(self, name, old, new):
55 def _plain_text_only_changed(self, name, old, new):
56 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
56 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
57
57
58 Use DisplayFormatter.active_types = ['text/plain']
58 Use DisplayFormatter.active_types = ['text/plain']
59 for the same effect.
59 for the same effect.
60 """, DeprecationWarning)
60 """, DeprecationWarning)
61 if new:
61 if new:
62 self.active_types = ['text/plain']
62 self.active_types = ['text/plain']
63 else:
63 else:
64 self.active_types = self.format_types
64 self.active_types = self.format_types
65
65
66 active_types = List(Unicode, config=True,
66 active_types = List(Unicode, config=True,
67 help="""List of currently active mime-types to display.
67 help="""List of currently active mime-types to display.
68 You can use this to set a white-list for formats to display.
68 You can use this to set a white-list for formats to display.
69
69
70 Most users will not need to change this value.
70 Most users will not need to change this value.
71 """)
71 """)
72 def _active_types_default(self):
72 def _active_types_default(self):
73 return self.format_types
73 return self.format_types
74
74
75 def _active_types_changed(self, name, old, new):
75 def _active_types_changed(self, name, old, new):
76 for key, formatter in self.formatters.items():
76 for key, formatter in self.formatters.items():
77 if key in new:
77 if key in new:
78 formatter.enabled = True
78 formatter.enabled = True
79 else:
79 else:
80 formatter.enabled = False
80 formatter.enabled = False
81
81
82 # A dict of formatter whose keys are format types (MIME types) and whose
82 # A dict of formatter whose keys are format types (MIME types) and whose
83 # values are subclasses of BaseFormatter.
83 # values are subclasses of BaseFormatter.
84 formatters = Dict()
84 formatters = Dict()
85 def _formatters_default(self):
85 def _formatters_default(self):
86 """Activate the default formatters."""
86 """Activate the default formatters."""
87 formatter_classes = [
87 formatter_classes = [
88 PlainTextFormatter,
88 PlainTextFormatter,
89 HTMLFormatter,
89 HTMLFormatter,
90 SVGFormatter,
90 SVGFormatter,
91 PNGFormatter,
91 PNGFormatter,
92 JPEGFormatter,
92 JPEGFormatter,
93 LatexFormatter,
93 LatexFormatter,
94 JSONFormatter,
94 JSONFormatter,
95 JavascriptFormatter
95 JavascriptFormatter
96 ]
96 ]
97 d = {}
97 d = {}
98 for cls in formatter_classes:
98 for cls in formatter_classes:
99 f = cls(parent=self)
99 f = cls(parent=self)
100 d[f.format_type] = f
100 d[f.format_type] = f
101 return d
101 return d
102
102
103 def format(self, obj, include=None, exclude=None):
103 def format(self, obj, include=None, exclude=None):
104 """Return a format data dict for an object.
104 """Return a format data dict for an object.
105
105
106 By default all format types will be computed.
106 By default all format types will be computed.
107
107
108 The following MIME types are currently implemented:
108 The following MIME types are currently implemented:
109
109
110 * text/plain
110 * text/plain
111 * text/html
111 * text/html
112 * text/latex
112 * text/latex
113 * application/json
113 * application/json
114 * application/javascript
114 * application/javascript
115 * image/png
115 * image/png
116 * image/jpeg
116 * image/jpeg
117 * image/svg+xml
117 * image/svg+xml
118
118
119 Parameters
119 Parameters
120 ----------
120 ----------
121 obj : object
121 obj : object
122 The Python object whose format data will be computed.
122 The Python object whose format data will be computed.
123 include : list or tuple, optional
123 include : list or tuple, optional
124 A list of format type strings (MIME types) to include in the
124 A list of format type strings (MIME types) to include in the
125 format data dict. If this is set *only* the format types included
125 format data dict. If this is set *only* the format types included
126 in this list will be computed.
126 in this list will be computed.
127 exclude : list or tuple, optional
127 exclude : list or tuple, optional
128 A list of format type string (MIME types) to exclude in the format
128 A list of format type string (MIME types) to exclude in the format
129 data dict. If this is set all format types will be computed,
129 data dict. If this is set all format types will be computed,
130 except for those included in this argument.
130 except for those included in this argument.
131
131
132 Returns
132 Returns
133 -------
133 -------
134 (format_dict, metadata_dict) : tuple of two dicts
134 (format_dict, metadata_dict) : tuple of two dicts
135
135
136 format_dict is a dictionary of key/value pairs, one of each format that was
136 format_dict is a dictionary of key/value pairs, one of each format that was
137 generated for the object. The keys are the format types, which
137 generated for the object. The keys are the format types, which
138 will usually be MIME type strings and the values and JSON'able
138 will usually be MIME type strings and the values and JSON'able
139 data structure containing the raw data for the representation in
139 data structure containing the raw data for the representation in
140 that format.
140 that format.
141
141
142 metadata_dict is a dictionary of metadata about each mime-type output.
142 metadata_dict is a dictionary of metadata about each mime-type output.
143 Its keys will be a strict subset of the keys in format_dict.
143 Its keys will be a strict subset of the keys in format_dict.
144 """
144 """
145 format_dict = {}
145 format_dict = {}
146 md_dict = {}
146 md_dict = {}
147
147
148 for format_type, formatter in self.formatters.items():
148 for format_type, formatter in self.formatters.items():
149 if include and format_type not in include:
149 if include and format_type not in include:
150 continue
150 continue
151 if exclude and format_type in exclude:
151 if exclude and format_type in exclude:
152 continue
152 continue
153
153
154 md = None
154 md = None
155 try:
155 try:
156 data = formatter(obj)
156 data = formatter(obj)
157 except:
157 except:
158 # FIXME: log the exception
158 # FIXME: log the exception
159 raise
159 raise
160
160
161 # formatters can return raw data or (data, metadata)
161 # formatters can return raw data or (data, metadata)
162 if isinstance(data, tuple) and len(data) == 2:
162 if isinstance(data, tuple) and len(data) == 2:
163 data, md = data
163 data, md = data
164
164
165 if data is not None:
165 if data is not None:
166 format_dict[format_type] = data
166 format_dict[format_type] = data
167 if md is not None:
167 if md is not None:
168 md_dict[format_type] = md
168 md_dict[format_type] = md
169
169
170 return format_dict, md_dict
170 return format_dict, md_dict
171
171
172 @property
172 @property
173 def format_types(self):
173 def format_types(self):
174 """Return the format types (MIME types) of the active formatters."""
174 """Return the format types (MIME types) of the active formatters."""
175 return list(self.formatters.keys())
175 return list(self.formatters.keys())
176
176
177
177
178 #-----------------------------------------------------------------------------
178 #-----------------------------------------------------------------------------
179 # Formatters for specific format types (text, html, svg, etc.)
179 # Formatters for specific format types (text, html, svg, etc.)
180 #-----------------------------------------------------------------------------
180 #-----------------------------------------------------------------------------
181
181
182
182
183 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
183 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
184 """ Abstract base class for Formatters.
184 """ Abstract base class for Formatters.
185
185
186 A formatter is a callable class that is responsible for computing the
186 A formatter is a callable class that is responsible for computing the
187 raw format data for a particular format type (MIME type). For example,
187 raw format data for a particular format type (MIME type). For example,
188 an HTML formatter would have a format type of `text/html` and would return
188 an HTML formatter would have a format type of `text/html` and would return
189 the HTML representation of the object when called.
189 the HTML representation of the object when called.
190 """
190 """
191
191
192 # The format type of the data returned, usually a MIME type.
192 # The format type of the data returned, usually a MIME type.
193 format_type = 'text/plain'
193 format_type = 'text/plain'
194
194
195 # Is the formatter enabled...
195 # Is the formatter enabled...
196 enabled = True
196 enabled = True
197
197
198 @abc.abstractmethod
198 @abc.abstractmethod
199 def __call__(self, obj):
199 def __call__(self, obj):
200 """Return a JSON'able representation of the object.
200 """Return a JSON'able representation of the object.
201
201
202 If the object cannot be formatted by this formatter, then return None
202 If the object cannot be formatted by this formatter, then return None
203 """
203 """
204 try:
204 try:
205 return repr(obj)
205 return repr(obj)
206 except Exception:
206 except Exception:
207 return None
207 return None
208
208
209
209
210 def _mod_name_key(typ):
210 def _mod_name_key(typ):
211 """Return a '__module__.__name__' string key for a type."""
211 """Return a (__module__, __name__) tuple for a type.
212
213 Used as key in Formatter.deferred_printers.
214 """
212 module = getattr(typ, '__module__', None)
215 module = getattr(typ, '__module__', None)
213 name = getattr(typ, '__name__', None)
216 name = getattr(typ, '__name__', None)
214 return (module, name)
217 return (module, name)
215
218
216
219
217 def _get_type(obj):
220 def _get_type(obj):
218 """Return the type of an instance (old and new-style)"""
221 """Return the type of an instance (old and new-style)"""
219 return getattr(obj, '__class__', None) or type(obj)
222 return getattr(obj, '__class__', None) or type(obj)
220
223
224 _raise_key_error = object()
221
225
222 class BaseFormatter(Configurable):
226 class BaseFormatter(Configurable):
223 """A base formatter class that is configurable.
227 """A base formatter class that is configurable.
224
228
225 This formatter should usually be used as the base class of all formatters.
229 This formatter should usually be used as the base class of all formatters.
226 It is a traited :class:`Configurable` class and includes an extensible
230 It is a traited :class:`Configurable` class and includes an extensible
227 API for users to determine how their objects are formatted. The following
231 API for users to determine how their objects are formatted. The following
228 logic is used to find a function to format an given object.
232 logic is used to find a function to format an given object.
229
233
230 1. The object is introspected to see if it has a method with the name
234 1. The object is introspected to see if it has a method with the name
231 :attr:`print_method`. If is does, that object is passed to that method
235 :attr:`print_method`. If is does, that object is passed to that method
232 for formatting.
236 for formatting.
233 2. If no print method is found, three internal dictionaries are consulted
237 2. If no print method is found, three internal dictionaries are consulted
234 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
238 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
235 and :attr:`deferred_printers`.
239 and :attr:`deferred_printers`.
236
240
237 Users should use these dictionaries to register functions that will be
241 Users should use these dictionaries to register functions that will be
238 used to compute the format data for their objects (if those objects don't
242 used to compute the format data for their objects (if those objects don't
239 have the special print methods). The easiest way of using these
243 have the special print methods). The easiest way of using these
240 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
244 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
241 methods.
245 methods.
242
246
243 If no function/callable is found to compute the format data, ``None`` is
247 If no function/callable is found to compute the format data, ``None`` is
244 returned and this format type is not used.
248 returned and this format type is not used.
245 """
249 """
246
250
247 format_type = Unicode('text/plain')
251 format_type = Unicode('text/plain')
248
252
249 enabled = Bool(True, config=True)
253 enabled = Bool(True, config=True)
250
254
251 print_method = ObjectName('__repr__')
255 print_method = ObjectName('__repr__')
252
256
253 # The singleton printers.
257 # The singleton printers.
254 # Maps the IDs of the builtin singleton objects to the format functions.
258 # Maps the IDs of the builtin singleton objects to the format functions.
255 singleton_printers = Dict(config=True)
259 singleton_printers = Dict(config=True)
256
260
257 # The type-specific printers.
261 # The type-specific printers.
258 # Map type objects to the format functions.
262 # Map type objects to the format functions.
259 type_printers = Dict(config=True)
263 type_printers = Dict(config=True)
260
264
261 # The deferred-import type-specific printers.
265 # The deferred-import type-specific printers.
262 # Map (modulename, classname) pairs to the format functions.
266 # Map (modulename, classname) pairs to the format functions.
263 deferred_printers = Dict(config=True)
267 deferred_printers = Dict(config=True)
264
268
265 def __call__(self, obj):
269 def __call__(self, obj):
266 """Compute the format for an object."""
270 """Compute the format for an object."""
267 if self.enabled:
271 if self.enabled:
268 try:
272 try:
269 # lookup registered printer
273 # lookup registered printer
270 try:
274 try:
271 printer = self.lookup(obj)
275 printer = self.lookup(obj)
272 except KeyError:
276 except KeyError:
273 pass
277 pass
274 else:
278 else:
275 return printer(obj)
279 return printer(obj)
276 # Finally look for special method names
280 # Finally look for special method names
277 method = pretty._safe_getattr(obj, self.print_method, None)
281 method = pretty._safe_getattr(obj, self.print_method, None)
278 if method is not None:
282 if method is not None:
279 return method()
283 return method()
280 return None
284 return None
281 except Exception:
285 except Exception:
282 pass
286 pass
283 else:
287 else:
284 return None
288 return None
285
289
290 def __contains__(self, typ):
291 """map in to lookup_by_type"""
292 try:
293 self.lookup_by_type(typ)
294 except KeyError:
295 return False
296 else:
297 return True
298
286 def lookup(self, obj):
299 def lookup(self, obj):
287 """Look up the formatter for a given instance.
300 """Look up the formatter for a given instance.
288
301
289 Parameters
302 Parameters
290 ----------
303 ----------
291 obj : object instance
304 obj : object instance
292
305
293 Returns
306 Returns
294 -------
307 -------
295 f : callable
308 f : callable
296 The registered fromatting callable for the type.
309 The registered formatting callable for the type.
297
310
298 Raises
311 Raises
299 ------
312 ------
300 KeyError if the type has not been registered.
313 KeyError if the type has not been registered.
301 """
314 """
302 # look for singleton first
315 # look for singleton first
303 obj_id = id(obj)
316 obj_id = id(obj)
304 if obj_id in self.singleton_printers:
317 if obj_id in self.singleton_printers:
305 return self.singleton_printers[obj_id]
318 return self.singleton_printers[obj_id]
306 # then lookup by type
319 # then lookup by type
307 return self.lookup_by_type(_get_type(obj))
320 return self.lookup_by_type(_get_type(obj))
308
321
309 def lookup_by_type(self, typ):
322 def lookup_by_type(self, typ):
310 """ Look up all the registered formatters for a type.
323 """Look up the registered formatter for a type.
311
324
312 Parameters
325 Parameters
313 ----------
326 ----------
314 typ : type
327 typ : type
315
328
316 Returns
329 Returns
317 -------
330 -------
318 f : callable
331 f : callable
319 The registered fromatting callable for the type.
332 The registered formatting callable for the type.
320
333
321 Raises
334 Raises
322 ------
335 ------
323 KeyError if the type has not been registered.
336 KeyError if the type has not been registered.
324 """
337 """
325 for cls in pretty._get_mro(typ):
338 if isinstance(typ, string_types):
326 if cls in self.type_printers or self._in_deferred_types(cls):
339 typ_key = tuple(typ.rsplit('.',1))
327 return self.type_printers[cls]
340 if typ_key not in self.deferred_printers:
341 # We may have it cached in the type map. We will have to
342 # iterate over all of the types to check.
343 for cls in self.type_printers:
344 if _mod_name_key(cls) == typ_key:
345 return self.type_printers[cls]
346 else:
347 return self.deferred_printers[typ_key]
348 else:
349 for cls in pretty._get_mro(typ):
350 if cls in self.type_printers or self._in_deferred_types(cls):
351 return self.type_printers[cls]
328
352
329 # If we have reached here, the lookup failed.
353 # If we have reached here, the lookup failed.
330 raise KeyError("No registered printer for {0!r}".format(typ))
354 raise KeyError("No registered printer for {0!r}".format(typ))
331
355
332 def for_type(self, typ, func=None):
356 def for_type(self, typ, func=None):
333 """Add a format function for a given type.
357 """Add a format function for a given type.
334
358
335 Parameters
359 Parameters
336 -----------
360 -----------
337 typ : class
361 typ : class
338 The class of the object that will be formatted using `func`.
362 The class of the object that will be formatted using `func`.
339 func : callable
363 func : callable
340 A callable for computing the format data.
364 A callable for computing the format data.
341 `func` will be called with the object to be formatted,
365 `func` will be called with the object to be formatted,
342 and will return the raw data in this formatter's format.
366 and will return the raw data in this formatter's format.
343 Subclasses may use a different call signature for the
367 Subclasses may use a different call signature for the
344 `func` argument.
368 `func` argument.
345
369
346 If `func` is None or not specified, there will be no change,
370 If `func` is None or not specified, there will be no change,
347 only returning the current value.
371 only returning the current value.
348
372
349 Returns
373 Returns
350 -------
374 -------
351 oldfunc : callable
375 oldfunc : callable
352 The currently registered callable.
376 The currently registered callable.
353 If you are registering a new formatter,
377 If you are registering a new formatter,
354 this will be the previous value (to enable restoring later).
378 this will be the previous value (to enable restoring later).
355 """
379 """
356 # if string given, interpret as 'pkg.module.class_name'
380 # if string given, interpret as 'pkg.module.class_name'
357 if isinstance(typ, string_types):
381 if isinstance(typ, string_types):
358 type_module, type_name = typ.rsplit('.', 1)
382 type_module, type_name = typ.rsplit('.', 1)
359 return self.for_type_by_name(type_module, type_name, func)
383 return self.for_type_by_name(type_module, type_name, func)
360
384
361 try:
385 try:
362 oldfunc = self.lookup_by_type(typ)
386 oldfunc = self.lookup_by_type(typ)
363 except KeyError:
387 except KeyError:
364 oldfunc = None
388 oldfunc = None
365
389
366 if func is not None:
390 if func is not None:
367 self.type_printers[typ] = func
391 self.type_printers[typ] = func
368
392
369 return oldfunc
393 return oldfunc
370
394
371 def for_type_by_name(self, type_module, type_name, func=None):
395 def for_type_by_name(self, type_module, type_name, func=None):
372 """Add a format function for a type specified by the full dotted
396 """Add a format function for a type specified by the full dotted
373 module and name of the type, rather than the type of the object.
397 module and name of the type, rather than the type of the object.
374
398
375 Parameters
399 Parameters
376 ----------
400 ----------
377 type_module : str
401 type_module : str
378 The full dotted name of the module the type is defined in, like
402 The full dotted name of the module the type is defined in, like
379 ``numpy``.
403 ``numpy``.
380 type_name : str
404 type_name : str
381 The name of the type (the class name), like ``dtype``
405 The name of the type (the class name), like ``dtype``
382 func : callable
406 func : callable
383 A callable for computing the format data.
407 A callable for computing the format data.
384 `func` will be called with the object to be formatted,
408 `func` will be called with the object to be formatted,
385 and will return the raw data in this formatter's format.
409 and will return the raw data in this formatter's format.
386 Subclasses may use a different call signature for the
410 Subclasses may use a different call signature for the
387 `func` argument.
411 `func` argument.
388
412
389 If `func` is None or unspecified, there will be no change,
413 If `func` is None or unspecified, there will be no change,
390 only returning the current value.
414 only returning the current value.
391
415
392 Returns
416 Returns
393 -------
417 -------
394 oldfunc : callable
418 oldfunc : callable
395 The currently registered callable.
419 The currently registered callable.
396 If you are registering a new formatter,
420 If you are registering a new formatter,
397 this will be the previous value (to enable restoring later).
421 this will be the previous value (to enable restoring later).
398 """
422 """
399 key = (type_module, type_name)
423 key = (type_module, type_name)
400
424
401 oldfunc = self.deferred_printers.get(key, None)
425 try:
426 oldfunc = self.lookup_by_type("%s.%s" % key)
427 except KeyError:
428 oldfunc = None
429
402 if func is not None:
430 if func is not None:
403 self.deferred_printers[key] = func
431 self.deferred_printers[key] = func
404 return oldfunc
432 return oldfunc
405
433
406 def pop(self, typ):
434 def pop(self, typ, default=_raise_key_error):
407 """ Pop a registered object for the given type.
435 """Pop a formatter for the given type.
408
436
409 Parameters
437 Parameters
410 ----------
438 ----------
411 typ : type or '__module__.__name__' string for a type
439 typ : type or '__module__.__name__' string for a type
440 default : object
441 value to be returned if no formatter is registered for typ.
412
442
413 Returns
443 Returns
414 -------
444 -------
415 obj : object
445 obj : object
416 The last registered object for the type.
446 The last registered object for the type.
417
447
418 Raises
448 Raises
419 ------
449 ------
420 KeyError if the type is not registered.
450 KeyError if the type is not registered and default is not specified.
421 """
451 """
452
422 if isinstance(typ, string_types):
453 if isinstance(typ, string_types):
423 typ_key = tuple(typ.rsplit('.',1))
454 typ_key = tuple(typ.rsplit('.',1))
424 if typ_key not in self.deferred_printers:
455 if typ_key not in self.deferred_printers:
425 # We may have it cached in the type map. We will have to
456 # We may have it cached in the type map. We will have to
426 # iterate over all of the types to check.
457 # iterate over all of the types to check.
427 for cls in self.type_printers:
458 for cls in self.type_printers:
428 if _mod_name_key(cls) == typ_key:
459 if _mod_name_key(cls) == typ_key:
429 old = self.type_printers.pop(cls)
460 old = self.type_printers.pop(cls)
430 break
461 break
431 else:
462 else:
432 raise KeyError("No registered value for {0!r}".format(typ_key))
463 old = default
433 else:
464 else:
434 old = self.deferred_printers.pop(typ_key)
465 old = self.deferred_printers.pop(typ_key)
435 else:
466 else:
436 if typ in self.type_printers:
467 if typ in self.type_printers:
437 old = self.type_printers.pop(typ)
468 old = self.type_printers.pop(typ)
438 else:
469 else:
439 old = self.deferred_printers.pop(_mod_name_key(typ))
470 old = self.deferred_printers.pop(_mod_name_key(typ), default)
471 if old is _raise_key_error:
472 raise KeyError("No registered value for {0!r}".format(typ))
440 return old
473 return old
441
474
442 def _in_deferred_types(self, cls):
475 def _in_deferred_types(self, cls):
443 """
476 """
444 Check if the given class is specified in the deferred type registry.
477 Check if the given class is specified in the deferred type registry.
445
478
446 Successful matches will be moved to the regular type registry for future use.
479 Successful matches will be moved to the regular type registry for future use.
447 """
480 """
448 mod = getattr(cls, '__module__', None)
481 mod = getattr(cls, '__module__', None)
449 name = getattr(cls, '__name__', None)
482 name = getattr(cls, '__name__', None)
450 key = (mod, name)
483 key = (mod, name)
451 if key in self.deferred_printers:
484 if key in self.deferred_printers:
452 # Move the printer over to the regular registry.
485 # Move the printer over to the regular registry.
453 printer = self.deferred_printers.pop(key)
486 printer = self.deferred_printers.pop(key)
454 self.type_printers[cls] = printer
487 self.type_printers[cls] = printer
455 return True
488 return True
456 return False
489 return False
457
490
458
491
459 class PlainTextFormatter(BaseFormatter):
492 class PlainTextFormatter(BaseFormatter):
460 """The default pretty-printer.
493 """The default pretty-printer.
461
494
462 This uses :mod:`IPython.lib.pretty` to compute the format data of
495 This uses :mod:`IPython.lib.pretty` to compute the format data of
463 the object. If the object cannot be pretty printed, :func:`repr` is used.
496 the object. If the object cannot be pretty printed, :func:`repr` is used.
464 See the documentation of :mod:`IPython.lib.pretty` for details on
497 See the documentation of :mod:`IPython.lib.pretty` for details on
465 how to write pretty printers. Here is a simple example::
498 how to write pretty printers. Here is a simple example::
466
499
467 def dtype_pprinter(obj, p, cycle):
500 def dtype_pprinter(obj, p, cycle):
468 if cycle:
501 if cycle:
469 return p.text('dtype(...)')
502 return p.text('dtype(...)')
470 if hasattr(obj, 'fields'):
503 if hasattr(obj, 'fields'):
471 if obj.fields is None:
504 if obj.fields is None:
472 p.text(repr(obj))
505 p.text(repr(obj))
473 else:
506 else:
474 p.begin_group(7, 'dtype([')
507 p.begin_group(7, 'dtype([')
475 for i, field in enumerate(obj.descr):
508 for i, field in enumerate(obj.descr):
476 if i > 0:
509 if i > 0:
477 p.text(',')
510 p.text(',')
478 p.breakable()
511 p.breakable()
479 p.pretty(field)
512 p.pretty(field)
480 p.end_group(7, '])')
513 p.end_group(7, '])')
481 """
514 """
482
515
483 # The format type of data returned.
516 # The format type of data returned.
484 format_type = Unicode('text/plain')
517 format_type = Unicode('text/plain')
485
518
486 # This subclass ignores this attribute as it always need to return
519 # This subclass ignores this attribute as it always need to return
487 # something.
520 # something.
488 enabled = Bool(True, config=False)
521 enabled = Bool(True, config=False)
489
522
490 # Look for a _repr_pretty_ methods to use for pretty printing.
523 # Look for a _repr_pretty_ methods to use for pretty printing.
491 print_method = ObjectName('_repr_pretty_')
524 print_method = ObjectName('_repr_pretty_')
492
525
493 # Whether to pretty-print or not.
526 # Whether to pretty-print or not.
494 pprint = Bool(True, config=True)
527 pprint = Bool(True, config=True)
495
528
496 # Whether to be verbose or not.
529 # Whether to be verbose or not.
497 verbose = Bool(False, config=True)
530 verbose = Bool(False, config=True)
498
531
499 # The maximum width.
532 # The maximum width.
500 max_width = Integer(79, config=True)
533 max_width = Integer(79, config=True)
501
534
502 # The newline character.
535 # The newline character.
503 newline = Unicode('\n', config=True)
536 newline = Unicode('\n', config=True)
504
537
505 # format-string for pprinting floats
538 # format-string for pprinting floats
506 float_format = Unicode('%r')
539 float_format = Unicode('%r')
507 # setter for float precision, either int or direct format-string
540 # setter for float precision, either int or direct format-string
508 float_precision = CUnicode('', config=True)
541 float_precision = CUnicode('', config=True)
509
542
510 def _float_precision_changed(self, name, old, new):
543 def _float_precision_changed(self, name, old, new):
511 """float_precision changed, set float_format accordingly.
544 """float_precision changed, set float_format accordingly.
512
545
513 float_precision can be set by int or str.
546 float_precision can be set by int or str.
514 This will set float_format, after interpreting input.
547 This will set float_format, after interpreting input.
515 If numpy has been imported, numpy print precision will also be set.
548 If numpy has been imported, numpy print precision will also be set.
516
549
517 integer `n` sets format to '%.nf', otherwise, format set directly.
550 integer `n` sets format to '%.nf', otherwise, format set directly.
518
551
519 An empty string returns to defaults (repr for float, 8 for numpy).
552 An empty string returns to defaults (repr for float, 8 for numpy).
520
553
521 This parameter can be set via the '%precision' magic.
554 This parameter can be set via the '%precision' magic.
522 """
555 """
523
556
524 if '%' in new:
557 if '%' in new:
525 # got explicit format string
558 # got explicit format string
526 fmt = new
559 fmt = new
527 try:
560 try:
528 fmt%3.14159
561 fmt%3.14159
529 except Exception:
562 except Exception:
530 raise ValueError("Precision must be int or format string, not %r"%new)
563 raise ValueError("Precision must be int or format string, not %r"%new)
531 elif new:
564 elif new:
532 # otherwise, should be an int
565 # otherwise, should be an int
533 try:
566 try:
534 i = int(new)
567 i = int(new)
535 assert i >= 0
568 assert i >= 0
536 except ValueError:
569 except ValueError:
537 raise ValueError("Precision must be int or format string, not %r"%new)
570 raise ValueError("Precision must be int or format string, not %r"%new)
538 except AssertionError:
571 except AssertionError:
539 raise ValueError("int precision must be non-negative, not %r"%i)
572 raise ValueError("int precision must be non-negative, not %r"%i)
540
573
541 fmt = '%%.%if'%i
574 fmt = '%%.%if'%i
542 if 'numpy' in sys.modules:
575 if 'numpy' in sys.modules:
543 # set numpy precision if it has been imported
576 # set numpy precision if it has been imported
544 import numpy
577 import numpy
545 numpy.set_printoptions(precision=i)
578 numpy.set_printoptions(precision=i)
546 else:
579 else:
547 # default back to repr
580 # default back to repr
548 fmt = '%r'
581 fmt = '%r'
549 if 'numpy' in sys.modules:
582 if 'numpy' in sys.modules:
550 import numpy
583 import numpy
551 # numpy default is 8
584 # numpy default is 8
552 numpy.set_printoptions(precision=8)
585 numpy.set_printoptions(precision=8)
553 self.float_format = fmt
586 self.float_format = fmt
554
587
555 # Use the default pretty printers from IPython.lib.pretty.
588 # Use the default pretty printers from IPython.lib.pretty.
556 def _singleton_printers_default(self):
589 def _singleton_printers_default(self):
557 return pretty._singleton_pprinters.copy()
590 return pretty._singleton_pprinters.copy()
558
591
559 def _type_printers_default(self):
592 def _type_printers_default(self):
560 d = pretty._type_pprinters.copy()
593 d = pretty._type_pprinters.copy()
561 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
594 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
562 return d
595 return d
563
596
564 def _deferred_printers_default(self):
597 def _deferred_printers_default(self):
565 return pretty._deferred_type_pprinters.copy()
598 return pretty._deferred_type_pprinters.copy()
566
599
567 #### FormatterABC interface ####
600 #### FormatterABC interface ####
568
601
569 def __call__(self, obj):
602 def __call__(self, obj):
570 """Compute the pretty representation of the object."""
603 """Compute the pretty representation of the object."""
571 if not self.pprint:
604 if not self.pprint:
572 return pretty._safe_repr(obj)
605 return pretty._safe_repr(obj)
573 else:
606 else:
574 # This uses use StringIO, as cStringIO doesn't handle unicode.
607 # This uses use StringIO, as cStringIO doesn't handle unicode.
575 stream = StringIO()
608 stream = StringIO()
576 # self.newline.encode() is a quick fix for issue gh-597. We need to
609 # self.newline.encode() is a quick fix for issue gh-597. We need to
577 # ensure that stream does not get a mix of unicode and bytestrings,
610 # ensure that stream does not get a mix of unicode and bytestrings,
578 # or it will cause trouble.
611 # or it will cause trouble.
579 printer = pretty.RepresentationPrinter(stream, self.verbose,
612 printer = pretty.RepresentationPrinter(stream, self.verbose,
580 self.max_width, unicode_to_str(self.newline),
613 self.max_width, unicode_to_str(self.newline),
581 singleton_pprinters=self.singleton_printers,
614 singleton_pprinters=self.singleton_printers,
582 type_pprinters=self.type_printers,
615 type_pprinters=self.type_printers,
583 deferred_pprinters=self.deferred_printers)
616 deferred_pprinters=self.deferred_printers)
584 printer.pretty(obj)
617 printer.pretty(obj)
585 printer.flush()
618 printer.flush()
586 return stream.getvalue()
619 return stream.getvalue()
587
620
588
621
589 class HTMLFormatter(BaseFormatter):
622 class HTMLFormatter(BaseFormatter):
590 """An HTML formatter.
623 """An HTML formatter.
591
624
592 To define the callables that compute the HTML representation of your
625 To define the callables that compute the HTML representation of your
593 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
626 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
594 or :meth:`for_type_by_name` methods to register functions that handle
627 or :meth:`for_type_by_name` methods to register functions that handle
595 this.
628 this.
596
629
597 The return value of this formatter should be a valid HTML snippet that
630 The return value of this formatter should be a valid HTML snippet that
598 could be injected into an existing DOM. It should *not* include the
631 could be injected into an existing DOM. It should *not* include the
599 ```<html>`` or ```<body>`` tags.
632 ```<html>`` or ```<body>`` tags.
600 """
633 """
601 format_type = Unicode('text/html')
634 format_type = Unicode('text/html')
602
635
603 print_method = ObjectName('_repr_html_')
636 print_method = ObjectName('_repr_html_')
604
637
605
638
606 class SVGFormatter(BaseFormatter):
639 class SVGFormatter(BaseFormatter):
607 """An SVG formatter.
640 """An SVG formatter.
608
641
609 To define the callables that compute the SVG representation of your
642 To define the callables that compute the SVG representation of your
610 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
643 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
611 or :meth:`for_type_by_name` methods to register functions that handle
644 or :meth:`for_type_by_name` methods to register functions that handle
612 this.
645 this.
613
646
614 The return value of this formatter should be valid SVG enclosed in
647 The return value of this formatter should be valid SVG enclosed in
615 ```<svg>``` tags, that could be injected into an existing DOM. It should
648 ```<svg>``` tags, that could be injected into an existing DOM. It should
616 *not* include the ```<html>`` or ```<body>`` tags.
649 *not* include the ```<html>`` or ```<body>`` tags.
617 """
650 """
618 format_type = Unicode('image/svg+xml')
651 format_type = Unicode('image/svg+xml')
619
652
620 print_method = ObjectName('_repr_svg_')
653 print_method = ObjectName('_repr_svg_')
621
654
622
655
623 class PNGFormatter(BaseFormatter):
656 class PNGFormatter(BaseFormatter):
624 """A PNG formatter.
657 """A PNG formatter.
625
658
626 To define the callables that compute the PNG representation of your
659 To define the callables that compute the PNG representation of your
627 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
660 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
628 or :meth:`for_type_by_name` methods to register functions that handle
661 or :meth:`for_type_by_name` methods to register functions that handle
629 this.
662 this.
630
663
631 The return value of this formatter should be raw PNG data, *not*
664 The return value of this formatter should be raw PNG data, *not*
632 base64 encoded.
665 base64 encoded.
633 """
666 """
634 format_type = Unicode('image/png')
667 format_type = Unicode('image/png')
635
668
636 print_method = ObjectName('_repr_png_')
669 print_method = ObjectName('_repr_png_')
637
670
638
671
639 class JPEGFormatter(BaseFormatter):
672 class JPEGFormatter(BaseFormatter):
640 """A JPEG formatter.
673 """A JPEG formatter.
641
674
642 To define the callables that compute the JPEG representation of your
675 To define the callables that compute the JPEG representation of your
643 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
676 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
644 or :meth:`for_type_by_name` methods to register functions that handle
677 or :meth:`for_type_by_name` methods to register functions that handle
645 this.
678 this.
646
679
647 The return value of this formatter should be raw JPEG data, *not*
680 The return value of this formatter should be raw JPEG data, *not*
648 base64 encoded.
681 base64 encoded.
649 """
682 """
650 format_type = Unicode('image/jpeg')
683 format_type = Unicode('image/jpeg')
651
684
652 print_method = ObjectName('_repr_jpeg_')
685 print_method = ObjectName('_repr_jpeg_')
653
686
654
687
655 class LatexFormatter(BaseFormatter):
688 class LatexFormatter(BaseFormatter):
656 """A LaTeX formatter.
689 """A LaTeX formatter.
657
690
658 To define the callables that compute the LaTeX representation of your
691 To define the callables that compute the LaTeX representation of your
659 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
692 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
660 or :meth:`for_type_by_name` methods to register functions that handle
693 or :meth:`for_type_by_name` methods to register functions that handle
661 this.
694 this.
662
695
663 The return value of this formatter should be a valid LaTeX equation,
696 The return value of this formatter should be a valid LaTeX equation,
664 enclosed in either ```$```, ```$$``` or another LaTeX equation
697 enclosed in either ```$```, ```$$``` or another LaTeX equation
665 environment.
698 environment.
666 """
699 """
667 format_type = Unicode('text/latex')
700 format_type = Unicode('text/latex')
668
701
669 print_method = ObjectName('_repr_latex_')
702 print_method = ObjectName('_repr_latex_')
670
703
671
704
672 class JSONFormatter(BaseFormatter):
705 class JSONFormatter(BaseFormatter):
673 """A JSON string formatter.
706 """A JSON string formatter.
674
707
675 To define the callables that compute the JSON string representation of
708 To define the callables that compute the JSON string representation of
676 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
709 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
677 or :meth:`for_type_by_name` methods to register functions that handle
710 or :meth:`for_type_by_name` methods to register functions that handle
678 this.
711 this.
679
712
680 The return value of this formatter should be a valid JSON string.
713 The return value of this formatter should be a valid JSON string.
681 """
714 """
682 format_type = Unicode('application/json')
715 format_type = Unicode('application/json')
683
716
684 print_method = ObjectName('_repr_json_')
717 print_method = ObjectName('_repr_json_')
685
718
686
719
687 class JavascriptFormatter(BaseFormatter):
720 class JavascriptFormatter(BaseFormatter):
688 """A Javascript formatter.
721 """A Javascript formatter.
689
722
690 To define the callables that compute the Javascript representation of
723 To define the callables that compute the Javascript representation of
691 your objects, define a :meth:`_repr_javascript_` method or use the
724 your objects, define a :meth:`_repr_javascript_` method or use the
692 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
725 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
693 that handle this.
726 that handle this.
694
727
695 The return value of this formatter should be valid Javascript code and
728 The return value of this formatter should be valid Javascript code and
696 should *not* be enclosed in ```<script>``` tags.
729 should *not* be enclosed in ```<script>``` tags.
697 """
730 """
698 format_type = Unicode('application/javascript')
731 format_type = Unicode('application/javascript')
699
732
700 print_method = ObjectName('_repr_javascript_')
733 print_method = ObjectName('_repr_javascript_')
701
734
702 FormatterABC.register(BaseFormatter)
735 FormatterABC.register(BaseFormatter)
703 FormatterABC.register(PlainTextFormatter)
736 FormatterABC.register(PlainTextFormatter)
704 FormatterABC.register(HTMLFormatter)
737 FormatterABC.register(HTMLFormatter)
705 FormatterABC.register(SVGFormatter)
738 FormatterABC.register(SVGFormatter)
706 FormatterABC.register(PNGFormatter)
739 FormatterABC.register(PNGFormatter)
707 FormatterABC.register(JPEGFormatter)
740 FormatterABC.register(JPEGFormatter)
708 FormatterABC.register(LatexFormatter)
741 FormatterABC.register(LatexFormatter)
709 FormatterABC.register(JSONFormatter)
742 FormatterABC.register(JSONFormatter)
710 FormatterABC.register(JavascriptFormatter)
743 FormatterABC.register(JavascriptFormatter)
711
744
712
745
713 def format_display_data(obj, include=None, exclude=None):
746 def format_display_data(obj, include=None, exclude=None):
714 """Return a format data dict for an object.
747 """Return a format data dict for an object.
715
748
716 By default all format types will be computed.
749 By default all format types will be computed.
717
750
718 The following MIME types are currently implemented:
751 The following MIME types are currently implemented:
719
752
720 * text/plain
753 * text/plain
721 * text/html
754 * text/html
722 * text/latex
755 * text/latex
723 * application/json
756 * application/json
724 * application/javascript
757 * application/javascript
725 * image/png
758 * image/png
726 * image/jpeg
759 * image/jpeg
727 * image/svg+xml
760 * image/svg+xml
728
761
729 Parameters
762 Parameters
730 ----------
763 ----------
731 obj : object
764 obj : object
732 The Python object whose format data will be computed.
765 The Python object whose format data will be computed.
733
766
734 Returns
767 Returns
735 -------
768 -------
736 format_dict : dict
769 format_dict : dict
737 A dictionary of key/value pairs, one or each format that was
770 A dictionary of key/value pairs, one or each format that was
738 generated for the object. The keys are the format types, which
771 generated for the object. The keys are the format types, which
739 will usually be MIME type strings and the values and JSON'able
772 will usually be MIME type strings and the values and JSON'able
740 data structure containing the raw data for the representation in
773 data structure containing the raw data for the representation in
741 that format.
774 that format.
742 include : list or tuple, optional
775 include : list or tuple, optional
743 A list of format type strings (MIME types) to include in the
776 A list of format type strings (MIME types) to include in the
744 format data dict. If this is set *only* the format types included
777 format data dict. If this is set *only* the format types included
745 in this list will be computed.
778 in this list will be computed.
746 exclude : list or tuple, optional
779 exclude : list or tuple, optional
747 A list of format type string (MIME types) to exclue in the format
780 A list of format type string (MIME types) to exclue in the format
748 data dict. If this is set all format types will be computed,
781 data dict. If this is set all format types will be computed,
749 except for those included in this argument.
782 except for those included in this argument.
750 """
783 """
751 from IPython.core.interactiveshell import InteractiveShell
784 from IPython.core.interactiveshell import InteractiveShell
752
785
753 InteractiveShell.instance().display_formatter.format(
786 InteractiveShell.instance().display_formatter.format(
754 obj,
787 obj,
755 include,
788 include,
756 exclude
789 exclude
757 )
790 )
758
791
@@ -1,349 +1,340 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Pylab (matplotlib) support utilities.
2 """Pylab (matplotlib) support utilities.
3
3
4 Authors
4 Authors
5 -------
5 -------
6
6
7 * Fernando Perez.
7 * Fernando Perez.
8 * Brian Granger
8 * Brian Granger
9 """
9 """
10 from __future__ import print_function
10 from __future__ import print_function
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2009 The IPython Development Team
13 # Copyright (C) 2009 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import sys
23 import sys
24 from io import BytesIO
24 from io import BytesIO
25
25
26 from IPython.core.display import _pngxy
26 from IPython.core.display import _pngxy
27 from IPython.utils.decorators import flag_calls
27 from IPython.utils.decorators import flag_calls
28
28
29 # If user specifies a GUI, that dictates the backend, otherwise we read the
29 # If user specifies a GUI, that dictates the backend, otherwise we read the
30 # user's mpl default from the mpl rc structure
30 # user's mpl default from the mpl rc structure
31 backends = {'tk': 'TkAgg',
31 backends = {'tk': 'TkAgg',
32 'gtk': 'GTKAgg',
32 'gtk': 'GTKAgg',
33 'wx': 'WXAgg',
33 'wx': 'WXAgg',
34 'qt': 'Qt4Agg', # qt3 not supported
34 'qt': 'Qt4Agg', # qt3 not supported
35 'qt4': 'Qt4Agg',
35 'qt4': 'Qt4Agg',
36 'osx': 'MacOSX',
36 'osx': 'MacOSX',
37 'inline' : 'module://IPython.kernel.zmq.pylab.backend_inline'}
37 'inline' : 'module://IPython.kernel.zmq.pylab.backend_inline'}
38
38
39 # We also need a reverse backends2guis mapping that will properly choose which
39 # We also need a reverse backends2guis mapping that will properly choose which
40 # GUI support to activate based on the desired matplotlib backend. For the
40 # GUI support to activate based on the desired matplotlib backend. For the
41 # most part it's just a reverse of the above dict, but we also need to add a
41 # most part it's just a reverse of the above dict, but we also need to add a
42 # few others that map to the same GUI manually:
42 # few others that map to the same GUI manually:
43 backend2gui = dict(zip(backends.values(), backends.keys()))
43 backend2gui = dict(zip(backends.values(), backends.keys()))
44 # Our tests expect backend2gui to just return 'qt'
44 # Our tests expect backend2gui to just return 'qt'
45 backend2gui['Qt4Agg'] = 'qt'
45 backend2gui['Qt4Agg'] = 'qt'
46 # In the reverse mapping, there are a few extra valid matplotlib backends that
46 # In the reverse mapping, there are a few extra valid matplotlib backends that
47 # map to the same GUI support
47 # map to the same GUI support
48 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
48 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
49 backend2gui['WX'] = 'wx'
49 backend2gui['WX'] = 'wx'
50 backend2gui['CocoaAgg'] = 'osx'
50 backend2gui['CocoaAgg'] = 'osx'
51
51
52 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
53 # Matplotlib utilities
53 # Matplotlib utilities
54 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
55
55
56
56
57 def getfigs(*fig_nums):
57 def getfigs(*fig_nums):
58 """Get a list of matplotlib figures by figure numbers.
58 """Get a list of matplotlib figures by figure numbers.
59
59
60 If no arguments are given, all available figures are returned. If the
60 If no arguments are given, all available figures are returned. If the
61 argument list contains references to invalid figures, a warning is printed
61 argument list contains references to invalid figures, a warning is printed
62 but the function continues pasting further figures.
62 but the function continues pasting further figures.
63
63
64 Parameters
64 Parameters
65 ----------
65 ----------
66 figs : tuple
66 figs : tuple
67 A tuple of ints giving the figure numbers of the figures to return.
67 A tuple of ints giving the figure numbers of the figures to return.
68 """
68 """
69 from matplotlib._pylab_helpers import Gcf
69 from matplotlib._pylab_helpers import Gcf
70 if not fig_nums:
70 if not fig_nums:
71 fig_managers = Gcf.get_all_fig_managers()
71 fig_managers = Gcf.get_all_fig_managers()
72 return [fm.canvas.figure for fm in fig_managers]
72 return [fm.canvas.figure for fm in fig_managers]
73 else:
73 else:
74 figs = []
74 figs = []
75 for num in fig_nums:
75 for num in fig_nums:
76 f = Gcf.figs.get(num)
76 f = Gcf.figs.get(num)
77 if f is None:
77 if f is None:
78 print('Warning: figure %s not available.' % num)
78 print('Warning: figure %s not available.' % num)
79 else:
79 else:
80 figs.append(f.canvas.figure)
80 figs.append(f.canvas.figure)
81 return figs
81 return figs
82
82
83
83
84 def figsize(sizex, sizey):
84 def figsize(sizex, sizey):
85 """Set the default figure size to be [sizex, sizey].
85 """Set the default figure size to be [sizex, sizey].
86
86
87 This is just an easy to remember, convenience wrapper that sets::
87 This is just an easy to remember, convenience wrapper that sets::
88
88
89 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
89 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
90 """
90 """
91 import matplotlib
91 import matplotlib
92 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
92 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
93
93
94
94
95 def print_figure(fig, fmt='png'):
95 def print_figure(fig, fmt='png'):
96 """Convert a figure to svg or png for inline display."""
96 """Convert a figure to svg or png for inline display."""
97 from matplotlib import rcParams
97 from matplotlib import rcParams
98 # When there's an empty figure, we shouldn't return anything, otherwise we
98 # When there's an empty figure, we shouldn't return anything, otherwise we
99 # get big blank areas in the qt console.
99 # get big blank areas in the qt console.
100 if not fig.axes and not fig.lines:
100 if not fig.axes and not fig.lines:
101 return
101 return
102
102
103 fc = fig.get_facecolor()
103 fc = fig.get_facecolor()
104 ec = fig.get_edgecolor()
104 ec = fig.get_edgecolor()
105 bytes_io = BytesIO()
105 bytes_io = BytesIO()
106 dpi = rcParams['savefig.dpi']
106 dpi = rcParams['savefig.dpi']
107 if fmt == 'retina':
107 if fmt == 'retina':
108 dpi = dpi * 2
108 dpi = dpi * 2
109 fmt = 'png'
109 fmt = 'png'
110 fig.canvas.print_figure(bytes_io, format=fmt, bbox_inches='tight',
110 fig.canvas.print_figure(bytes_io, format=fmt, bbox_inches='tight',
111 facecolor=fc, edgecolor=ec, dpi=dpi)
111 facecolor=fc, edgecolor=ec, dpi=dpi)
112 data = bytes_io.getvalue()
112 data = bytes_io.getvalue()
113 return data
113 return data
114
114
115 def retina_figure(fig):
115 def retina_figure(fig):
116 """format a figure as a pixel-doubled (retina) PNG"""
116 """format a figure as a pixel-doubled (retina) PNG"""
117 pngdata = print_figure(fig, fmt='retina')
117 pngdata = print_figure(fig, fmt='retina')
118 w, h = _pngxy(pngdata)
118 w, h = _pngxy(pngdata)
119 metadata = dict(width=w//2, height=h//2)
119 metadata = dict(width=w//2, height=h//2)
120 return pngdata, metadata
120 return pngdata, metadata
121
121
122 # We need a little factory function here to create the closure where
122 # We need a little factory function here to create the closure where
123 # safe_execfile can live.
123 # safe_execfile can live.
124 def mpl_runner(safe_execfile):
124 def mpl_runner(safe_execfile):
125 """Factory to return a matplotlib-enabled runner for %run.
125 """Factory to return a matplotlib-enabled runner for %run.
126
126
127 Parameters
127 Parameters
128 ----------
128 ----------
129 safe_execfile : function
129 safe_execfile : function
130 This must be a function with the same interface as the
130 This must be a function with the same interface as the
131 :meth:`safe_execfile` method of IPython.
131 :meth:`safe_execfile` method of IPython.
132
132
133 Returns
133 Returns
134 -------
134 -------
135 A function suitable for use as the ``runner`` argument of the %run magic
135 A function suitable for use as the ``runner`` argument of the %run magic
136 function.
136 function.
137 """
137 """
138
138
139 def mpl_execfile(fname,*where,**kw):
139 def mpl_execfile(fname,*where,**kw):
140 """matplotlib-aware wrapper around safe_execfile.
140 """matplotlib-aware wrapper around safe_execfile.
141
141
142 Its interface is identical to that of the :func:`execfile` builtin.
142 Its interface is identical to that of the :func:`execfile` builtin.
143
143
144 This is ultimately a call to execfile(), but wrapped in safeties to
144 This is ultimately a call to execfile(), but wrapped in safeties to
145 properly handle interactive rendering."""
145 properly handle interactive rendering."""
146
146
147 import matplotlib
147 import matplotlib
148 import matplotlib.pylab as pylab
148 import matplotlib.pylab as pylab
149
149
150 #print '*** Matplotlib runner ***' # dbg
150 #print '*** Matplotlib runner ***' # dbg
151 # turn off rendering until end of script
151 # turn off rendering until end of script
152 is_interactive = matplotlib.rcParams['interactive']
152 is_interactive = matplotlib.rcParams['interactive']
153 matplotlib.interactive(False)
153 matplotlib.interactive(False)
154 safe_execfile(fname,*where,**kw)
154 safe_execfile(fname,*where,**kw)
155 matplotlib.interactive(is_interactive)
155 matplotlib.interactive(is_interactive)
156 # make rendering call now, if the user tried to do it
156 # make rendering call now, if the user tried to do it
157 if pylab.draw_if_interactive.called:
157 if pylab.draw_if_interactive.called:
158 pylab.draw()
158 pylab.draw()
159 pylab.draw_if_interactive.called = False
159 pylab.draw_if_interactive.called = False
160
160
161 return mpl_execfile
161 return mpl_execfile
162
162
163
163
164 def select_figure_format(shell, fmt):
164 def select_figure_format(shell, fmt):
165 """Select figure format for inline backend, can be 'png', 'retina', or 'svg'.
165 """Select figure format for inline backend, can be 'png', 'retina', or 'svg'.
166
166
167 Using this method ensures only one figure format is active at a time.
167 Using this method ensures only one figure format is active at a time.
168 """
168 """
169 from matplotlib.figure import Figure
169 from matplotlib.figure import Figure
170 from IPython.kernel.zmq.pylab import backend_inline
170 from IPython.kernel.zmq.pylab import backend_inline
171
171
172 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
172 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
173 png_formatter = shell.display_formatter.formatters['image/png']
173 png_formatter = shell.display_formatter.formatters['image/png']
174
174
175 if fmt == 'png':
175 if fmt == 'png':
176 try:
176 svg_formatter.pop(Figure, None)
177 svg_formatter.pop(Figure)
178 except KeyError:
179 pass
180 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png'))
177 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png'))
181 elif fmt in ('png2x', 'retina'):
178 elif fmt in ('png2x', 'retina'):
182 try:
179 svg_formatter.pop(Figure, None)
183 svg_formatter.pop(Figure)
184 except KeyError:
185 pass
186 png_formatter.for_type(Figure, retina_figure)
180 png_formatter.for_type(Figure, retina_figure)
187 elif fmt == 'svg':
181 elif fmt == 'svg':
188 try:
182 png_formatter.pop(Figure, None)
189 svg_formatter.pop(Figure)
190 except KeyError:
191 pass
192 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg'))
183 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg'))
193 else:
184 else:
194 raise ValueError("supported formats are: 'png', 'retina', 'svg', not %r" % fmt)
185 raise ValueError("supported formats are: 'png', 'retina', 'svg', not %r" % fmt)
195
186
196 # set the format to be used in the backend()
187 # set the format to be used in the backend()
197 backend_inline._figure_format = fmt
188 backend_inline._figure_format = fmt
198
189
199 #-----------------------------------------------------------------------------
190 #-----------------------------------------------------------------------------
200 # Code for initializing matplotlib and importing pylab
191 # Code for initializing matplotlib and importing pylab
201 #-----------------------------------------------------------------------------
192 #-----------------------------------------------------------------------------
202
193
203
194
204 def find_gui_and_backend(gui=None, gui_select=None):
195 def find_gui_and_backend(gui=None, gui_select=None):
205 """Given a gui string return the gui and mpl backend.
196 """Given a gui string return the gui and mpl backend.
206
197
207 Parameters
198 Parameters
208 ----------
199 ----------
209 gui : str
200 gui : str
210 Can be one of ('tk','gtk','wx','qt','qt4','inline').
201 Can be one of ('tk','gtk','wx','qt','qt4','inline').
211 gui_select : str
202 gui_select : str
212 Can be one of ('tk','gtk','wx','qt','qt4','inline').
203 Can be one of ('tk','gtk','wx','qt','qt4','inline').
213 This is any gui already selected by the shell.
204 This is any gui already selected by the shell.
214
205
215 Returns
206 Returns
216 -------
207 -------
217 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
208 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
218 'WXAgg','Qt4Agg','module://IPython.kernel.zmq.pylab.backend_inline').
209 'WXAgg','Qt4Agg','module://IPython.kernel.zmq.pylab.backend_inline').
219 """
210 """
220
211
221 import matplotlib
212 import matplotlib
222
213
223 if gui and gui != 'auto':
214 if gui and gui != 'auto':
224 # select backend based on requested gui
215 # select backend based on requested gui
225 backend = backends[gui]
216 backend = backends[gui]
226 else:
217 else:
227 # We need to read the backend from the original data structure, *not*
218 # We need to read the backend from the original data structure, *not*
228 # from mpl.rcParams, since a prior invocation of %matplotlib may have
219 # from mpl.rcParams, since a prior invocation of %matplotlib may have
229 # overwritten that.
220 # overwritten that.
230 # WARNING: this assumes matplotlib 1.1 or newer!!
221 # WARNING: this assumes matplotlib 1.1 or newer!!
231 backend = matplotlib.rcParamsOrig['backend']
222 backend = matplotlib.rcParamsOrig['backend']
232 # In this case, we need to find what the appropriate gui selection call
223 # In this case, we need to find what the appropriate gui selection call
233 # should be for IPython, so we can activate inputhook accordingly
224 # should be for IPython, so we can activate inputhook accordingly
234 gui = backend2gui.get(backend, None)
225 gui = backend2gui.get(backend, None)
235
226
236 # If we have already had a gui active, we need it and inline are the
227 # If we have already had a gui active, we need it and inline are the
237 # ones allowed.
228 # ones allowed.
238 if gui_select and gui != gui_select:
229 if gui_select and gui != gui_select:
239 gui = gui_select
230 gui = gui_select
240 backend = backends[gui]
231 backend = backends[gui]
241
232
242 return gui, backend
233 return gui, backend
243
234
244
235
245 def activate_matplotlib(backend):
236 def activate_matplotlib(backend):
246 """Activate the given backend and set interactive to True."""
237 """Activate the given backend and set interactive to True."""
247
238
248 import matplotlib
239 import matplotlib
249 matplotlib.interactive(True)
240 matplotlib.interactive(True)
250
241
251 # Matplotlib had a bug where even switch_backend could not force
242 # Matplotlib had a bug where even switch_backend could not force
252 # the rcParam to update. This needs to be set *before* the module
243 # the rcParam to update. This needs to be set *before* the module
253 # magic of switch_backend().
244 # magic of switch_backend().
254 matplotlib.rcParams['backend'] = backend
245 matplotlib.rcParams['backend'] = backend
255
246
256 import matplotlib.pyplot
247 import matplotlib.pyplot
257 matplotlib.pyplot.switch_backend(backend)
248 matplotlib.pyplot.switch_backend(backend)
258
249
259 # This must be imported last in the matplotlib series, after
250 # This must be imported last in the matplotlib series, after
260 # backend/interactivity choices have been made
251 # backend/interactivity choices have been made
261 import matplotlib.pylab as pylab
252 import matplotlib.pylab as pylab
262
253
263 pylab.show._needmain = False
254 pylab.show._needmain = False
264 # We need to detect at runtime whether show() is called by the user.
255 # We need to detect at runtime whether show() is called by the user.
265 # For this, we wrap it into a decorator which adds a 'called' flag.
256 # For this, we wrap it into a decorator which adds a 'called' flag.
266 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
257 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
267
258
268
259
269 def import_pylab(user_ns, import_all=True):
260 def import_pylab(user_ns, import_all=True):
270 """Populate the namespace with pylab-related values.
261 """Populate the namespace with pylab-related values.
271
262
272 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
263 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
273
264
274 Also imports a few names from IPython (figsize, display, getfigs)
265 Also imports a few names from IPython (figsize, display, getfigs)
275
266
276 """
267 """
277
268
278 # Import numpy as np/pyplot as plt are conventions we're trying to
269 # Import numpy as np/pyplot as plt are conventions we're trying to
279 # somewhat standardize on. Making them available to users by default
270 # somewhat standardize on. Making them available to users by default
280 # will greatly help this.
271 # will greatly help this.
281 s = ("import numpy\n"
272 s = ("import numpy\n"
282 "import matplotlib\n"
273 "import matplotlib\n"
283 "from matplotlib import pylab, mlab, pyplot\n"
274 "from matplotlib import pylab, mlab, pyplot\n"
284 "np = numpy\n"
275 "np = numpy\n"
285 "plt = pyplot\n"
276 "plt = pyplot\n"
286 )
277 )
287 exec(s, user_ns)
278 exec(s, user_ns)
288
279
289 if import_all:
280 if import_all:
290 s = ("from matplotlib.pylab import *\n"
281 s = ("from matplotlib.pylab import *\n"
291 "from numpy import *\n")
282 "from numpy import *\n")
292 exec(s, user_ns)
283 exec(s, user_ns)
293
284
294 # IPython symbols to add
285 # IPython symbols to add
295 user_ns['figsize'] = figsize
286 user_ns['figsize'] = figsize
296 from IPython.core.display import display
287 from IPython.core.display import display
297 # Add display and getfigs to the user's namespace
288 # Add display and getfigs to the user's namespace
298 user_ns['display'] = display
289 user_ns['display'] = display
299 user_ns['getfigs'] = getfigs
290 user_ns['getfigs'] = getfigs
300
291
301
292
302 def configure_inline_support(shell, backend):
293 def configure_inline_support(shell, backend):
303 """Configure an IPython shell object for matplotlib use.
294 """Configure an IPython shell object for matplotlib use.
304
295
305 Parameters
296 Parameters
306 ----------
297 ----------
307 shell : InteractiveShell instance
298 shell : InteractiveShell instance
308
299
309 backend : matplotlib backend
300 backend : matplotlib backend
310 """
301 """
311 # If using our svg payload backend, register the post-execution
302 # If using our svg payload backend, register the post-execution
312 # function that will pick up the results for display. This can only be
303 # function that will pick up the results for display. This can only be
313 # done with access to the real shell object.
304 # done with access to the real shell object.
314
305
315 # Note: if we can't load the inline backend, then there's no point
306 # Note: if we can't load the inline backend, then there's no point
316 # continuing (such as in terminal-only shells in environments without
307 # continuing (such as in terminal-only shells in environments without
317 # zeromq available).
308 # zeromq available).
318 try:
309 try:
319 from IPython.kernel.zmq.pylab.backend_inline import InlineBackend
310 from IPython.kernel.zmq.pylab.backend_inline import InlineBackend
320 except ImportError:
311 except ImportError:
321 return
312 return
322 from matplotlib import pyplot
313 from matplotlib import pyplot
323
314
324 cfg = InlineBackend.instance(parent=shell)
315 cfg = InlineBackend.instance(parent=shell)
325 cfg.shell = shell
316 cfg.shell = shell
326 if cfg not in shell.configurables:
317 if cfg not in shell.configurables:
327 shell.configurables.append(cfg)
318 shell.configurables.append(cfg)
328
319
329 if backend == backends['inline']:
320 if backend == backends['inline']:
330 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
321 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
331 shell.register_post_execute(flush_figures)
322 shell.register_post_execute(flush_figures)
332
323
333 # Save rcParams that will be overwrittern
324 # Save rcParams that will be overwrittern
334 shell._saved_rcParams = dict()
325 shell._saved_rcParams = dict()
335 for k in cfg.rc:
326 for k in cfg.rc:
336 shell._saved_rcParams[k] = pyplot.rcParams[k]
327 shell._saved_rcParams[k] = pyplot.rcParams[k]
337 # load inline_rc
328 # load inline_rc
338 pyplot.rcParams.update(cfg.rc)
329 pyplot.rcParams.update(cfg.rc)
339 else:
330 else:
340 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
331 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
341 if flush_figures in shell._post_execute:
332 if flush_figures in shell._post_execute:
342 shell._post_execute.pop(flush_figures)
333 shell._post_execute.pop(flush_figures)
343 if hasattr(shell, '_saved_rcParams'):
334 if hasattr(shell, '_saved_rcParams'):
344 pyplot.rcParams.update(shell._saved_rcParams)
335 pyplot.rcParams.update(shell._saved_rcParams)
345 del shell._saved_rcParams
336 del shell._saved_rcParams
346
337
347 # Setup the default figure format
338 # Setup the default figure format
348 select_figure_format(shell, cfg.figure_format)
339 select_figure_format(shell, cfg.figure_format)
349
340
@@ -1,210 +1,234 b''
1 """Tests for the Formatters.
1 """Tests for the Formatters.
2 """
2 """
3
3
4 from math import pi
4 from math import pi
5
5
6 try:
6 try:
7 import numpy
7 import numpy
8 except:
8 except:
9 numpy = None
9 numpy = None
10 import nose.tools as nt
10 import nose.tools as nt
11
11
12 from IPython.core.formatters import PlainTextFormatter, _mod_name_key
12 from IPython.core.formatters import PlainTextFormatter, _mod_name_key
13
13
14 class A(object):
14 class A(object):
15 def __repr__(self):
15 def __repr__(self):
16 return 'A()'
16 return 'A()'
17
17
18 class B(A):
18 class B(A):
19 def __repr__(self):
19 def __repr__(self):
20 return 'B()'
20 return 'B()'
21
21
22 class C:
22 class C:
23 pass
23 pass
24
24
25 class BadPretty(object):
25 class BadPretty(object):
26 _repr_pretty_ = None
26 _repr_pretty_ = None
27
27
28 class GoodPretty(object):
28 class GoodPretty(object):
29 def _repr_pretty_(self, pp, cycle):
29 def _repr_pretty_(self, pp, cycle):
30 pp.text('foo')
30 pp.text('foo')
31
31
32 def __repr__(self):
32 def __repr__(self):
33 return 'GoodPretty()'
33 return 'GoodPretty()'
34
34
35 def foo_printer(obj, pp, cycle):
35 def foo_printer(obj, pp, cycle):
36 pp.text('foo')
36 pp.text('foo')
37
37
38 def test_pretty():
38 def test_pretty():
39 f = PlainTextFormatter()
39 f = PlainTextFormatter()
40 f.for_type(A, foo_printer)
40 f.for_type(A, foo_printer)
41 nt.assert_equal(f(A()), 'foo')
41 nt.assert_equal(f(A()), 'foo')
42 nt.assert_equal(f(B()), 'foo')
42 nt.assert_equal(f(B()), 'foo')
43 nt.assert_equal(f(GoodPretty()), 'foo')
43 nt.assert_equal(f(GoodPretty()), 'foo')
44 # Just don't raise an exception for the following:
44 # Just don't raise an exception for the following:
45 f(BadPretty())
45 f(BadPretty())
46
46
47 f.pprint = False
47 f.pprint = False
48 nt.assert_equal(f(A()), 'A()')
48 nt.assert_equal(f(A()), 'A()')
49 nt.assert_equal(f(B()), 'B()')
49 nt.assert_equal(f(B()), 'B()')
50 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
50 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
51
51
52
52
53 def test_deferred():
53 def test_deferred():
54 f = PlainTextFormatter()
54 f = PlainTextFormatter()
55
55
56 def test_precision():
56 def test_precision():
57 """test various values for float_precision."""
57 """test various values for float_precision."""
58 f = PlainTextFormatter()
58 f = PlainTextFormatter()
59 nt.assert_equal(f(pi), repr(pi))
59 nt.assert_equal(f(pi), repr(pi))
60 f.float_precision = 0
60 f.float_precision = 0
61 if numpy:
61 if numpy:
62 po = numpy.get_printoptions()
62 po = numpy.get_printoptions()
63 nt.assert_equal(po['precision'], 0)
63 nt.assert_equal(po['precision'], 0)
64 nt.assert_equal(f(pi), '3')
64 nt.assert_equal(f(pi), '3')
65 f.float_precision = 2
65 f.float_precision = 2
66 if numpy:
66 if numpy:
67 po = numpy.get_printoptions()
67 po = numpy.get_printoptions()
68 nt.assert_equal(po['precision'], 2)
68 nt.assert_equal(po['precision'], 2)
69 nt.assert_equal(f(pi), '3.14')
69 nt.assert_equal(f(pi), '3.14')
70 f.float_precision = '%g'
70 f.float_precision = '%g'
71 if numpy:
71 if numpy:
72 po = numpy.get_printoptions()
72 po = numpy.get_printoptions()
73 nt.assert_equal(po['precision'], 2)
73 nt.assert_equal(po['precision'], 2)
74 nt.assert_equal(f(pi), '3.14159')
74 nt.assert_equal(f(pi), '3.14159')
75 f.float_precision = '%e'
75 f.float_precision = '%e'
76 nt.assert_equal(f(pi), '3.141593e+00')
76 nt.assert_equal(f(pi), '3.141593e+00')
77 f.float_precision = ''
77 f.float_precision = ''
78 if numpy:
78 if numpy:
79 po = numpy.get_printoptions()
79 po = numpy.get_printoptions()
80 nt.assert_equal(po['precision'], 8)
80 nt.assert_equal(po['precision'], 8)
81 nt.assert_equal(f(pi), repr(pi))
81 nt.assert_equal(f(pi), repr(pi))
82
82
83 def test_bad_precision():
83 def test_bad_precision():
84 """test various invalid values for float_precision."""
84 """test various invalid values for float_precision."""
85 f = PlainTextFormatter()
85 f = PlainTextFormatter()
86 def set_fp(p):
86 def set_fp(p):
87 f.float_precision=p
87 f.float_precision=p
88 nt.assert_raises(ValueError, set_fp, '%')
88 nt.assert_raises(ValueError, set_fp, '%')
89 nt.assert_raises(ValueError, set_fp, '%.3f%i')
89 nt.assert_raises(ValueError, set_fp, '%.3f%i')
90 nt.assert_raises(ValueError, set_fp, 'foo')
90 nt.assert_raises(ValueError, set_fp, 'foo')
91 nt.assert_raises(ValueError, set_fp, -1)
91 nt.assert_raises(ValueError, set_fp, -1)
92
92
93 def test_for_type():
93 def test_for_type():
94 f = PlainTextFormatter()
94 f = PlainTextFormatter()
95
95
96 # initial return, None
96 # initial return, None
97 nt.assert_is(f.for_type(C, foo_printer), None)
97 nt.assert_is(f.for_type(C, foo_printer), None)
98 # no func queries
98 # no func queries
99 nt.assert_is(f.for_type(C), foo_printer)
99 nt.assert_is(f.for_type(C), foo_printer)
100 # shouldn't change anything
100 # shouldn't change anything
101 nt.assert_is(f.for_type(C), foo_printer)
101 nt.assert_is(f.for_type(C), foo_printer)
102 # None should do the same
102 # None should do the same
103 nt.assert_is(f.for_type(C, None), foo_printer)
103 nt.assert_is(f.for_type(C, None), foo_printer)
104 nt.assert_is(f.for_type(C, None), foo_printer)
104 nt.assert_is(f.for_type(C, None), foo_printer)
105
105
106 def test_for_type_string():
106 def test_for_type_string():
107 f = PlainTextFormatter()
107 f = PlainTextFormatter()
108
108
109 mod = C.__module__
109 mod = C.__module__
110
110
111 type_str = '%s.%s' % (C.__module__, 'C')
111 type_str = '%s.%s' % (C.__module__, 'C')
112
112
113 # initial return, None
113 # initial return, None
114 nt.assert_is(f.for_type(type_str, foo_printer), None)
114 nt.assert_is(f.for_type(type_str, foo_printer), None)
115 # no func queries
115 # no func queries
116 nt.assert_is(f.for_type(type_str), foo_printer)
116 nt.assert_is(f.for_type(type_str), foo_printer)
117 nt.assert_in(_mod_name_key(C), f.deferred_printers)
117 nt.assert_in(_mod_name_key(C), f.deferred_printers)
118 nt.assert_is(f.for_type(C), foo_printer)
118 nt.assert_is(f.for_type(C), foo_printer)
119 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
119 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
120 nt.assert_in(C, f.type_printers)
120 nt.assert_in(C, f.type_printers)
121
121
122 def test_for_type_by_name():
122 def test_for_type_by_name():
123 f = PlainTextFormatter()
123 f = PlainTextFormatter()
124
124
125 mod = C.__module__
125 mod = C.__module__
126
126
127 # initial return, None
127 # initial return, None
128 nt.assert_is(f.for_type_by_name(mod, 'C', foo_printer), None)
128 nt.assert_is(f.for_type_by_name(mod, 'C', foo_printer), None)
129 # no func queries
129 # no func queries
130 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
130 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
131 # shouldn't change anything
131 # shouldn't change anything
132 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
132 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
133 # None should do the same
133 # None should do the same
134 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
134 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
135 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
135 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
136
136
137 def test_lookup():
137 def test_lookup():
138 f = PlainTextFormatter()
138 f = PlainTextFormatter()
139
139
140 f.for_type(C, foo_printer)
140 f.for_type(C, foo_printer)
141 nt.assert_is(f.lookup(C()), foo_printer)
141 nt.assert_is(f.lookup(C()), foo_printer)
142 with nt.assert_raises(KeyError):
142 with nt.assert_raises(KeyError):
143 f.lookup(A())
143 f.lookup(A())
144
144
145 def test_lookup_string():
145 def test_lookup_string():
146 f = PlainTextFormatter()
146 f = PlainTextFormatter()
147 type_str = '%s.%s' % (C.__module__, 'C')
147 type_str = '%s.%s' % (C.__module__, 'C')
148
148
149 f.for_type(type_str, foo_printer)
149 f.for_type(type_str, foo_printer)
150 nt.assert_is(f.lookup(C()), foo_printer)
150 nt.assert_is(f.lookup(C()), foo_printer)
151 # should move from deferred to imported dict
151 # should move from deferred to imported dict
152 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
152 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
153 nt.assert_in(C, f.type_printers)
153 nt.assert_in(C, f.type_printers)
154
154
155 def test_lookup_by_type():
155 def test_lookup_by_type():
156 f = PlainTextFormatter()
156 f = PlainTextFormatter()
157 f.for_type(C, foo_printer)
157 f.for_type(C, foo_printer)
158 nt.assert_is(f.lookup_by_type(C), foo_printer)
158 nt.assert_is(f.lookup_by_type(C), foo_printer)
159 type_str = '%s.%s' % (C.__module__, 'C')
159 type_str = '%s.%s' % (C.__module__, 'C')
160 with nt.assert_raises(KeyError):
160 with nt.assert_raises(KeyError):
161 f.lookup_by_type(A)
161 f.lookup_by_type(A)
162
162
163 def test_lookup_by_type_string():
163 def test_lookup_by_type_string():
164 f = PlainTextFormatter()
164 f = PlainTextFormatter()
165 type_str = '%s.%s' % (C.__module__, 'C')
165 type_str = '%s.%s' % (C.__module__, 'C')
166 f.for_type(type_str, foo_printer)
166 f.for_type(type_str, foo_printer)
167
167
168 # verify insertion
168 # verify insertion
169 nt.assert_in(_mod_name_key(C), f.deferred_printers)
169 nt.assert_in(_mod_name_key(C), f.deferred_printers)
170 nt.assert_not_in(C, f.type_printers)
170 nt.assert_not_in(C, f.type_printers)
171
171
172 nt.assert_is(f.lookup_by_type(type_str), foo_printer)
173 # lookup by string doesn't cause import
174 nt.assert_in(_mod_name_key(C), f.deferred_printers)
175 nt.assert_not_in(C, f.type_printers)
176
172 nt.assert_is(f.lookup_by_type(C), foo_printer)
177 nt.assert_is(f.lookup_by_type(C), foo_printer)
173 # should move from deferred to imported dict
178 # should move from deferred to imported dict
174 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
179 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
175 nt.assert_in(C, f.type_printers)
180 nt.assert_in(C, f.type_printers)
176
181
182 def test_in_formatter():
183 f = PlainTextFormatter()
184 f.for_type(C, foo_printer)
185 type_str = '%s.%s' % (C.__module__, 'C')
186 nt.assert_in(C, f)
187 nt.assert_in(type_str, f)
188
189 def test_string_in_formatter():
190 f = PlainTextFormatter()
191 type_str = '%s.%s' % (C.__module__, 'C')
192 f.for_type(type_str, foo_printer)
193 nt.assert_in(type_str, f)
194 nt.assert_in(C, f)
195
177 def test_pop():
196 def test_pop():
178 f = PlainTextFormatter()
197 f = PlainTextFormatter()
179 f.for_type(C, foo_printer)
198 f.for_type(C, foo_printer)
180 nt.assert_is(f.lookup_by_type(C), foo_printer)
199 nt.assert_is(f.lookup_by_type(C), foo_printer)
181 f.pop(C)
200 nt.assert_is(f.pop(C, None), foo_printer)
201 f.for_type(C, foo_printer)
202 nt.assert_is(f.pop(C), foo_printer)
182 with nt.assert_raises(KeyError):
203 with nt.assert_raises(KeyError):
183 f.lookup_by_type(C)
204 f.lookup_by_type(C)
184 with nt.assert_raises(KeyError):
205 with nt.assert_raises(KeyError):
185 f.pop(C)
206 f.pop(C)
186 with nt.assert_raises(KeyError):
207 with nt.assert_raises(KeyError):
187 f.pop(A)
208 f.pop(A)
209 nt.assert_is(f.pop(A, None), None)
188
210
189 def test_pop_string():
211 def test_pop_string():
190 f = PlainTextFormatter()
212 f = PlainTextFormatter()
191 type_str = '%s.%s' % (C.__module__, 'C')
213 type_str = '%s.%s' % (C.__module__, 'C')
192
214
193 with nt.assert_raises(KeyError):
215 with nt.assert_raises(KeyError):
194 f.pop(type_str)
216 f.pop(type_str)
195
217
196 f.for_type(type_str, foo_printer)
218 f.for_type(type_str, foo_printer)
197 f.pop(type_str)
219 f.pop(type_str)
198 with nt.assert_raises(KeyError):
220 with nt.assert_raises(KeyError):
199 f.lookup_by_type(C)
221 f.lookup_by_type(C)
200 with nt.assert_raises(KeyError):
222 with nt.assert_raises(KeyError):
201 f.pop(type_str)
223 f.pop(type_str)
202
224
203 f.for_type(C, foo_printer)
225 f.for_type(C, foo_printer)
204 f.pop(type_str)
226 nt.assert_is(f.pop(type_str, None), foo_printer)
205 with nt.assert_raises(KeyError):
227 with nt.assert_raises(KeyError):
206 f.lookup_by_type(C)
228 f.lookup_by_type(C)
207 with nt.assert_raises(KeyError):
229 with nt.assert_raises(KeyError):
208 f.pop(type_str)
230 f.pop(type_str)
231 nt.assert_is(f.pop(type_str, None), None)
232
209
233
210
234
General Comments 0
You need to be logged in to leave comments. Login now