##// END OF EJS Templates
Merge pull request #4832 from minrk/formatter-not-implemented...
Thomas Kluyver -
r14737:b823a5a0 merge
parent child Browse files
Show More
@@ -1,816 +1,825
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)
194 except NotImplementedError as e:
195 # don't warn on NotImplementedErrors
196 return None
191 except Exception as e:
197 except Exception as e:
192 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 )
193 return None
201 return None
194 if r is None or isinstance(r, self._return_type) or \
202 if r is None or isinstance(r, self._return_type) or \
195 (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)):
196 return r
204 return r
197 else:
205 else:
198 warn("%s formatter returned invalid type %s (expected %s) for object: %s" % (
206 warnings.warn(
199 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" % \
200 ))
208 (self.format_type, type(r), self._return_type, pretty._safe_repr(args[0])),
201
209 FormatterWarning
210 )
202
211
203
212
204 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
213 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
205 """ Abstract base class for Formatters.
214 """ Abstract base class for Formatters.
206
215
207 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
208 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,
209 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
210 the HTML representation of the object when called.
219 the HTML representation of the object when called.
211 """
220 """
212
221
213 # The format type of the data returned, usually a MIME type.
222 # The format type of the data returned, usually a MIME type.
214 format_type = 'text/plain'
223 format_type = 'text/plain'
215
224
216 # Is the formatter enabled...
225 # Is the formatter enabled...
217 enabled = True
226 enabled = True
218
227
219 @abc.abstractmethod
228 @abc.abstractmethod
220 @warn_format_error
229 @warn_format_error
221 def __call__(self, obj):
230 def __call__(self, obj):
222 """Return a JSON'able representation of the object.
231 """Return a JSON'able representation of the object.
223
232
224 If the object cannot be formatted by this formatter,
233 If the object cannot be formatted by this formatter,
225 warn and return None.
234 warn and return None.
226 """
235 """
227 return repr(obj)
236 return repr(obj)
228
237
229
238
230 def _mod_name_key(typ):
239 def _mod_name_key(typ):
231 """Return a (__module__, __name__) tuple for a type.
240 """Return a (__module__, __name__) tuple for a type.
232
241
233 Used as key in Formatter.deferred_printers.
242 Used as key in Formatter.deferred_printers.
234 """
243 """
235 module = getattr(typ, '__module__', None)
244 module = getattr(typ, '__module__', None)
236 name = getattr(typ, '__name__', None)
245 name = getattr(typ, '__name__', None)
237 return (module, name)
246 return (module, name)
238
247
239
248
240 def _get_type(obj):
249 def _get_type(obj):
241 """Return the type of an instance (old and new-style)"""
250 """Return the type of an instance (old and new-style)"""
242 return getattr(obj, '__class__', None) or type(obj)
251 return getattr(obj, '__class__', None) or type(obj)
243
252
244 _raise_key_error = object()
253 _raise_key_error = object()
245
254
246
255
247 class BaseFormatter(Configurable):
256 class BaseFormatter(Configurable):
248 """A base formatter class that is configurable.
257 """A base formatter class that is configurable.
249
258
250 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.
251 It is a traited :class:`Configurable` class and includes an extensible
260 It is a traited :class:`Configurable` class and includes an extensible
252 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
253 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.
254
263
255 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
256 :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
257 for formatting.
266 for formatting.
258 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
259 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
268 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
260 and :attr:`deferred_printers`.
269 and :attr:`deferred_printers`.
261
270
262 Users should use these dictionaries to register functions that will be
271 Users should use these dictionaries to register functions that will be
263 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
264 have the special print methods). The easiest way of using these
273 have the special print methods). The easiest way of using these
265 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`
266 methods.
275 methods.
267
276
268 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
269 returned and this format type is not used.
278 returned and this format type is not used.
270 """
279 """
271
280
272 format_type = Unicode('text/plain')
281 format_type = Unicode('text/plain')
273 _return_type = string_types
282 _return_type = string_types
274
283
275 enabled = Bool(True, config=True)
284 enabled = Bool(True, config=True)
276
285
277 print_method = ObjectName('__repr__')
286 print_method = ObjectName('__repr__')
278
287
279 # The singleton printers.
288 # The singleton printers.
280 # 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.
281 singleton_printers = Dict(config=True)
290 singleton_printers = Dict(config=True)
282
291
283 # The type-specific printers.
292 # The type-specific printers.
284 # Map type objects to the format functions.
293 # Map type objects to the format functions.
285 type_printers = Dict(config=True)
294 type_printers = Dict(config=True)
286
295
287 # The deferred-import type-specific printers.
296 # The deferred-import type-specific printers.
288 # Map (modulename, classname) pairs to the format functions.
297 # Map (modulename, classname) pairs to the format functions.
289 deferred_printers = Dict(config=True)
298 deferred_printers = Dict(config=True)
290
299
291 @warn_format_error
300 @warn_format_error
292 def __call__(self, obj):
301 def __call__(self, obj):
293 """Compute the format for an object."""
302 """Compute the format for an object."""
294 if self.enabled:
303 if self.enabled:
295 # lookup registered printer
304 # lookup registered printer
296 try:
305 try:
297 printer = self.lookup(obj)
306 printer = self.lookup(obj)
298 except KeyError:
307 except KeyError:
299 pass
308 pass
300 else:
309 else:
301 return printer(obj)
310 return printer(obj)
302 # Finally look for special method names
311 # Finally look for special method names
303 method = pretty._safe_getattr(obj, self.print_method, None)
312 method = pretty._safe_getattr(obj, self.print_method, None)
304 if method is not None:
313 if method is not None:
305 return method()
314 return method()
306 return None
315 return None
307 else:
316 else:
308 return None
317 return None
309
318
310 def __contains__(self, typ):
319 def __contains__(self, typ):
311 """map in to lookup_by_type"""
320 """map in to lookup_by_type"""
312 try:
321 try:
313 self.lookup_by_type(typ)
322 self.lookup_by_type(typ)
314 except KeyError:
323 except KeyError:
315 return False
324 return False
316 else:
325 else:
317 return True
326 return True
318
327
319 def lookup(self, obj):
328 def lookup(self, obj):
320 """Look up the formatter for a given instance.
329 """Look up the formatter for a given instance.
321
330
322 Parameters
331 Parameters
323 ----------
332 ----------
324 obj : object instance
333 obj : object instance
325
334
326 Returns
335 Returns
327 -------
336 -------
328 f : callable
337 f : callable
329 The registered formatting callable for the type.
338 The registered formatting callable for the type.
330
339
331 Raises
340 Raises
332 ------
341 ------
333 KeyError if the type has not been registered.
342 KeyError if the type has not been registered.
334 """
343 """
335 # look for singleton first
344 # look for singleton first
336 obj_id = id(obj)
345 obj_id = id(obj)
337 if obj_id in self.singleton_printers:
346 if obj_id in self.singleton_printers:
338 return self.singleton_printers[obj_id]
347 return self.singleton_printers[obj_id]
339 # then lookup by type
348 # then lookup by type
340 return self.lookup_by_type(_get_type(obj))
349 return self.lookup_by_type(_get_type(obj))
341
350
342 def lookup_by_type(self, typ):
351 def lookup_by_type(self, typ):
343 """Look up the registered formatter for a type.
352 """Look up the registered formatter for a type.
344
353
345 Parameters
354 Parameters
346 ----------
355 ----------
347 typ : type or '__module__.__name__' string for a type
356 typ : type or '__module__.__name__' string for a type
348
357
349 Returns
358 Returns
350 -------
359 -------
351 f : callable
360 f : callable
352 The registered formatting callable for the type.
361 The registered formatting callable for the type.
353
362
354 Raises
363 Raises
355 ------
364 ------
356 KeyError if the type has not been registered.
365 KeyError if the type has not been registered.
357 """
366 """
358 if isinstance(typ, string_types):
367 if isinstance(typ, string_types):
359 typ_key = tuple(typ.rsplit('.',1))
368 typ_key = tuple(typ.rsplit('.',1))
360 if typ_key not in self.deferred_printers:
369 if typ_key not in self.deferred_printers:
361 # 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
362 # iterate over all of the types to check.
371 # iterate over all of the types to check.
363 for cls in self.type_printers:
372 for cls in self.type_printers:
364 if _mod_name_key(cls) == typ_key:
373 if _mod_name_key(cls) == typ_key:
365 return self.type_printers[cls]
374 return self.type_printers[cls]
366 else:
375 else:
367 return self.deferred_printers[typ_key]
376 return self.deferred_printers[typ_key]
368 else:
377 else:
369 for cls in pretty._get_mro(typ):
378 for cls in pretty._get_mro(typ):
370 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):
371 return self.type_printers[cls]
380 return self.type_printers[cls]
372
381
373 # If we have reached here, the lookup failed.
382 # If we have reached here, the lookup failed.
374 raise KeyError("No registered printer for {0!r}".format(typ))
383 raise KeyError("No registered printer for {0!r}".format(typ))
375
384
376 def for_type(self, typ, func=None):
385 def for_type(self, typ, func=None):
377 """Add a format function for a given type.
386 """Add a format function for a given type.
378
387
379 Parameters
388 Parameters
380 -----------
389 -----------
381 typ : type or '__module__.__name__' string for a type
390 typ : type or '__module__.__name__' string for a type
382 The class of the object that will be formatted using `func`.
391 The class of the object that will be formatted using `func`.
383 func : callable
392 func : callable
384 A callable for computing the format data.
393 A callable for computing the format data.
385 `func` will be called with the object to be formatted,
394 `func` will be called with the object to be formatted,
386 and will return the raw data in this formatter's format.
395 and will return the raw data in this formatter's format.
387 Subclasses may use a different call signature for the
396 Subclasses may use a different call signature for the
388 `func` argument.
397 `func` argument.
389
398
390 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,
391 only returning the current value.
400 only returning the current value.
392
401
393 Returns
402 Returns
394 -------
403 -------
395 oldfunc : callable
404 oldfunc : callable
396 The currently registered callable.
405 The currently registered callable.
397 If you are registering a new formatter,
406 If you are registering a new formatter,
398 this will be the previous value (to enable restoring later).
407 this will be the previous value (to enable restoring later).
399 """
408 """
400 # if string given, interpret as 'pkg.module.class_name'
409 # if string given, interpret as 'pkg.module.class_name'
401 if isinstance(typ, string_types):
410 if isinstance(typ, string_types):
402 type_module, type_name = typ.rsplit('.', 1)
411 type_module, type_name = typ.rsplit('.', 1)
403 return self.for_type_by_name(type_module, type_name, func)
412 return self.for_type_by_name(type_module, type_name, func)
404
413
405 try:
414 try:
406 oldfunc = self.lookup_by_type(typ)
415 oldfunc = self.lookup_by_type(typ)
407 except KeyError:
416 except KeyError:
408 oldfunc = None
417 oldfunc = None
409
418
410 if func is not None:
419 if func is not None:
411 self.type_printers[typ] = func
420 self.type_printers[typ] = func
412
421
413 return oldfunc
422 return oldfunc
414
423
415 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):
416 """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
417 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.
418
427
419 Parameters
428 Parameters
420 ----------
429 ----------
421 type_module : str
430 type_module : str
422 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
423 ``numpy``.
432 ``numpy``.
424 type_name : str
433 type_name : str
425 The name of the type (the class name), like ``dtype``
434 The name of the type (the class name), like ``dtype``
426 func : callable
435 func : callable
427 A callable for computing the format data.
436 A callable for computing the format data.
428 `func` will be called with the object to be formatted,
437 `func` will be called with the object to be formatted,
429 and will return the raw data in this formatter's format.
438 and will return the raw data in this formatter's format.
430 Subclasses may use a different call signature for the
439 Subclasses may use a different call signature for the
431 `func` argument.
440 `func` argument.
432
441
433 If `func` is None or unspecified, there will be no change,
442 If `func` is None or unspecified, there will be no change,
434 only returning the current value.
443 only returning the current value.
435
444
436 Returns
445 Returns
437 -------
446 -------
438 oldfunc : callable
447 oldfunc : callable
439 The currently registered callable.
448 The currently registered callable.
440 If you are registering a new formatter,
449 If you are registering a new formatter,
441 this will be the previous value (to enable restoring later).
450 this will be the previous value (to enable restoring later).
442 """
451 """
443 key = (type_module, type_name)
452 key = (type_module, type_name)
444
453
445 try:
454 try:
446 oldfunc = self.lookup_by_type("%s.%s" % key)
455 oldfunc = self.lookup_by_type("%s.%s" % key)
447 except KeyError:
456 except KeyError:
448 oldfunc = None
457 oldfunc = None
449
458
450 if func is not None:
459 if func is not None:
451 self.deferred_printers[key] = func
460 self.deferred_printers[key] = func
452 return oldfunc
461 return oldfunc
453
462
454 def pop(self, typ, default=_raise_key_error):
463 def pop(self, typ, default=_raise_key_error):
455 """Pop a formatter for the given type.
464 """Pop a formatter for the given type.
456
465
457 Parameters
466 Parameters
458 ----------
467 ----------
459 typ : type or '__module__.__name__' string for a type
468 typ : type or '__module__.__name__' string for a type
460 default : object
469 default : object
461 value to be returned if no formatter is registered for typ.
470 value to be returned if no formatter is registered for typ.
462
471
463 Returns
472 Returns
464 -------
473 -------
465 obj : object
474 obj : object
466 The last registered object for the type.
475 The last registered object for the type.
467
476
468 Raises
477 Raises
469 ------
478 ------
470 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.
471 """
480 """
472
481
473 if isinstance(typ, string_types):
482 if isinstance(typ, string_types):
474 typ_key = tuple(typ.rsplit('.',1))
483 typ_key = tuple(typ.rsplit('.',1))
475 if typ_key not in self.deferred_printers:
484 if typ_key not in self.deferred_printers:
476 # 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
477 # iterate over all of the types to check.
486 # iterate over all of the types to check.
478 for cls in self.type_printers:
487 for cls in self.type_printers:
479 if _mod_name_key(cls) == typ_key:
488 if _mod_name_key(cls) == typ_key:
480 old = self.type_printers.pop(cls)
489 old = self.type_printers.pop(cls)
481 break
490 break
482 else:
491 else:
483 old = default
492 old = default
484 else:
493 else:
485 old = self.deferred_printers.pop(typ_key)
494 old = self.deferred_printers.pop(typ_key)
486 else:
495 else:
487 if typ in self.type_printers:
496 if typ in self.type_printers:
488 old = self.type_printers.pop(typ)
497 old = self.type_printers.pop(typ)
489 else:
498 else:
490 old = self.deferred_printers.pop(_mod_name_key(typ), default)
499 old = self.deferred_printers.pop(_mod_name_key(typ), default)
491 if old is _raise_key_error:
500 if old is _raise_key_error:
492 raise KeyError("No registered value for {0!r}".format(typ))
501 raise KeyError("No registered value for {0!r}".format(typ))
493 return old
502 return old
494
503
495 def _in_deferred_types(self, cls):
504 def _in_deferred_types(self, cls):
496 """
505 """
497 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.
498
507
499 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.
500 """
509 """
501 mod = getattr(cls, '__module__', None)
510 mod = getattr(cls, '__module__', None)
502 name = getattr(cls, '__name__', None)
511 name = getattr(cls, '__name__', None)
503 key = (mod, name)
512 key = (mod, name)
504 if key in self.deferred_printers:
513 if key in self.deferred_printers:
505 # Move the printer over to the regular registry.
514 # Move the printer over to the regular registry.
506 printer = self.deferred_printers.pop(key)
515 printer = self.deferred_printers.pop(key)
507 self.type_printers[cls] = printer
516 self.type_printers[cls] = printer
508 return True
517 return True
509 return False
518 return False
510
519
511
520
512 class PlainTextFormatter(BaseFormatter):
521 class PlainTextFormatter(BaseFormatter):
513 """The default pretty-printer.
522 """The default pretty-printer.
514
523
515 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
516 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.
517 See the documentation of :mod:`IPython.lib.pretty` for details on
526 See the documentation of :mod:`IPython.lib.pretty` for details on
518 how to write pretty printers. Here is a simple example::
527 how to write pretty printers. Here is a simple example::
519
528
520 def dtype_pprinter(obj, p, cycle):
529 def dtype_pprinter(obj, p, cycle):
521 if cycle:
530 if cycle:
522 return p.text('dtype(...)')
531 return p.text('dtype(...)')
523 if hasattr(obj, 'fields'):
532 if hasattr(obj, 'fields'):
524 if obj.fields is None:
533 if obj.fields is None:
525 p.text(repr(obj))
534 p.text(repr(obj))
526 else:
535 else:
527 p.begin_group(7, 'dtype([')
536 p.begin_group(7, 'dtype([')
528 for i, field in enumerate(obj.descr):
537 for i, field in enumerate(obj.descr):
529 if i > 0:
538 if i > 0:
530 p.text(',')
539 p.text(',')
531 p.breakable()
540 p.breakable()
532 p.pretty(field)
541 p.pretty(field)
533 p.end_group(7, '])')
542 p.end_group(7, '])')
534 """
543 """
535
544
536 # The format type of data returned.
545 # The format type of data returned.
537 format_type = Unicode('text/plain')
546 format_type = Unicode('text/plain')
538
547
539 # This subclass ignores this attribute as it always need to return
548 # This subclass ignores this attribute as it always need to return
540 # something.
549 # something.
541 enabled = Bool(True, config=False)
550 enabled = Bool(True, config=False)
542
551
543 # Look for a _repr_pretty_ methods to use for pretty printing.
552 # Look for a _repr_pretty_ methods to use for pretty printing.
544 print_method = ObjectName('_repr_pretty_')
553 print_method = ObjectName('_repr_pretty_')
545
554
546 # Whether to pretty-print or not.
555 # Whether to pretty-print or not.
547 pprint = Bool(True, config=True)
556 pprint = Bool(True, config=True)
548
557
549 # Whether to be verbose or not.
558 # Whether to be verbose or not.
550 verbose = Bool(False, config=True)
559 verbose = Bool(False, config=True)
551
560
552 # The maximum width.
561 # The maximum width.
553 max_width = Integer(79, config=True)
562 max_width = Integer(79, config=True)
554
563
555 # The newline character.
564 # The newline character.
556 newline = Unicode('\n', config=True)
565 newline = Unicode('\n', config=True)
557
566
558 # format-string for pprinting floats
567 # format-string for pprinting floats
559 float_format = Unicode('%r')
568 float_format = Unicode('%r')
560 # setter for float precision, either int or direct format-string
569 # setter for float precision, either int or direct format-string
561 float_precision = CUnicode('', config=True)
570 float_precision = CUnicode('', config=True)
562
571
563 def _float_precision_changed(self, name, old, new):
572 def _float_precision_changed(self, name, old, new):
564 """float_precision changed, set float_format accordingly.
573 """float_precision changed, set float_format accordingly.
565
574
566 float_precision can be set by int or str.
575 float_precision can be set by int or str.
567 This will set float_format, after interpreting input.
576 This will set float_format, after interpreting input.
568 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.
569
578
570 integer `n` sets format to '%.nf', otherwise, format set directly.
579 integer `n` sets format to '%.nf', otherwise, format set directly.
571
580
572 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).
573
582
574 This parameter can be set via the '%precision' magic.
583 This parameter can be set via the '%precision' magic.
575 """
584 """
576
585
577 if '%' in new:
586 if '%' in new:
578 # got explicit format string
587 # got explicit format string
579 fmt = new
588 fmt = new
580 try:
589 try:
581 fmt%3.14159
590 fmt%3.14159
582 except Exception:
591 except Exception:
583 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)
584 elif new:
593 elif new:
585 # otherwise, should be an int
594 # otherwise, should be an int
586 try:
595 try:
587 i = int(new)
596 i = int(new)
588 assert i >= 0
597 assert i >= 0
589 except ValueError:
598 except ValueError:
590 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)
591 except AssertionError:
600 except AssertionError:
592 raise ValueError("int precision must be non-negative, not %r"%i)
601 raise ValueError("int precision must be non-negative, not %r"%i)
593
602
594 fmt = '%%.%if'%i
603 fmt = '%%.%if'%i
595 if 'numpy' in sys.modules:
604 if 'numpy' in sys.modules:
596 # set numpy precision if it has been imported
605 # set numpy precision if it has been imported
597 import numpy
606 import numpy
598 numpy.set_printoptions(precision=i)
607 numpy.set_printoptions(precision=i)
599 else:
608 else:
600 # default back to repr
609 # default back to repr
601 fmt = '%r'
610 fmt = '%r'
602 if 'numpy' in sys.modules:
611 if 'numpy' in sys.modules:
603 import numpy
612 import numpy
604 # numpy default is 8
613 # numpy default is 8
605 numpy.set_printoptions(precision=8)
614 numpy.set_printoptions(precision=8)
606 self.float_format = fmt
615 self.float_format = fmt
607
616
608 # Use the default pretty printers from IPython.lib.pretty.
617 # Use the default pretty printers from IPython.lib.pretty.
609 def _singleton_printers_default(self):
618 def _singleton_printers_default(self):
610 return pretty._singleton_pprinters.copy()
619 return pretty._singleton_pprinters.copy()
611
620
612 def _type_printers_default(self):
621 def _type_printers_default(self):
613 d = pretty._type_pprinters.copy()
622 d = pretty._type_pprinters.copy()
614 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)
615 return d
624 return d
616
625
617 def _deferred_printers_default(self):
626 def _deferred_printers_default(self):
618 return pretty._deferred_type_pprinters.copy()
627 return pretty._deferred_type_pprinters.copy()
619
628
620 #### FormatterABC interface ####
629 #### FormatterABC interface ####
621
630
622 @warn_format_error
631 @warn_format_error
623 def __call__(self, obj):
632 def __call__(self, obj):
624 """Compute the pretty representation of the object."""
633 """Compute the pretty representation of the object."""
625 if not self.pprint:
634 if not self.pprint:
626 return pretty._safe_repr(obj)
635 return pretty._safe_repr(obj)
627 else:
636 else:
628 # This uses use StringIO, as cStringIO doesn't handle unicode.
637 # This uses use StringIO, as cStringIO doesn't handle unicode.
629 stream = StringIO()
638 stream = StringIO()
630 # 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
631 # 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,
632 # or it will cause trouble.
641 # or it will cause trouble.
633 printer = pretty.RepresentationPrinter(stream, self.verbose,
642 printer = pretty.RepresentationPrinter(stream, self.verbose,
634 self.max_width, unicode_to_str(self.newline),
643 self.max_width, unicode_to_str(self.newline),
635 singleton_pprinters=self.singleton_printers,
644 singleton_pprinters=self.singleton_printers,
636 type_pprinters=self.type_printers,
645 type_pprinters=self.type_printers,
637 deferred_pprinters=self.deferred_printers)
646 deferred_pprinters=self.deferred_printers)
638 printer.pretty(obj)
647 printer.pretty(obj)
639 printer.flush()
648 printer.flush()
640 return stream.getvalue()
649 return stream.getvalue()
641
650
642
651
643 class HTMLFormatter(BaseFormatter):
652 class HTMLFormatter(BaseFormatter):
644 """An HTML formatter.
653 """An HTML formatter.
645
654
646 To define the callables that compute the HTML representation of your
655 To define the callables that compute the HTML representation of your
647 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`
648 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
649 this.
658 this.
650
659
651 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
652 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
653 ```<html>`` or ```<body>`` tags.
662 ```<html>`` or ```<body>`` tags.
654 """
663 """
655 format_type = Unicode('text/html')
664 format_type = Unicode('text/html')
656
665
657 print_method = ObjectName('_repr_html_')
666 print_method = ObjectName('_repr_html_')
658
667
659
668
660 class SVGFormatter(BaseFormatter):
669 class SVGFormatter(BaseFormatter):
661 """An SVG formatter.
670 """An SVG formatter.
662
671
663 To define the callables that compute the SVG representation of your
672 To define the callables that compute the SVG representation of your
664 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`
665 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
666 this.
675 this.
667
676
668 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
669 ```<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
670 *not* include the ```<html>`` or ```<body>`` tags.
679 *not* include the ```<html>`` or ```<body>`` tags.
671 """
680 """
672 format_type = Unicode('image/svg+xml')
681 format_type = Unicode('image/svg+xml')
673
682
674 print_method = ObjectName('_repr_svg_')
683 print_method = ObjectName('_repr_svg_')
675
684
676
685
677 class PNGFormatter(BaseFormatter):
686 class PNGFormatter(BaseFormatter):
678 """A PNG formatter.
687 """A PNG formatter.
679
688
680 To define the callables that compute the PNG representation of your
689 To define the callables that compute the PNG representation of your
681 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`
682 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
683 this.
692 this.
684
693
685 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*
686 base64 encoded.
695 base64 encoded.
687 """
696 """
688 format_type = Unicode('image/png')
697 format_type = Unicode('image/png')
689
698
690 print_method = ObjectName('_repr_png_')
699 print_method = ObjectName('_repr_png_')
691
700
692 _return_type = (bytes, unicode_type)
701 _return_type = (bytes, unicode_type)
693
702
694
703
695 class JPEGFormatter(BaseFormatter):
704 class JPEGFormatter(BaseFormatter):
696 """A JPEG formatter.
705 """A JPEG formatter.
697
706
698 To define the callables that compute the JPEG representation of your
707 To define the callables that compute the JPEG representation of your
699 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`
700 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
701 this.
710 this.
702
711
703 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*
704 base64 encoded.
713 base64 encoded.
705 """
714 """
706 format_type = Unicode('image/jpeg')
715 format_type = Unicode('image/jpeg')
707
716
708 print_method = ObjectName('_repr_jpeg_')
717 print_method = ObjectName('_repr_jpeg_')
709
718
710 _return_type = (bytes, unicode_type)
719 _return_type = (bytes, unicode_type)
711
720
712
721
713 class LatexFormatter(BaseFormatter):
722 class LatexFormatter(BaseFormatter):
714 """A LaTeX formatter.
723 """A LaTeX formatter.
715
724
716 To define the callables that compute the LaTeX representation of your
725 To define the callables that compute the LaTeX representation of your
717 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`
718 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
719 this.
728 this.
720
729
721 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,
722 enclosed in either ```$```, ```$$``` or another LaTeX equation
731 enclosed in either ```$```, ```$$``` or another LaTeX equation
723 environment.
732 environment.
724 """
733 """
725 format_type = Unicode('text/latex')
734 format_type = Unicode('text/latex')
726
735
727 print_method = ObjectName('_repr_latex_')
736 print_method = ObjectName('_repr_latex_')
728
737
729
738
730 class JSONFormatter(BaseFormatter):
739 class JSONFormatter(BaseFormatter):
731 """A JSON string formatter.
740 """A JSON string formatter.
732
741
733 To define the callables that compute the JSON string representation of
742 To define the callables that compute the JSON string representation of
734 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`
735 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
736 this.
745 this.
737
746
738 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.
739 """
748 """
740 format_type = Unicode('application/json')
749 format_type = Unicode('application/json')
741
750
742 print_method = ObjectName('_repr_json_')
751 print_method = ObjectName('_repr_json_')
743
752
744
753
745 class JavascriptFormatter(BaseFormatter):
754 class JavascriptFormatter(BaseFormatter):
746 """A Javascript formatter.
755 """A Javascript formatter.
747
756
748 To define the callables that compute the Javascript representation of
757 To define the callables that compute the Javascript representation of
749 your objects, define a :meth:`_repr_javascript_` method or use the
758 your objects, define a :meth:`_repr_javascript_` method or use the
750 :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
751 that handle this.
760 that handle this.
752
761
753 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
754 should *not* be enclosed in ```<script>``` tags.
763 should *not* be enclosed in ```<script>``` tags.
755 """
764 """
756 format_type = Unicode('application/javascript')
765 format_type = Unicode('application/javascript')
757
766
758 print_method = ObjectName('_repr_javascript_')
767 print_method = ObjectName('_repr_javascript_')
759
768
760 FormatterABC.register(BaseFormatter)
769 FormatterABC.register(BaseFormatter)
761 FormatterABC.register(PlainTextFormatter)
770 FormatterABC.register(PlainTextFormatter)
762 FormatterABC.register(HTMLFormatter)
771 FormatterABC.register(HTMLFormatter)
763 FormatterABC.register(SVGFormatter)
772 FormatterABC.register(SVGFormatter)
764 FormatterABC.register(PNGFormatter)
773 FormatterABC.register(PNGFormatter)
765 FormatterABC.register(JPEGFormatter)
774 FormatterABC.register(JPEGFormatter)
766 FormatterABC.register(LatexFormatter)
775 FormatterABC.register(LatexFormatter)
767 FormatterABC.register(JSONFormatter)
776 FormatterABC.register(JSONFormatter)
768 FormatterABC.register(JavascriptFormatter)
777 FormatterABC.register(JavascriptFormatter)
769
778
770
779
771 def format_display_data(obj, include=None, exclude=None):
780 def format_display_data(obj, include=None, exclude=None):
772 """Return a format data dict for an object.
781 """Return a format data dict for an object.
773
782
774 By default all format types will be computed.
783 By default all format types will be computed.
775
784
776 The following MIME types are currently implemented:
785 The following MIME types are currently implemented:
777
786
778 * text/plain
787 * text/plain
779 * text/html
788 * text/html
780 * text/latex
789 * text/latex
781 * application/json
790 * application/json
782 * application/javascript
791 * application/javascript
783 * image/png
792 * image/png
784 * image/jpeg
793 * image/jpeg
785 * image/svg+xml
794 * image/svg+xml
786
795
787 Parameters
796 Parameters
788 ----------
797 ----------
789 obj : object
798 obj : object
790 The Python object whose format data will be computed.
799 The Python object whose format data will be computed.
791
800
792 Returns
801 Returns
793 -------
802 -------
794 format_dict : dict
803 format_dict : dict
795 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
796 generated for the object. The keys are the format types, which
805 generated for the object. The keys are the format types, which
797 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
798 data structure containing the raw data for the representation in
807 data structure containing the raw data for the representation in
799 that format.
808 that format.
800 include : list or tuple, optional
809 include : list or tuple, optional
801 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
802 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
803 in this list will be computed.
812 in this list will be computed.
804 exclude : list or tuple, optional
813 exclude : list or tuple, optional
805 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
806 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,
807 except for those included in this argument.
816 except for those included in this argument.
808 """
817 """
809 from IPython.core.interactiveshell import InteractiveShell
818 from IPython.core.interactiveshell import InteractiveShell
810
819
811 InteractiveShell.instance().display_formatter.format(
820 InteractiveShell.instance().display_formatter.format(
812 obj,
821 obj,
813 include,
822 include,
814 exclude
823 exclude
815 )
824 )
816
825
@@ -1,270 +1,282
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():
248 f = HTMLFormatter()
249 class HTMLNotImplemented(object):
250 def _repr_html_(self):
251 raise NotImplementedError
252 return 1/0
253 h = HTMLNotImplemented()
254 with capture_output() as captured:
255 result = f(h)
256 nt.assert_is(result, None)
257 nt.assert_not_in("FormatterWarning", captured.stderr)
258
247 def test_warn_error_for_type():
259 def test_warn_error_for_type():
248 f = HTMLFormatter()
260 f = HTMLFormatter()
249 f.for_type(int, lambda i: name_error)
261 f.for_type(int, lambda i: name_error)
250 with capture_output() as captured:
262 with capture_output() as captured:
251 result = f(5)
263 result = f(5)
252 nt.assert_is(result, None)
264 nt.assert_is(result, None)
253 nt.assert_in("WARNING", captured.stderr)
265 nt.assert_in("FormatterWarning", captured.stderr)
254 nt.assert_in("text/html", captured.stderr)
266 nt.assert_in("text/html", captured.stderr)
255 nt.assert_in("name_error", captured.stderr)
267 nt.assert_in("name_error", captured.stderr)
256
268
257 def test_warn_error_pretty_method():
269 def test_warn_error_pretty_method():
258 f = PlainTextFormatter()
270 f = PlainTextFormatter()
259 class BadPretty(object):
271 class BadPretty(object):
260 def _repr_pretty_(self):
272 def _repr_pretty_(self):
261 return "hello"
273 return "hello"
262 bad = BadPretty()
274 bad = BadPretty()
263 with capture_output() as captured:
275 with capture_output() as captured:
264 result = f(bad)
276 result = f(bad)
265 nt.assert_is(result, None)
277 nt.assert_is(result, None)
266 nt.assert_in("WARNING", captured.stderr)
278 nt.assert_in("FormatterWarning", captured.stderr)
267 nt.assert_in("text/plain", captured.stderr)
279 nt.assert_in("text/plain", captured.stderr)
268 nt.assert_in("argument", captured.stderr)
280 nt.assert_in("argument", captured.stderr)
269
281
270
282
General Comments 0
You need to be logged in to leave comments. Login now