##// END OF EJS Templates
use real Warnings for formatter errors...
MinRK -
Show More
@@ -1,819 +1,825 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 from IPython.external.decorator import decorator
31 from IPython.external.decorator import decorator
32
32
33 # Our own imports
33 # Our own imports
34 from IPython.config.configurable import Configurable
34 from IPython.config.configurable import Configurable
35 from IPython.lib import pretty
35 from IPython.lib import pretty
36 from IPython.utils import io
36 from IPython.utils import io
37 from IPython.utils.traitlets import (
37 from IPython.utils.traitlets import (
38 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
38 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
39 )
39 )
40 from IPython.utils.warn import warn
40 from IPython.utils.warn import warn
41 from IPython.utils.py3compat import (
41 from IPython.utils.py3compat import (
42 unicode_to_str, with_metaclass, PY3, string_types, unicode_type,
42 unicode_to_str, with_metaclass, PY3, string_types, unicode_type,
43 )
43 )
44
44
45 if PY3:
45 if PY3:
46 from io import StringIO
46 from io import StringIO
47 else:
47 else:
48 from StringIO import StringIO
48 from StringIO import StringIO
49
49
50
50
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52 # The main DisplayFormatter class
52 # The main DisplayFormatter class
53 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
54
54
55 class DisplayFormatter(Configurable):
55 class DisplayFormatter(Configurable):
56
56
57 # When set to true only the default plain text formatter will be used.
57 # When set to true only the default plain text formatter will be used.
58 plain_text_only = Bool(False, config=True)
58 plain_text_only = Bool(False, config=True)
59 def _plain_text_only_changed(self, name, old, new):
59 def _plain_text_only_changed(self, name, old, new):
60 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
60 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
61
61
62 Use DisplayFormatter.active_types = ['text/plain']
62 Use DisplayFormatter.active_types = ['text/plain']
63 for the same effect.
63 for the same effect.
64 """, DeprecationWarning)
64 """, DeprecationWarning)
65 if new:
65 if new:
66 self.active_types = ['text/plain']
66 self.active_types = ['text/plain']
67 else:
67 else:
68 self.active_types = self.format_types
68 self.active_types = self.format_types
69
69
70 active_types = List(Unicode, config=True,
70 active_types = List(Unicode, config=True,
71 help="""List of currently active mime-types to display.
71 help="""List of currently active mime-types to display.
72 You can use this to set a white-list for formats to display.
72 You can use this to set a white-list for formats to display.
73
73
74 Most users will not need to change this value.
74 Most users will not need to change this value.
75 """)
75 """)
76 def _active_types_default(self):
76 def _active_types_default(self):
77 return self.format_types
77 return self.format_types
78
78
79 def _active_types_changed(self, name, old, new):
79 def _active_types_changed(self, name, old, new):
80 for key, formatter in self.formatters.items():
80 for key, formatter in self.formatters.items():
81 if key in new:
81 if key in new:
82 formatter.enabled = True
82 formatter.enabled = True
83 else:
83 else:
84 formatter.enabled = False
84 formatter.enabled = False
85
85
86 # A dict of formatter whose keys are format types (MIME types) and whose
86 # A dict of formatter whose keys are format types (MIME types) and whose
87 # values are subclasses of BaseFormatter.
87 # values are subclasses of BaseFormatter.
88 formatters = Dict()
88 formatters = Dict()
89 def _formatters_default(self):
89 def _formatters_default(self):
90 """Activate the default formatters."""
90 """Activate the default formatters."""
91 formatter_classes = [
91 formatter_classes = [
92 PlainTextFormatter,
92 PlainTextFormatter,
93 HTMLFormatter,
93 HTMLFormatter,
94 SVGFormatter,
94 SVGFormatter,
95 PNGFormatter,
95 PNGFormatter,
96 JPEGFormatter,
96 JPEGFormatter,
97 LatexFormatter,
97 LatexFormatter,
98 JSONFormatter,
98 JSONFormatter,
99 JavascriptFormatter
99 JavascriptFormatter
100 ]
100 ]
101 d = {}
101 d = {}
102 for cls in formatter_classes:
102 for cls in formatter_classes:
103 f = cls(parent=self)
103 f = cls(parent=self)
104 d[f.format_type] = f
104 d[f.format_type] = f
105 return d
105 return d
106
106
107 def format(self, obj, include=None, exclude=None):
107 def format(self, obj, include=None, exclude=None):
108 """Return a format data dict for an object.
108 """Return a format data dict for an object.
109
109
110 By default all format types will be computed.
110 By default all format types will be computed.
111
111
112 The following MIME types are currently implemented:
112 The following MIME types are currently implemented:
113
113
114 * text/plain
114 * text/plain
115 * text/html
115 * text/html
116 * text/latex
116 * text/latex
117 * application/json
117 * application/json
118 * application/javascript
118 * application/javascript
119 * image/png
119 * image/png
120 * image/jpeg
120 * image/jpeg
121 * image/svg+xml
121 * image/svg+xml
122
122
123 Parameters
123 Parameters
124 ----------
124 ----------
125 obj : object
125 obj : object
126 The Python object whose format data will be computed.
126 The Python object whose format data will be computed.
127 include : list or tuple, optional
127 include : list or tuple, optional
128 A list of format type strings (MIME types) to include in the
128 A list of format type strings (MIME types) to include in the
129 format data dict. If this is set *only* the format types included
129 format data dict. If this is set *only* the format types included
130 in this list will be computed.
130 in this list will be computed.
131 exclude : list or tuple, optional
131 exclude : list or tuple, optional
132 A list of format type string (MIME types) to exclude in the format
132 A list of format type string (MIME types) to exclude in the format
133 data dict. If this is set all format types will be computed,
133 data dict. If this is set all format types will be computed,
134 except for those included in this argument.
134 except for those included in this argument.
135
135
136 Returns
136 Returns
137 -------
137 -------
138 (format_dict, metadata_dict) : tuple of two dicts
138 (format_dict, metadata_dict) : tuple of two dicts
139
139
140 format_dict is a dictionary of key/value pairs, one of each format that was
140 format_dict is a dictionary of key/value pairs, one of each format that was
141 generated for the object. The keys are the format types, which
141 generated for the object. The keys are the format types, which
142 will usually be MIME type strings and the values and JSON'able
142 will usually be MIME type strings and the values and JSON'able
143 data structure containing the raw data for the representation in
143 data structure containing the raw data for the representation in
144 that format.
144 that format.
145
145
146 metadata_dict is a dictionary of metadata about each mime-type output.
146 metadata_dict is a dictionary of metadata about each mime-type output.
147 Its keys will be a strict subset of the keys in format_dict.
147 Its keys will be a strict subset of the keys in format_dict.
148 """
148 """
149 format_dict = {}
149 format_dict = {}
150 md_dict = {}
150 md_dict = {}
151
151
152 for format_type, formatter in self.formatters.items():
152 for format_type, formatter in self.formatters.items():
153 if include and format_type not in include:
153 if include and format_type not in include:
154 continue
154 continue
155 if exclude and format_type in exclude:
155 if exclude and format_type in exclude:
156 continue
156 continue
157
157
158 md = None
158 md = None
159 try:
159 try:
160 data = formatter(obj)
160 data = formatter(obj)
161 except:
161 except:
162 # FIXME: log the exception
162 # FIXME: log the exception
163 raise
163 raise
164
164
165 # formatters can return raw data or (data, metadata)
165 # formatters can return raw data or (data, metadata)
166 if isinstance(data, tuple) and len(data) == 2:
166 if isinstance(data, tuple) and len(data) == 2:
167 data, md = data
167 data, md = data
168
168
169 if data is not None:
169 if data is not None:
170 format_dict[format_type] = data
170 format_dict[format_type] = data
171 if md is not None:
171 if md is not None:
172 md_dict[format_type] = md
172 md_dict[format_type] = md
173
173
174 return format_dict, md_dict
174 return format_dict, md_dict
175
175
176 @property
176 @property
177 def format_types(self):
177 def format_types(self):
178 """Return the format types (MIME types) of the active formatters."""
178 """Return the format types (MIME types) of the active formatters."""
179 return list(self.formatters.keys())
179 return list(self.formatters.keys())
180
180
181
181
182 #-----------------------------------------------------------------------------
182 #-----------------------------------------------------------------------------
183 # Formatters for specific format types (text, html, svg, etc.)
183 # Formatters for specific format types (text, html, svg, etc.)
184 #-----------------------------------------------------------------------------
184 #-----------------------------------------------------------------------------
185
185
186 class FormatterWarning(UserWarning):
187 """Warning class for errors in formatters"""
188
186 @decorator
189 @decorator
187 def warn_format_error(method, self, *args, **kwargs):
190 def warn_format_error(method, self, *args, **kwargs):
188 """decorator for warning on failed format call"""
191 """decorator for warning on failed format call"""
189 try:
192 try:
190 r = method(self, *args, **kwargs)
193 r = method(self, *args, **kwargs)
191 except NotImplementedError as e:
194 except NotImplementedError as e:
192 # don't warn on NotImplementedErrors
195 # don't warn on NotImplementedErrors
193 return None
196 return None
194 except Exception as e:
197 except Exception as e:
195 warn("Exception in %s formatter: %s" % (self.format_type, e))
198 warnings.warn("Exception in %s formatter: %s" % (self.format_type, e),
199 FormatterWarning,
200 )
196 return None
201 return None
197 if r is None or isinstance(r, self._return_type) or \
202 if r is None or isinstance(r, self._return_type) or \
198 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
203 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
199 return r
204 return r
200 else:
205 else:
201 warn("%s formatter returned invalid type %s (expected %s) for object: %s" % (
206 warnings.warn(
202 self.format_type, type(r), self._return_type, pretty._safe_repr(args[0])
207 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
203 ))
208 (self.format_type, type(r), self._return_type, pretty._safe_repr(args[0])),
204
209 FormatterWarning
210 )
205
211
206
212
207 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
213 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
208 """ Abstract base class for Formatters.
214 """ Abstract base class for Formatters.
209
215
210 A formatter is a callable class that is responsible for computing the
216 A formatter is a callable class that is responsible for computing the
211 raw format data for a particular format type (MIME type). For example,
217 raw format data for a particular format type (MIME type). For example,
212 an HTML formatter would have a format type of `text/html` and would return
218 an HTML formatter would have a format type of `text/html` and would return
213 the HTML representation of the object when called.
219 the HTML representation of the object when called.
214 """
220 """
215
221
216 # The format type of the data returned, usually a MIME type.
222 # The format type of the data returned, usually a MIME type.
217 format_type = 'text/plain'
223 format_type = 'text/plain'
218
224
219 # Is the formatter enabled...
225 # Is the formatter enabled...
220 enabled = True
226 enabled = True
221
227
222 @abc.abstractmethod
228 @abc.abstractmethod
223 @warn_format_error
229 @warn_format_error
224 def __call__(self, obj):
230 def __call__(self, obj):
225 """Return a JSON'able representation of the object.
231 """Return a JSON'able representation of the object.
226
232
227 If the object cannot be formatted by this formatter,
233 If the object cannot be formatted by this formatter,
228 warn and return None.
234 warn and return None.
229 """
235 """
230 return repr(obj)
236 return repr(obj)
231
237
232
238
233 def _mod_name_key(typ):
239 def _mod_name_key(typ):
234 """Return a (__module__, __name__) tuple for a type.
240 """Return a (__module__, __name__) tuple for a type.
235
241
236 Used as key in Formatter.deferred_printers.
242 Used as key in Formatter.deferred_printers.
237 """
243 """
238 module = getattr(typ, '__module__', None)
244 module = getattr(typ, '__module__', None)
239 name = getattr(typ, '__name__', None)
245 name = getattr(typ, '__name__', None)
240 return (module, name)
246 return (module, name)
241
247
242
248
243 def _get_type(obj):
249 def _get_type(obj):
244 """Return the type of an instance (old and new-style)"""
250 """Return the type of an instance (old and new-style)"""
245 return getattr(obj, '__class__', None) or type(obj)
251 return getattr(obj, '__class__', None) or type(obj)
246
252
247 _raise_key_error = object()
253 _raise_key_error = object()
248
254
249
255
250 class BaseFormatter(Configurable):
256 class BaseFormatter(Configurable):
251 """A base formatter class that is configurable.
257 """A base formatter class that is configurable.
252
258
253 This formatter should usually be used as the base class of all formatters.
259 This formatter should usually be used as the base class of all formatters.
254 It is a traited :class:`Configurable` class and includes an extensible
260 It is a traited :class:`Configurable` class and includes an extensible
255 API for users to determine how their objects are formatted. The following
261 API for users to determine how their objects are formatted. The following
256 logic is used to find a function to format an given object.
262 logic is used to find a function to format an given object.
257
263
258 1. The object is introspected to see if it has a method with the name
264 1. The object is introspected to see if it has a method with the name
259 :attr:`print_method`. If is does, that object is passed to that method
265 :attr:`print_method`. If is does, that object is passed to that method
260 for formatting.
266 for formatting.
261 2. If no print method is found, three internal dictionaries are consulted
267 2. If no print method is found, three internal dictionaries are consulted
262 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
268 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
263 and :attr:`deferred_printers`.
269 and :attr:`deferred_printers`.
264
270
265 Users should use these dictionaries to register functions that will be
271 Users should use these dictionaries to register functions that will be
266 used to compute the format data for their objects (if those objects don't
272 used to compute the format data for their objects (if those objects don't
267 have the special print methods). The easiest way of using these
273 have the special print methods). The easiest way of using these
268 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
274 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
269 methods.
275 methods.
270
276
271 If no function/callable is found to compute the format data, ``None`` is
277 If no function/callable is found to compute the format data, ``None`` is
272 returned and this format type is not used.
278 returned and this format type is not used.
273 """
279 """
274
280
275 format_type = Unicode('text/plain')
281 format_type = Unicode('text/plain')
276 _return_type = string_types
282 _return_type = string_types
277
283
278 enabled = Bool(True, config=True)
284 enabled = Bool(True, config=True)
279
285
280 print_method = ObjectName('__repr__')
286 print_method = ObjectName('__repr__')
281
287
282 # The singleton printers.
288 # The singleton printers.
283 # Maps the IDs of the builtin singleton objects to the format functions.
289 # Maps the IDs of the builtin singleton objects to the format functions.
284 singleton_printers = Dict(config=True)
290 singleton_printers = Dict(config=True)
285
291
286 # The type-specific printers.
292 # The type-specific printers.
287 # Map type objects to the format functions.
293 # Map type objects to the format functions.
288 type_printers = Dict(config=True)
294 type_printers = Dict(config=True)
289
295
290 # The deferred-import type-specific printers.
296 # The deferred-import type-specific printers.
291 # Map (modulename, classname) pairs to the format functions.
297 # Map (modulename, classname) pairs to the format functions.
292 deferred_printers = Dict(config=True)
298 deferred_printers = Dict(config=True)
293
299
294 @warn_format_error
300 @warn_format_error
295 def __call__(self, obj):
301 def __call__(self, obj):
296 """Compute the format for an object."""
302 """Compute the format for an object."""
297 if self.enabled:
303 if self.enabled:
298 # lookup registered printer
304 # lookup registered printer
299 try:
305 try:
300 printer = self.lookup(obj)
306 printer = self.lookup(obj)
301 except KeyError:
307 except KeyError:
302 pass
308 pass
303 else:
309 else:
304 return printer(obj)
310 return printer(obj)
305 # Finally look for special method names
311 # Finally look for special method names
306 method = pretty._safe_getattr(obj, self.print_method, None)
312 method = pretty._safe_getattr(obj, self.print_method, None)
307 if method is not None:
313 if method is not None:
308 return method()
314 return method()
309 return None
315 return None
310 else:
316 else:
311 return None
317 return None
312
318
313 def __contains__(self, typ):
319 def __contains__(self, typ):
314 """map in to lookup_by_type"""
320 """map in to lookup_by_type"""
315 try:
321 try:
316 self.lookup_by_type(typ)
322 self.lookup_by_type(typ)
317 except KeyError:
323 except KeyError:
318 return False
324 return False
319 else:
325 else:
320 return True
326 return True
321
327
322 def lookup(self, obj):
328 def lookup(self, obj):
323 """Look up the formatter for a given instance.
329 """Look up the formatter for a given instance.
324
330
325 Parameters
331 Parameters
326 ----------
332 ----------
327 obj : object instance
333 obj : object instance
328
334
329 Returns
335 Returns
330 -------
336 -------
331 f : callable
337 f : callable
332 The registered formatting callable for the type.
338 The registered formatting callable for the type.
333
339
334 Raises
340 Raises
335 ------
341 ------
336 KeyError if the type has not been registered.
342 KeyError if the type has not been registered.
337 """
343 """
338 # look for singleton first
344 # look for singleton first
339 obj_id = id(obj)
345 obj_id = id(obj)
340 if obj_id in self.singleton_printers:
346 if obj_id in self.singleton_printers:
341 return self.singleton_printers[obj_id]
347 return self.singleton_printers[obj_id]
342 # then lookup by type
348 # then lookup by type
343 return self.lookup_by_type(_get_type(obj))
349 return self.lookup_by_type(_get_type(obj))
344
350
345 def lookup_by_type(self, typ):
351 def lookup_by_type(self, typ):
346 """Look up the registered formatter for a type.
352 """Look up the registered formatter for a type.
347
353
348 Parameters
354 Parameters
349 ----------
355 ----------
350 typ : type or '__module__.__name__' string for a type
356 typ : type or '__module__.__name__' string for a type
351
357
352 Returns
358 Returns
353 -------
359 -------
354 f : callable
360 f : callable
355 The registered formatting callable for the type.
361 The registered formatting callable for the type.
356
362
357 Raises
363 Raises
358 ------
364 ------
359 KeyError if the type has not been registered.
365 KeyError if the type has not been registered.
360 """
366 """
361 if isinstance(typ, string_types):
367 if isinstance(typ, string_types):
362 typ_key = tuple(typ.rsplit('.',1))
368 typ_key = tuple(typ.rsplit('.',1))
363 if typ_key not in self.deferred_printers:
369 if typ_key not in self.deferred_printers:
364 # We may have it cached in the type map. We will have to
370 # We may have it cached in the type map. We will have to
365 # iterate over all of the types to check.
371 # iterate over all of the types to check.
366 for cls in self.type_printers:
372 for cls in self.type_printers:
367 if _mod_name_key(cls) == typ_key:
373 if _mod_name_key(cls) == typ_key:
368 return self.type_printers[cls]
374 return self.type_printers[cls]
369 else:
375 else:
370 return self.deferred_printers[typ_key]
376 return self.deferred_printers[typ_key]
371 else:
377 else:
372 for cls in pretty._get_mro(typ):
378 for cls in pretty._get_mro(typ):
373 if cls in self.type_printers or self._in_deferred_types(cls):
379 if cls in self.type_printers or self._in_deferred_types(cls):
374 return self.type_printers[cls]
380 return self.type_printers[cls]
375
381
376 # If we have reached here, the lookup failed.
382 # If we have reached here, the lookup failed.
377 raise KeyError("No registered printer for {0!r}".format(typ))
383 raise KeyError("No registered printer for {0!r}".format(typ))
378
384
379 def for_type(self, typ, func=None):
385 def for_type(self, typ, func=None):
380 """Add a format function for a given type.
386 """Add a format function for a given type.
381
387
382 Parameters
388 Parameters
383 -----------
389 -----------
384 typ : type or '__module__.__name__' string for a type
390 typ : type or '__module__.__name__' string for a type
385 The class of the object that will be formatted using `func`.
391 The class of the object that will be formatted using `func`.
386 func : callable
392 func : callable
387 A callable for computing the format data.
393 A callable for computing the format data.
388 `func` will be called with the object to be formatted,
394 `func` will be called with the object to be formatted,
389 and will return the raw data in this formatter's format.
395 and will return the raw data in this formatter's format.
390 Subclasses may use a different call signature for the
396 Subclasses may use a different call signature for the
391 `func` argument.
397 `func` argument.
392
398
393 If `func` is None or not specified, there will be no change,
399 If `func` is None or not specified, there will be no change,
394 only returning the current value.
400 only returning the current value.
395
401
396 Returns
402 Returns
397 -------
403 -------
398 oldfunc : callable
404 oldfunc : callable
399 The currently registered callable.
405 The currently registered callable.
400 If you are registering a new formatter,
406 If you are registering a new formatter,
401 this will be the previous value (to enable restoring later).
407 this will be the previous value (to enable restoring later).
402 """
408 """
403 # if string given, interpret as 'pkg.module.class_name'
409 # if string given, interpret as 'pkg.module.class_name'
404 if isinstance(typ, string_types):
410 if isinstance(typ, string_types):
405 type_module, type_name = typ.rsplit('.', 1)
411 type_module, type_name = typ.rsplit('.', 1)
406 return self.for_type_by_name(type_module, type_name, func)
412 return self.for_type_by_name(type_module, type_name, func)
407
413
408 try:
414 try:
409 oldfunc = self.lookup_by_type(typ)
415 oldfunc = self.lookup_by_type(typ)
410 except KeyError:
416 except KeyError:
411 oldfunc = None
417 oldfunc = None
412
418
413 if func is not None:
419 if func is not None:
414 self.type_printers[typ] = func
420 self.type_printers[typ] = func
415
421
416 return oldfunc
422 return oldfunc
417
423
418 def for_type_by_name(self, type_module, type_name, func=None):
424 def for_type_by_name(self, type_module, type_name, func=None):
419 """Add a format function for a type specified by the full dotted
425 """Add a format function for a type specified by the full dotted
420 module and name of the type, rather than the type of the object.
426 module and name of the type, rather than the type of the object.
421
427
422 Parameters
428 Parameters
423 ----------
429 ----------
424 type_module : str
430 type_module : str
425 The full dotted name of the module the type is defined in, like
431 The full dotted name of the module the type is defined in, like
426 ``numpy``.
432 ``numpy``.
427 type_name : str
433 type_name : str
428 The name of the type (the class name), like ``dtype``
434 The name of the type (the class name), like ``dtype``
429 func : callable
435 func : callable
430 A callable for computing the format data.
436 A callable for computing the format data.
431 `func` will be called with the object to be formatted,
437 `func` will be called with the object to be formatted,
432 and will return the raw data in this formatter's format.
438 and will return the raw data in this formatter's format.
433 Subclasses may use a different call signature for the
439 Subclasses may use a different call signature for the
434 `func` argument.
440 `func` argument.
435
441
436 If `func` is None or unspecified, there will be no change,
442 If `func` is None or unspecified, there will be no change,
437 only returning the current value.
443 only returning the current value.
438
444
439 Returns
445 Returns
440 -------
446 -------
441 oldfunc : callable
447 oldfunc : callable
442 The currently registered callable.
448 The currently registered callable.
443 If you are registering a new formatter,
449 If you are registering a new formatter,
444 this will be the previous value (to enable restoring later).
450 this will be the previous value (to enable restoring later).
445 """
451 """
446 key = (type_module, type_name)
452 key = (type_module, type_name)
447
453
448 try:
454 try:
449 oldfunc = self.lookup_by_type("%s.%s" % key)
455 oldfunc = self.lookup_by_type("%s.%s" % key)
450 except KeyError:
456 except KeyError:
451 oldfunc = None
457 oldfunc = None
452
458
453 if func is not None:
459 if func is not None:
454 self.deferred_printers[key] = func
460 self.deferred_printers[key] = func
455 return oldfunc
461 return oldfunc
456
462
457 def pop(self, typ, default=_raise_key_error):
463 def pop(self, typ, default=_raise_key_error):
458 """Pop a formatter for the given type.
464 """Pop a formatter for the given type.
459
465
460 Parameters
466 Parameters
461 ----------
467 ----------
462 typ : type or '__module__.__name__' string for a type
468 typ : type or '__module__.__name__' string for a type
463 default : object
469 default : object
464 value to be returned if no formatter is registered for typ.
470 value to be returned if no formatter is registered for typ.
465
471
466 Returns
472 Returns
467 -------
473 -------
468 obj : object
474 obj : object
469 The last registered object for the type.
475 The last registered object for the type.
470
476
471 Raises
477 Raises
472 ------
478 ------
473 KeyError if the type is not registered and default is not specified.
479 KeyError if the type is not registered and default is not specified.
474 """
480 """
475
481
476 if isinstance(typ, string_types):
482 if isinstance(typ, string_types):
477 typ_key = tuple(typ.rsplit('.',1))
483 typ_key = tuple(typ.rsplit('.',1))
478 if typ_key not in self.deferred_printers:
484 if typ_key not in self.deferred_printers:
479 # We may have it cached in the type map. We will have to
485 # We may have it cached in the type map. We will have to
480 # iterate over all of the types to check.
486 # iterate over all of the types to check.
481 for cls in self.type_printers:
487 for cls in self.type_printers:
482 if _mod_name_key(cls) == typ_key:
488 if _mod_name_key(cls) == typ_key:
483 old = self.type_printers.pop(cls)
489 old = self.type_printers.pop(cls)
484 break
490 break
485 else:
491 else:
486 old = default
492 old = default
487 else:
493 else:
488 old = self.deferred_printers.pop(typ_key)
494 old = self.deferred_printers.pop(typ_key)
489 else:
495 else:
490 if typ in self.type_printers:
496 if typ in self.type_printers:
491 old = self.type_printers.pop(typ)
497 old = self.type_printers.pop(typ)
492 else:
498 else:
493 old = self.deferred_printers.pop(_mod_name_key(typ), default)
499 old = self.deferred_printers.pop(_mod_name_key(typ), default)
494 if old is _raise_key_error:
500 if old is _raise_key_error:
495 raise KeyError("No registered value for {0!r}".format(typ))
501 raise KeyError("No registered value for {0!r}".format(typ))
496 return old
502 return old
497
503
498 def _in_deferred_types(self, cls):
504 def _in_deferred_types(self, cls):
499 """
505 """
500 Check if the given class is specified in the deferred type registry.
506 Check if the given class is specified in the deferred type registry.
501
507
502 Successful matches will be moved to the regular type registry for future use.
508 Successful matches will be moved to the regular type registry for future use.
503 """
509 """
504 mod = getattr(cls, '__module__', None)
510 mod = getattr(cls, '__module__', None)
505 name = getattr(cls, '__name__', None)
511 name = getattr(cls, '__name__', None)
506 key = (mod, name)
512 key = (mod, name)
507 if key in self.deferred_printers:
513 if key in self.deferred_printers:
508 # Move the printer over to the regular registry.
514 # Move the printer over to the regular registry.
509 printer = self.deferred_printers.pop(key)
515 printer = self.deferred_printers.pop(key)
510 self.type_printers[cls] = printer
516 self.type_printers[cls] = printer
511 return True
517 return True
512 return False
518 return False
513
519
514
520
515 class PlainTextFormatter(BaseFormatter):
521 class PlainTextFormatter(BaseFormatter):
516 """The default pretty-printer.
522 """The default pretty-printer.
517
523
518 This uses :mod:`IPython.lib.pretty` to compute the format data of
524 This uses :mod:`IPython.lib.pretty` to compute the format data of
519 the object. If the object cannot be pretty printed, :func:`repr` is used.
525 the object. If the object cannot be pretty printed, :func:`repr` is used.
520 See the documentation of :mod:`IPython.lib.pretty` for details on
526 See the documentation of :mod:`IPython.lib.pretty` for details on
521 how to write pretty printers. Here is a simple example::
527 how to write pretty printers. Here is a simple example::
522
528
523 def dtype_pprinter(obj, p, cycle):
529 def dtype_pprinter(obj, p, cycle):
524 if cycle:
530 if cycle:
525 return p.text('dtype(...)')
531 return p.text('dtype(...)')
526 if hasattr(obj, 'fields'):
532 if hasattr(obj, 'fields'):
527 if obj.fields is None:
533 if obj.fields is None:
528 p.text(repr(obj))
534 p.text(repr(obj))
529 else:
535 else:
530 p.begin_group(7, 'dtype([')
536 p.begin_group(7, 'dtype([')
531 for i, field in enumerate(obj.descr):
537 for i, field in enumerate(obj.descr):
532 if i > 0:
538 if i > 0:
533 p.text(',')
539 p.text(',')
534 p.breakable()
540 p.breakable()
535 p.pretty(field)
541 p.pretty(field)
536 p.end_group(7, '])')
542 p.end_group(7, '])')
537 """
543 """
538
544
539 # The format type of data returned.
545 # The format type of data returned.
540 format_type = Unicode('text/plain')
546 format_type = Unicode('text/plain')
541
547
542 # This subclass ignores this attribute as it always need to return
548 # This subclass ignores this attribute as it always need to return
543 # something.
549 # something.
544 enabled = Bool(True, config=False)
550 enabled = Bool(True, config=False)
545
551
546 # Look for a _repr_pretty_ methods to use for pretty printing.
552 # Look for a _repr_pretty_ methods to use for pretty printing.
547 print_method = ObjectName('_repr_pretty_')
553 print_method = ObjectName('_repr_pretty_')
548
554
549 # Whether to pretty-print or not.
555 # Whether to pretty-print or not.
550 pprint = Bool(True, config=True)
556 pprint = Bool(True, config=True)
551
557
552 # Whether to be verbose or not.
558 # Whether to be verbose or not.
553 verbose = Bool(False, config=True)
559 verbose = Bool(False, config=True)
554
560
555 # The maximum width.
561 # The maximum width.
556 max_width = Integer(79, config=True)
562 max_width = Integer(79, config=True)
557
563
558 # The newline character.
564 # The newline character.
559 newline = Unicode('\n', config=True)
565 newline = Unicode('\n', config=True)
560
566
561 # format-string for pprinting floats
567 # format-string for pprinting floats
562 float_format = Unicode('%r')
568 float_format = Unicode('%r')
563 # setter for float precision, either int or direct format-string
569 # setter for float precision, either int or direct format-string
564 float_precision = CUnicode('', config=True)
570 float_precision = CUnicode('', config=True)
565
571
566 def _float_precision_changed(self, name, old, new):
572 def _float_precision_changed(self, name, old, new):
567 """float_precision changed, set float_format accordingly.
573 """float_precision changed, set float_format accordingly.
568
574
569 float_precision can be set by int or str.
575 float_precision can be set by int or str.
570 This will set float_format, after interpreting input.
576 This will set float_format, after interpreting input.
571 If numpy has been imported, numpy print precision will also be set.
577 If numpy has been imported, numpy print precision will also be set.
572
578
573 integer `n` sets format to '%.nf', otherwise, format set directly.
579 integer `n` sets format to '%.nf', otherwise, format set directly.
574
580
575 An empty string returns to defaults (repr for float, 8 for numpy).
581 An empty string returns to defaults (repr for float, 8 for numpy).
576
582
577 This parameter can be set via the '%precision' magic.
583 This parameter can be set via the '%precision' magic.
578 """
584 """
579
585
580 if '%' in new:
586 if '%' in new:
581 # got explicit format string
587 # got explicit format string
582 fmt = new
588 fmt = new
583 try:
589 try:
584 fmt%3.14159
590 fmt%3.14159
585 except Exception:
591 except Exception:
586 raise ValueError("Precision must be int or format string, not %r"%new)
592 raise ValueError("Precision must be int or format string, not %r"%new)
587 elif new:
593 elif new:
588 # otherwise, should be an int
594 # otherwise, should be an int
589 try:
595 try:
590 i = int(new)
596 i = int(new)
591 assert i >= 0
597 assert i >= 0
592 except ValueError:
598 except ValueError:
593 raise ValueError("Precision must be int or format string, not %r"%new)
599 raise ValueError("Precision must be int or format string, not %r"%new)
594 except AssertionError:
600 except AssertionError:
595 raise ValueError("int precision must be non-negative, not %r"%i)
601 raise ValueError("int precision must be non-negative, not %r"%i)
596
602
597 fmt = '%%.%if'%i
603 fmt = '%%.%if'%i
598 if 'numpy' in sys.modules:
604 if 'numpy' in sys.modules:
599 # set numpy precision if it has been imported
605 # set numpy precision if it has been imported
600 import numpy
606 import numpy
601 numpy.set_printoptions(precision=i)
607 numpy.set_printoptions(precision=i)
602 else:
608 else:
603 # default back to repr
609 # default back to repr
604 fmt = '%r'
610 fmt = '%r'
605 if 'numpy' in sys.modules:
611 if 'numpy' in sys.modules:
606 import numpy
612 import numpy
607 # numpy default is 8
613 # numpy default is 8
608 numpy.set_printoptions(precision=8)
614 numpy.set_printoptions(precision=8)
609 self.float_format = fmt
615 self.float_format = fmt
610
616
611 # Use the default pretty printers from IPython.lib.pretty.
617 # Use the default pretty printers from IPython.lib.pretty.
612 def _singleton_printers_default(self):
618 def _singleton_printers_default(self):
613 return pretty._singleton_pprinters.copy()
619 return pretty._singleton_pprinters.copy()
614
620
615 def _type_printers_default(self):
621 def _type_printers_default(self):
616 d = pretty._type_pprinters.copy()
622 d = pretty._type_pprinters.copy()
617 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
623 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
618 return d
624 return d
619
625
620 def _deferred_printers_default(self):
626 def _deferred_printers_default(self):
621 return pretty._deferred_type_pprinters.copy()
627 return pretty._deferred_type_pprinters.copy()
622
628
623 #### FormatterABC interface ####
629 #### FormatterABC interface ####
624
630
625 @warn_format_error
631 @warn_format_error
626 def __call__(self, obj):
632 def __call__(self, obj):
627 """Compute the pretty representation of the object."""
633 """Compute the pretty representation of the object."""
628 if not self.pprint:
634 if not self.pprint:
629 return pretty._safe_repr(obj)
635 return pretty._safe_repr(obj)
630 else:
636 else:
631 # This uses use StringIO, as cStringIO doesn't handle unicode.
637 # This uses use StringIO, as cStringIO doesn't handle unicode.
632 stream = StringIO()
638 stream = StringIO()
633 # self.newline.encode() is a quick fix for issue gh-597. We need to
639 # self.newline.encode() is a quick fix for issue gh-597. We need to
634 # ensure that stream does not get a mix of unicode and bytestrings,
640 # ensure that stream does not get a mix of unicode and bytestrings,
635 # or it will cause trouble.
641 # or it will cause trouble.
636 printer = pretty.RepresentationPrinter(stream, self.verbose,
642 printer = pretty.RepresentationPrinter(stream, self.verbose,
637 self.max_width, unicode_to_str(self.newline),
643 self.max_width, unicode_to_str(self.newline),
638 singleton_pprinters=self.singleton_printers,
644 singleton_pprinters=self.singleton_printers,
639 type_pprinters=self.type_printers,
645 type_pprinters=self.type_printers,
640 deferred_pprinters=self.deferred_printers)
646 deferred_pprinters=self.deferred_printers)
641 printer.pretty(obj)
647 printer.pretty(obj)
642 printer.flush()
648 printer.flush()
643 return stream.getvalue()
649 return stream.getvalue()
644
650
645
651
646 class HTMLFormatter(BaseFormatter):
652 class HTMLFormatter(BaseFormatter):
647 """An HTML formatter.
653 """An HTML formatter.
648
654
649 To define the callables that compute the HTML representation of your
655 To define the callables that compute the HTML representation of your
650 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
656 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
651 or :meth:`for_type_by_name` methods to register functions that handle
657 or :meth:`for_type_by_name` methods to register functions that handle
652 this.
658 this.
653
659
654 The return value of this formatter should be a valid HTML snippet that
660 The return value of this formatter should be a valid HTML snippet that
655 could be injected into an existing DOM. It should *not* include the
661 could be injected into an existing DOM. It should *not* include the
656 ```<html>`` or ```<body>`` tags.
662 ```<html>`` or ```<body>`` tags.
657 """
663 """
658 format_type = Unicode('text/html')
664 format_type = Unicode('text/html')
659
665
660 print_method = ObjectName('_repr_html_')
666 print_method = ObjectName('_repr_html_')
661
667
662
668
663 class SVGFormatter(BaseFormatter):
669 class SVGFormatter(BaseFormatter):
664 """An SVG formatter.
670 """An SVG formatter.
665
671
666 To define the callables that compute the SVG representation of your
672 To define the callables that compute the SVG representation of your
667 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
673 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
668 or :meth:`for_type_by_name` methods to register functions that handle
674 or :meth:`for_type_by_name` methods to register functions that handle
669 this.
675 this.
670
676
671 The return value of this formatter should be valid SVG enclosed in
677 The return value of this formatter should be valid SVG enclosed in
672 ```<svg>``` tags, that could be injected into an existing DOM. It should
678 ```<svg>``` tags, that could be injected into an existing DOM. It should
673 *not* include the ```<html>`` or ```<body>`` tags.
679 *not* include the ```<html>`` or ```<body>`` tags.
674 """
680 """
675 format_type = Unicode('image/svg+xml')
681 format_type = Unicode('image/svg+xml')
676
682
677 print_method = ObjectName('_repr_svg_')
683 print_method = ObjectName('_repr_svg_')
678
684
679
685
680 class PNGFormatter(BaseFormatter):
686 class PNGFormatter(BaseFormatter):
681 """A PNG formatter.
687 """A PNG formatter.
682
688
683 To define the callables that compute the PNG representation of your
689 To define the callables that compute the PNG representation of your
684 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
690 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
685 or :meth:`for_type_by_name` methods to register functions that handle
691 or :meth:`for_type_by_name` methods to register functions that handle
686 this.
692 this.
687
693
688 The return value of this formatter should be raw PNG data, *not*
694 The return value of this formatter should be raw PNG data, *not*
689 base64 encoded.
695 base64 encoded.
690 """
696 """
691 format_type = Unicode('image/png')
697 format_type = Unicode('image/png')
692
698
693 print_method = ObjectName('_repr_png_')
699 print_method = ObjectName('_repr_png_')
694
700
695 _return_type = (bytes, unicode_type)
701 _return_type = (bytes, unicode_type)
696
702
697
703
698 class JPEGFormatter(BaseFormatter):
704 class JPEGFormatter(BaseFormatter):
699 """A JPEG formatter.
705 """A JPEG formatter.
700
706
701 To define the callables that compute the JPEG representation of your
707 To define the callables that compute the JPEG representation of your
702 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
708 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
703 or :meth:`for_type_by_name` methods to register functions that handle
709 or :meth:`for_type_by_name` methods to register functions that handle
704 this.
710 this.
705
711
706 The return value of this formatter should be raw JPEG data, *not*
712 The return value of this formatter should be raw JPEG data, *not*
707 base64 encoded.
713 base64 encoded.
708 """
714 """
709 format_type = Unicode('image/jpeg')
715 format_type = Unicode('image/jpeg')
710
716
711 print_method = ObjectName('_repr_jpeg_')
717 print_method = ObjectName('_repr_jpeg_')
712
718
713 _return_type = (bytes, unicode_type)
719 _return_type = (bytes, unicode_type)
714
720
715
721
716 class LatexFormatter(BaseFormatter):
722 class LatexFormatter(BaseFormatter):
717 """A LaTeX formatter.
723 """A LaTeX formatter.
718
724
719 To define the callables that compute the LaTeX representation of your
725 To define the callables that compute the LaTeX representation of your
720 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
726 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
721 or :meth:`for_type_by_name` methods to register functions that handle
727 or :meth:`for_type_by_name` methods to register functions that handle
722 this.
728 this.
723
729
724 The return value of this formatter should be a valid LaTeX equation,
730 The return value of this formatter should be a valid LaTeX equation,
725 enclosed in either ```$```, ```$$``` or another LaTeX equation
731 enclosed in either ```$```, ```$$``` or another LaTeX equation
726 environment.
732 environment.
727 """
733 """
728 format_type = Unicode('text/latex')
734 format_type = Unicode('text/latex')
729
735
730 print_method = ObjectName('_repr_latex_')
736 print_method = ObjectName('_repr_latex_')
731
737
732
738
733 class JSONFormatter(BaseFormatter):
739 class JSONFormatter(BaseFormatter):
734 """A JSON string formatter.
740 """A JSON string formatter.
735
741
736 To define the callables that compute the JSON string representation of
742 To define the callables that compute the JSON string representation of
737 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
743 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
738 or :meth:`for_type_by_name` methods to register functions that handle
744 or :meth:`for_type_by_name` methods to register functions that handle
739 this.
745 this.
740
746
741 The return value of this formatter should be a valid JSON string.
747 The return value of this formatter should be a valid JSON string.
742 """
748 """
743 format_type = Unicode('application/json')
749 format_type = Unicode('application/json')
744
750
745 print_method = ObjectName('_repr_json_')
751 print_method = ObjectName('_repr_json_')
746
752
747
753
748 class JavascriptFormatter(BaseFormatter):
754 class JavascriptFormatter(BaseFormatter):
749 """A Javascript formatter.
755 """A Javascript formatter.
750
756
751 To define the callables that compute the Javascript representation of
757 To define the callables that compute the Javascript representation of
752 your objects, define a :meth:`_repr_javascript_` method or use the
758 your objects, define a :meth:`_repr_javascript_` method or use the
753 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
759 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
754 that handle this.
760 that handle this.
755
761
756 The return value of this formatter should be valid Javascript code and
762 The return value of this formatter should be valid Javascript code and
757 should *not* be enclosed in ```<script>``` tags.
763 should *not* be enclosed in ```<script>``` tags.
758 """
764 """
759 format_type = Unicode('application/javascript')
765 format_type = Unicode('application/javascript')
760
766
761 print_method = ObjectName('_repr_javascript_')
767 print_method = ObjectName('_repr_javascript_')
762
768
763 FormatterABC.register(BaseFormatter)
769 FormatterABC.register(BaseFormatter)
764 FormatterABC.register(PlainTextFormatter)
770 FormatterABC.register(PlainTextFormatter)
765 FormatterABC.register(HTMLFormatter)
771 FormatterABC.register(HTMLFormatter)
766 FormatterABC.register(SVGFormatter)
772 FormatterABC.register(SVGFormatter)
767 FormatterABC.register(PNGFormatter)
773 FormatterABC.register(PNGFormatter)
768 FormatterABC.register(JPEGFormatter)
774 FormatterABC.register(JPEGFormatter)
769 FormatterABC.register(LatexFormatter)
775 FormatterABC.register(LatexFormatter)
770 FormatterABC.register(JSONFormatter)
776 FormatterABC.register(JSONFormatter)
771 FormatterABC.register(JavascriptFormatter)
777 FormatterABC.register(JavascriptFormatter)
772
778
773
779
774 def format_display_data(obj, include=None, exclude=None):
780 def format_display_data(obj, include=None, exclude=None):
775 """Return a format data dict for an object.
781 """Return a format data dict for an object.
776
782
777 By default all format types will be computed.
783 By default all format types will be computed.
778
784
779 The following MIME types are currently implemented:
785 The following MIME types are currently implemented:
780
786
781 * text/plain
787 * text/plain
782 * text/html
788 * text/html
783 * text/latex
789 * text/latex
784 * application/json
790 * application/json
785 * application/javascript
791 * application/javascript
786 * image/png
792 * image/png
787 * image/jpeg
793 * image/jpeg
788 * image/svg+xml
794 * image/svg+xml
789
795
790 Parameters
796 Parameters
791 ----------
797 ----------
792 obj : object
798 obj : object
793 The Python object whose format data will be computed.
799 The Python object whose format data will be computed.
794
800
795 Returns
801 Returns
796 -------
802 -------
797 format_dict : dict
803 format_dict : dict
798 A dictionary of key/value pairs, one or each format that was
804 A dictionary of key/value pairs, one or each format that was
799 generated for the object. The keys are the format types, which
805 generated for the object. The keys are the format types, which
800 will usually be MIME type strings and the values and JSON'able
806 will usually be MIME type strings and the values and JSON'able
801 data structure containing the raw data for the representation in
807 data structure containing the raw data for the representation in
802 that format.
808 that format.
803 include : list or tuple, optional
809 include : list or tuple, optional
804 A list of format type strings (MIME types) to include in the
810 A list of format type strings (MIME types) to include in the
805 format data dict. If this is set *only* the format types included
811 format data dict. If this is set *only* the format types included
806 in this list will be computed.
812 in this list will be computed.
807 exclude : list or tuple, optional
813 exclude : list or tuple, optional
808 A list of format type string (MIME types) to exclue in the format
814 A list of format type string (MIME types) to exclue in the format
809 data dict. If this is set all format types will be computed,
815 data dict. If this is set all format types will be computed,
810 except for those included in this argument.
816 except for those included in this argument.
811 """
817 """
812 from IPython.core.interactiveshell import InteractiveShell
818 from IPython.core.interactiveshell import InteractiveShell
813
819
814 InteractiveShell.instance().display_formatter.format(
820 InteractiveShell.instance().display_formatter.format(
815 obj,
821 obj,
816 include,
822 include,
817 exclude
823 exclude
818 )
824 )
819
825
@@ -1,282 +1,282 b''
1 """Tests for the Formatters."""
1 """Tests for the Formatters."""
2
2
3 from math import pi
3 from math import pi
4
4
5 try:
5 try:
6 import numpy
6 import numpy
7 except:
7 except:
8 numpy = None
8 numpy = None
9 import nose.tools as nt
9 import nose.tools as nt
10
10
11 from IPython.core.formatters import PlainTextFormatter, HTMLFormatter, _mod_name_key
11 from IPython.core.formatters import PlainTextFormatter, HTMLFormatter, _mod_name_key
12 from IPython.utils.io import capture_output
12 from IPython.utils.io import capture_output
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)
172 nt.assert_is(f.lookup_by_type(type_str), foo_printer)
173 # lookup by string doesn't cause import
173 # lookup by string doesn't cause import
174 nt.assert_in(_mod_name_key(C), f.deferred_printers)
174 nt.assert_in(_mod_name_key(C), f.deferred_printers)
175 nt.assert_not_in(C, f.type_printers)
175 nt.assert_not_in(C, f.type_printers)
176
176
177 nt.assert_is(f.lookup_by_type(C), foo_printer)
177 nt.assert_is(f.lookup_by_type(C), foo_printer)
178 # should move from deferred to imported dict
178 # should move from deferred to imported dict
179 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
179 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
180 nt.assert_in(C, f.type_printers)
180 nt.assert_in(C, f.type_printers)
181
181
182 def test_in_formatter():
182 def test_in_formatter():
183 f = PlainTextFormatter()
183 f = PlainTextFormatter()
184 f.for_type(C, foo_printer)
184 f.for_type(C, foo_printer)
185 type_str = '%s.%s' % (C.__module__, 'C')
185 type_str = '%s.%s' % (C.__module__, 'C')
186 nt.assert_in(C, f)
186 nt.assert_in(C, f)
187 nt.assert_in(type_str, f)
187 nt.assert_in(type_str, f)
188
188
189 def test_string_in_formatter():
189 def test_string_in_formatter():
190 f = PlainTextFormatter()
190 f = PlainTextFormatter()
191 type_str = '%s.%s' % (C.__module__, 'C')
191 type_str = '%s.%s' % (C.__module__, 'C')
192 f.for_type(type_str, foo_printer)
192 f.for_type(type_str, foo_printer)
193 nt.assert_in(type_str, f)
193 nt.assert_in(type_str, f)
194 nt.assert_in(C, f)
194 nt.assert_in(C, f)
195
195
196 def test_pop():
196 def test_pop():
197 f = PlainTextFormatter()
197 f = PlainTextFormatter()
198 f.for_type(C, foo_printer)
198 f.for_type(C, foo_printer)
199 nt.assert_is(f.lookup_by_type(C), foo_printer)
199 nt.assert_is(f.lookup_by_type(C), foo_printer)
200 nt.assert_is(f.pop(C, None), foo_printer)
200 nt.assert_is(f.pop(C, None), foo_printer)
201 f.for_type(C, foo_printer)
201 f.for_type(C, foo_printer)
202 nt.assert_is(f.pop(C), foo_printer)
202 nt.assert_is(f.pop(C), foo_printer)
203 with nt.assert_raises(KeyError):
203 with nt.assert_raises(KeyError):
204 f.lookup_by_type(C)
204 f.lookup_by_type(C)
205 with nt.assert_raises(KeyError):
205 with nt.assert_raises(KeyError):
206 f.pop(C)
206 f.pop(C)
207 with nt.assert_raises(KeyError):
207 with nt.assert_raises(KeyError):
208 f.pop(A)
208 f.pop(A)
209 nt.assert_is(f.pop(A, None), None)
209 nt.assert_is(f.pop(A, None), None)
210
210
211 def test_pop_string():
211 def test_pop_string():
212 f = PlainTextFormatter()
212 f = PlainTextFormatter()
213 type_str = '%s.%s' % (C.__module__, 'C')
213 type_str = '%s.%s' % (C.__module__, 'C')
214
214
215 with nt.assert_raises(KeyError):
215 with nt.assert_raises(KeyError):
216 f.pop(type_str)
216 f.pop(type_str)
217
217
218 f.for_type(type_str, foo_printer)
218 f.for_type(type_str, foo_printer)
219 f.pop(type_str)
219 f.pop(type_str)
220 with nt.assert_raises(KeyError):
220 with nt.assert_raises(KeyError):
221 f.lookup_by_type(C)
221 f.lookup_by_type(C)
222 with nt.assert_raises(KeyError):
222 with nt.assert_raises(KeyError):
223 f.pop(type_str)
223 f.pop(type_str)
224
224
225 f.for_type(C, foo_printer)
225 f.for_type(C, foo_printer)
226 nt.assert_is(f.pop(type_str, None), foo_printer)
226 nt.assert_is(f.pop(type_str, None), foo_printer)
227 with nt.assert_raises(KeyError):
227 with nt.assert_raises(KeyError):
228 f.lookup_by_type(C)
228 f.lookup_by_type(C)
229 with nt.assert_raises(KeyError):
229 with nt.assert_raises(KeyError):
230 f.pop(type_str)
230 f.pop(type_str)
231 nt.assert_is(f.pop(type_str, None), None)
231 nt.assert_is(f.pop(type_str, None), None)
232
232
233
233
234 def test_warn_error_method():
234 def test_warn_error_method():
235 f = HTMLFormatter()
235 f = HTMLFormatter()
236 class BadHTML(object):
236 class BadHTML(object):
237 def _repr_html_(self):
237 def _repr_html_(self):
238 return 1/0
238 return 1/0
239 bad = BadHTML()
239 bad = BadHTML()
240 with capture_output() as captured:
240 with capture_output() as captured:
241 result = f(bad)
241 result = f(bad)
242 nt.assert_is(result, None)
242 nt.assert_is(result, None)
243 nt.assert_in("WARNING", captured.stderr)
243 nt.assert_in("FormatterWarning", captured.stderr)
244 nt.assert_in("text/html", captured.stderr)
244 nt.assert_in("text/html", captured.stderr)
245 nt.assert_in("zero", captured.stderr)
245 nt.assert_in("zero", captured.stderr)
246
246
247 def test_nowarn_notimplemented():
247 def test_nowarn_notimplemented():
248 f = HTMLFormatter()
248 f = HTMLFormatter()
249 class HTMLNotImplemented(object):
249 class HTMLNotImplemented(object):
250 def _repr_html_(self):
250 def _repr_html_(self):
251 raise NotImplementedError
251 raise NotImplementedError
252 return 1/0
252 return 1/0
253 h = HTMLNotImplemented()
253 h = HTMLNotImplemented()
254 with capture_output() as captured:
254 with capture_output() as captured:
255 result = f(h)
255 result = f(h)
256 nt.assert_is(result, None)
256 nt.assert_is(result, None)
257 nt.assert_not_in("WARNING", captured.stderr)
257 nt.assert_not_in("FormatterWarning", captured.stderr)
258
258
259 def test_warn_error_for_type():
259 def test_warn_error_for_type():
260 f = HTMLFormatter()
260 f = HTMLFormatter()
261 f.for_type(int, lambda i: name_error)
261 f.for_type(int, lambda i: name_error)
262 with capture_output() as captured:
262 with capture_output() as captured:
263 result = f(5)
263 result = f(5)
264 nt.assert_is(result, None)
264 nt.assert_is(result, None)
265 nt.assert_in("WARNING", captured.stderr)
265 nt.assert_in("FormatterWarning", captured.stderr)
266 nt.assert_in("text/html", captured.stderr)
266 nt.assert_in("text/html", captured.stderr)
267 nt.assert_in("name_error", captured.stderr)
267 nt.assert_in("name_error", captured.stderr)
268
268
269 def test_warn_error_pretty_method():
269 def test_warn_error_pretty_method():
270 f = PlainTextFormatter()
270 f = PlainTextFormatter()
271 class BadPretty(object):
271 class BadPretty(object):
272 def _repr_pretty_(self):
272 def _repr_pretty_(self):
273 return "hello"
273 return "hello"
274 bad = BadPretty()
274 bad = BadPretty()
275 with capture_output() as captured:
275 with capture_output() as captured:
276 result = f(bad)
276 result = f(bad)
277 nt.assert_is(result, None)
277 nt.assert_is(result, None)
278 nt.assert_in("WARNING", captured.stderr)
278 nt.assert_in("FormatterWarning", captured.stderr)
279 nt.assert_in("text/plain", captured.stderr)
279 nt.assert_in("text/plain", captured.stderr)
280 nt.assert_in("argument", captured.stderr)
280 nt.assert_in("argument", captured.stderr)
281
281
282
282
General Comments 0
You need to be logged in to leave comments. Login now