##// END OF EJS Templates
Backport PR #10896: Ensure that MimeBundleFormatter always returns a 2-tuple
Min RK -
Show More
@@ -1,1037 +1,1037 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
9
10 # Copyright (c) IPython Development Team.
10 # Copyright (c) IPython Development Team.
11 # Distributed under the terms of the Modified BSD License.
11 # Distributed under the terms of the Modified BSD License.
12
12
13 import abc
13 import abc
14 import json
14 import json
15 import sys
15 import sys
16 import traceback
16 import traceback
17 import warnings
17 import warnings
18
18
19 from decorator import decorator
19 from decorator import decorator
20
20
21 from traitlets.config.configurable import Configurable
21 from traitlets.config.configurable import Configurable
22 from IPython.core.getipython import get_ipython
22 from IPython.core.getipython import get_ipython
23 from IPython.utils.sentinel import Sentinel
23 from IPython.utils.sentinel import Sentinel
24 from IPython.utils.dir2 import get_real_method
24 from IPython.utils.dir2 import get_real_method
25 from IPython.lib import pretty
25 from IPython.lib import pretty
26 from traitlets import (
26 from traitlets import (
27 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
27 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
28 ForwardDeclaredInstance,
28 ForwardDeclaredInstance,
29 default, observe,
29 default, observe,
30 )
30 )
31 from IPython.utils.py3compat import (
31 from IPython.utils.py3compat import (
32 with_metaclass, string_types, unicode_type,
32 with_metaclass, string_types, unicode_type,
33 )
33 )
34
34
35
35
36 class DisplayFormatter(Configurable):
36 class DisplayFormatter(Configurable):
37
37
38 active_types = List(Unicode(),
38 active_types = List(Unicode(),
39 help="""List of currently active mime-types to display.
39 help="""List of currently active mime-types to display.
40 You can use this to set a white-list for formats to display.
40 You can use this to set a white-list for formats to display.
41
41
42 Most users will not need to change this value.
42 Most users will not need to change this value.
43 """).tag(config=True)
43 """).tag(config=True)
44
44
45 @default('active_types')
45 @default('active_types')
46 def _active_types_default(self):
46 def _active_types_default(self):
47 return self.format_types
47 return self.format_types
48
48
49 @observe('active_types')
49 @observe('active_types')
50 def _active_types_changed(self, change):
50 def _active_types_changed(self, change):
51 for key, formatter in self.formatters.items():
51 for key, formatter in self.formatters.items():
52 if key in change['new']:
52 if key in change['new']:
53 formatter.enabled = True
53 formatter.enabled = True
54 else:
54 else:
55 formatter.enabled = False
55 formatter.enabled = False
56
56
57 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
57 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
58 @default('ipython_display_formatter')
58 @default('ipython_display_formatter')
59 def _default_formatter(self):
59 def _default_formatter(self):
60 return IPythonDisplayFormatter(parent=self)
60 return IPythonDisplayFormatter(parent=self)
61
61
62 mimebundle_formatter = ForwardDeclaredInstance('FormatterABC')
62 mimebundle_formatter = ForwardDeclaredInstance('FormatterABC')
63 @default('mimebundle_formatter')
63 @default('mimebundle_formatter')
64 def _default_mime_formatter(self):
64 def _default_mime_formatter(self):
65 return MimeBundleFormatter(parent=self)
65 return MimeBundleFormatter(parent=self)
66
66
67 # A dict of formatter whose keys are format types (MIME types) and whose
67 # A dict of formatter whose keys are format types (MIME types) and whose
68 # values are subclasses of BaseFormatter.
68 # values are subclasses of BaseFormatter.
69 formatters = Dict()
69 formatters = Dict()
70 @default('formatters')
70 @default('formatters')
71 def _formatters_default(self):
71 def _formatters_default(self):
72 """Activate the default formatters."""
72 """Activate the default formatters."""
73 formatter_classes = [
73 formatter_classes = [
74 PlainTextFormatter,
74 PlainTextFormatter,
75 HTMLFormatter,
75 HTMLFormatter,
76 MarkdownFormatter,
76 MarkdownFormatter,
77 SVGFormatter,
77 SVGFormatter,
78 PNGFormatter,
78 PNGFormatter,
79 PDFFormatter,
79 PDFFormatter,
80 JPEGFormatter,
80 JPEGFormatter,
81 LatexFormatter,
81 LatexFormatter,
82 JSONFormatter,
82 JSONFormatter,
83 JavascriptFormatter
83 JavascriptFormatter
84 ]
84 ]
85 d = {}
85 d = {}
86 for cls in formatter_classes:
86 for cls in formatter_classes:
87 f = cls(parent=self)
87 f = cls(parent=self)
88 d[f.format_type] = f
88 d[f.format_type] = f
89 return d
89 return d
90
90
91 def format(self, obj, include=None, exclude=None):
91 def format(self, obj, include=None, exclude=None):
92 """Return a format data dict for an object.
92 """Return a format data dict for an object.
93
93
94 By default all format types will be computed.
94 By default all format types will be computed.
95
95
96 The following MIME types are usually implemented:
96 The following MIME types are usually implemented:
97
97
98 * text/plain
98 * text/plain
99 * text/html
99 * text/html
100 * text/markdown
100 * text/markdown
101 * text/latex
101 * text/latex
102 * application/json
102 * application/json
103 * application/javascript
103 * application/javascript
104 * application/pdf
104 * application/pdf
105 * image/png
105 * image/png
106 * image/jpeg
106 * image/jpeg
107 * image/svg+xml
107 * image/svg+xml
108
108
109 Parameters
109 Parameters
110 ----------
110 ----------
111 obj : object
111 obj : object
112 The Python object whose format data will be computed.
112 The Python object whose format data will be computed.
113 include : list, tuple or set; optional
113 include : list, tuple or set; optional
114 A list of format type strings (MIME types) to include in the
114 A list of format type strings (MIME types) to include in the
115 format data dict. If this is set *only* the format types included
115 format data dict. If this is set *only* the format types included
116 in this list will be computed.
116 in this list will be computed.
117 exclude : list, tuple or set; optional
117 exclude : list, tuple or set; optional
118 A list of format type string (MIME types) to exclude in the format
118 A list of format type string (MIME types) to exclude in the format
119 data dict. If this is set all format types will be computed,
119 data dict. If this is set all format types will be computed,
120 except for those included in this argument.
120 except for those included in this argument.
121 Mimetypes present in exclude will take precedence over the ones in include
121 Mimetypes present in exclude will take precedence over the ones in include
122
122
123 Returns
123 Returns
124 -------
124 -------
125 (format_dict, metadata_dict) : tuple of two dicts
125 (format_dict, metadata_dict) : tuple of two dicts
126
126
127 format_dict is a dictionary of key/value pairs, one of each format that was
127 format_dict is a dictionary of key/value pairs, one of each format that was
128 generated for the object. The keys are the format types, which
128 generated for the object. The keys are the format types, which
129 will usually be MIME type strings and the values and JSON'able
129 will usually be MIME type strings and the values and JSON'able
130 data structure containing the raw data for the representation in
130 data structure containing the raw data for the representation in
131 that format.
131 that format.
132
132
133 metadata_dict is a dictionary of metadata about each mime-type output.
133 metadata_dict is a dictionary of metadata about each mime-type output.
134 Its keys will be a strict subset of the keys in format_dict.
134 Its keys will be a strict subset of the keys in format_dict.
135
135
136 Notes
136 Notes
137 -----
137 -----
138
138
139 If an object implement `_repr_mimebundle_` as well as various
139 If an object implement `_repr_mimebundle_` as well as various
140 `_repr_*_`, the data returned by `_repr_mimebundle_` will take
140 `_repr_*_`, the data returned by `_repr_mimebundle_` will take
141 precedence and the corresponding `_repr_*_` for this mimetype will
141 precedence and the corresponding `_repr_*_` for this mimetype will
142 not be called.
142 not be called.
143
143
144 """
144 """
145 format_dict = {}
145 format_dict = {}
146 md_dict = {}
146 md_dict = {}
147
147
148 if self.ipython_display_formatter(obj):
148 if self.ipython_display_formatter(obj):
149 # object handled itself, don't proceed
149 # object handled itself, don't proceed
150 return {}, {}
150 return {}, {}
151
151
152 format_dict, md_dict = self.mimebundle_formatter(obj, include=include, exclude=exclude)
152 format_dict, md_dict = self.mimebundle_formatter(obj, include=include, exclude=exclude)
153
153
154 if format_dict or md_dict:
154 if format_dict or md_dict:
155 if include:
155 if include:
156 format_dict = {k:v for k,v in format_dict.items() if k in include}
156 format_dict = {k:v for k,v in format_dict.items() if k in include}
157 md_dict = {k:v for k,v in md_dict.items() if k in include}
157 md_dict = {k:v for k,v in md_dict.items() if k in include}
158 if exclude:
158 if exclude:
159 format_dict = {k:v for k,v in format_dict.items() if k not in exclude}
159 format_dict = {k:v for k,v in format_dict.items() if k not in exclude}
160 md_dict = {k:v for k,v in md_dict.items() if k not in exclude}
160 md_dict = {k:v for k,v in md_dict.items() if k not in exclude}
161
161
162 for format_type, formatter in self.formatters.items():
162 for format_type, formatter in self.formatters.items():
163 if format_type in format_dict:
163 if format_type in format_dict:
164 # already got it from mimebundle, don't render again
164 # already got it from mimebundle, don't render again
165 continue
165 continue
166 if include and format_type not in include:
166 if include and format_type not in include:
167 continue
167 continue
168 if exclude and format_type in exclude:
168 if exclude and format_type in exclude:
169 continue
169 continue
170
170
171 md = None
171 md = None
172 try:
172 try:
173 data = formatter(obj)
173 data = formatter(obj)
174 except:
174 except:
175 # FIXME: log the exception
175 # FIXME: log the exception
176 raise
176 raise
177
177
178 # formatters can return raw data or (data, metadata)
178 # formatters can return raw data or (data, metadata)
179 if isinstance(data, tuple) and len(data) == 2:
179 if isinstance(data, tuple) and len(data) == 2:
180 data, md = data
180 data, md = data
181
181
182 if data is not None:
182 if data is not None:
183 format_dict[format_type] = data
183 format_dict[format_type] = data
184 if md is not None:
184 if md is not None:
185 md_dict[format_type] = md
185 md_dict[format_type] = md
186 return format_dict, md_dict
186 return format_dict, md_dict
187
187
188 @property
188 @property
189 def format_types(self):
189 def format_types(self):
190 """Return the format types (MIME types) of the active formatters."""
190 """Return the format types (MIME types) of the active formatters."""
191 return list(self.formatters.keys())
191 return list(self.formatters.keys())
192
192
193
193
194 #-----------------------------------------------------------------------------
194 #-----------------------------------------------------------------------------
195 # Formatters for specific format types (text, html, svg, etc.)
195 # Formatters for specific format types (text, html, svg, etc.)
196 #-----------------------------------------------------------------------------
196 #-----------------------------------------------------------------------------
197
197
198
198
199 def _safe_repr(obj):
199 def _safe_repr(obj):
200 """Try to return a repr of an object
200 """Try to return a repr of an object
201
201
202 always returns a string, at least.
202 always returns a string, at least.
203 """
203 """
204 try:
204 try:
205 return repr(obj)
205 return repr(obj)
206 except Exception as e:
206 except Exception as e:
207 return "un-repr-able object (%r)" % e
207 return "un-repr-able object (%r)" % e
208
208
209
209
210 class FormatterWarning(UserWarning):
210 class FormatterWarning(UserWarning):
211 """Warning class for errors in formatters"""
211 """Warning class for errors in formatters"""
212
212
213 @decorator
213 @decorator
214 def catch_format_error(method, self, *args, **kwargs):
214 def catch_format_error(method, self, *args, **kwargs):
215 """show traceback on failed format call"""
215 """show traceback on failed format call"""
216 try:
216 try:
217 r = method(self, *args, **kwargs)
217 r = method(self, *args, **kwargs)
218 except NotImplementedError:
218 except NotImplementedError:
219 # don't warn on NotImplementedErrors
219 # don't warn on NotImplementedErrors
220 return None
220 return self._check_return(None, args[0])
221 except Exception:
221 except Exception:
222 exc_info = sys.exc_info()
222 exc_info = sys.exc_info()
223 ip = get_ipython()
223 ip = get_ipython()
224 if ip is not None:
224 if ip is not None:
225 ip.showtraceback(exc_info)
225 ip.showtraceback(exc_info)
226 else:
226 else:
227 traceback.print_exception(*exc_info)
227 traceback.print_exception(*exc_info)
228 return None
228 return self._check_return(None, args[0])
229 return self._check_return(r, args[0])
229 return self._check_return(r, args[0])
230
230
231
231
232 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
232 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
233 """ Abstract base class for Formatters.
233 """ Abstract base class for Formatters.
234
234
235 A formatter is a callable class that is responsible for computing the
235 A formatter is a callable class that is responsible for computing the
236 raw format data for a particular format type (MIME type). For example,
236 raw format data for a particular format type (MIME type). For example,
237 an HTML formatter would have a format type of `text/html` and would return
237 an HTML formatter would have a format type of `text/html` and would return
238 the HTML representation of the object when called.
238 the HTML representation of the object when called.
239 """
239 """
240
240
241 # The format type of the data returned, usually a MIME type.
241 # The format type of the data returned, usually a MIME type.
242 format_type = 'text/plain'
242 format_type = 'text/plain'
243
243
244 # Is the formatter enabled...
244 # Is the formatter enabled...
245 enabled = True
245 enabled = True
246
246
247 @abc.abstractmethod
247 @abc.abstractmethod
248 def __call__(self, obj):
248 def __call__(self, obj):
249 """Return a JSON'able representation of the object.
249 """Return a JSON'able representation of the object.
250
250
251 If the object cannot be formatted by this formatter,
251 If the object cannot be formatted by this formatter,
252 warn and return None.
252 warn and return None.
253 """
253 """
254 return repr(obj)
254 return repr(obj)
255
255
256
256
257 def _mod_name_key(typ):
257 def _mod_name_key(typ):
258 """Return a (__module__, __name__) tuple for a type.
258 """Return a (__module__, __name__) tuple for a type.
259
259
260 Used as key in Formatter.deferred_printers.
260 Used as key in Formatter.deferred_printers.
261 """
261 """
262 module = getattr(typ, '__module__', None)
262 module = getattr(typ, '__module__', None)
263 name = getattr(typ, '__name__', None)
263 name = getattr(typ, '__name__', None)
264 return (module, name)
264 return (module, name)
265
265
266
266
267 def _get_type(obj):
267 def _get_type(obj):
268 """Return the type of an instance (old and new-style)"""
268 """Return the type of an instance (old and new-style)"""
269 return getattr(obj, '__class__', None) or type(obj)
269 return getattr(obj, '__class__', None) or type(obj)
270
270
271
271
272 _raise_key_error = Sentinel('_raise_key_error', __name__,
272 _raise_key_error = Sentinel('_raise_key_error', __name__,
273 """
273 """
274 Special value to raise a KeyError
274 Special value to raise a KeyError
275
275
276 Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop`
276 Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop`
277 """)
277 """)
278
278
279
279
280 class BaseFormatter(Configurable):
280 class BaseFormatter(Configurable):
281 """A base formatter class that is configurable.
281 """A base formatter class that is configurable.
282
282
283 This formatter should usually be used as the base class of all formatters.
283 This formatter should usually be used as the base class of all formatters.
284 It is a traited :class:`Configurable` class and includes an extensible
284 It is a traited :class:`Configurable` class and includes an extensible
285 API for users to determine how their objects are formatted. The following
285 API for users to determine how their objects are formatted. The following
286 logic is used to find a function to format an given object.
286 logic is used to find a function to format an given object.
287
287
288 1. The object is introspected to see if it has a method with the name
288 1. The object is introspected to see if it has a method with the name
289 :attr:`print_method`. If is does, that object is passed to that method
289 :attr:`print_method`. If is does, that object is passed to that method
290 for formatting.
290 for formatting.
291 2. If no print method is found, three internal dictionaries are consulted
291 2. If no print method is found, three internal dictionaries are consulted
292 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
292 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
293 and :attr:`deferred_printers`.
293 and :attr:`deferred_printers`.
294
294
295 Users should use these dictionaries to register functions that will be
295 Users should use these dictionaries to register functions that will be
296 used to compute the format data for their objects (if those objects don't
296 used to compute the format data for their objects (if those objects don't
297 have the special print methods). The easiest way of using these
297 have the special print methods). The easiest way of using these
298 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
298 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
299 methods.
299 methods.
300
300
301 If no function/callable is found to compute the format data, ``None`` is
301 If no function/callable is found to compute the format data, ``None`` is
302 returned and this format type is not used.
302 returned and this format type is not used.
303 """
303 """
304
304
305 format_type = Unicode('text/plain')
305 format_type = Unicode('text/plain')
306 _return_type = string_types
306 _return_type = string_types
307
307
308 enabled = Bool(True).tag(config=True)
308 enabled = Bool(True).tag(config=True)
309
309
310 print_method = ObjectName('__repr__')
310 print_method = ObjectName('__repr__')
311
311
312 # The singleton printers.
312 # The singleton printers.
313 # Maps the IDs of the builtin singleton objects to the format functions.
313 # Maps the IDs of the builtin singleton objects to the format functions.
314 singleton_printers = Dict().tag(config=True)
314 singleton_printers = Dict().tag(config=True)
315
315
316 # The type-specific printers.
316 # The type-specific printers.
317 # Map type objects to the format functions.
317 # Map type objects to the format functions.
318 type_printers = Dict().tag(config=True)
318 type_printers = Dict().tag(config=True)
319
319
320 # The deferred-import type-specific printers.
320 # The deferred-import type-specific printers.
321 # Map (modulename, classname) pairs to the format functions.
321 # Map (modulename, classname) pairs to the format functions.
322 deferred_printers = Dict().tag(config=True)
322 deferred_printers = Dict().tag(config=True)
323
323
324 @catch_format_error
324 @catch_format_error
325 def __call__(self, obj):
325 def __call__(self, obj):
326 """Compute the format for an object."""
326 """Compute the format for an object."""
327 if self.enabled:
327 if self.enabled:
328 # lookup registered printer
328 # lookup registered printer
329 try:
329 try:
330 printer = self.lookup(obj)
330 printer = self.lookup(obj)
331 except KeyError:
331 except KeyError:
332 pass
332 pass
333 else:
333 else:
334 return printer(obj)
334 return printer(obj)
335 # Finally look for special method names
335 # Finally look for special method names
336 method = get_real_method(obj, self.print_method)
336 method = get_real_method(obj, self.print_method)
337 if method is not None:
337 if method is not None:
338 return method()
338 return method()
339 return None
339 return None
340 else:
340 else:
341 return None
341 return None
342
342
343 def __contains__(self, typ):
343 def __contains__(self, typ):
344 """map in to lookup_by_type"""
344 """map in to lookup_by_type"""
345 try:
345 try:
346 self.lookup_by_type(typ)
346 self.lookup_by_type(typ)
347 except KeyError:
347 except KeyError:
348 return False
348 return False
349 else:
349 else:
350 return True
350 return True
351
351
352 def _check_return(self, r, obj):
352 def _check_return(self, r, obj):
353 """Check that a return value is appropriate
353 """Check that a return value is appropriate
354
354
355 Return the value if so, None otherwise, warning if invalid.
355 Return the value if so, None otherwise, warning if invalid.
356 """
356 """
357 if r is None or isinstance(r, self._return_type) or \
357 if r is None or isinstance(r, self._return_type) or \
358 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
358 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
359 return r
359 return r
360 else:
360 else:
361 warnings.warn(
361 warnings.warn(
362 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
362 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
363 (self.format_type, type(r), self._return_type, _safe_repr(obj)),
363 (self.format_type, type(r), self._return_type, _safe_repr(obj)),
364 FormatterWarning
364 FormatterWarning
365 )
365 )
366
366
367 def lookup(self, obj):
367 def lookup(self, obj):
368 """Look up the formatter for a given instance.
368 """Look up the formatter for a given instance.
369
369
370 Parameters
370 Parameters
371 ----------
371 ----------
372 obj : object instance
372 obj : object instance
373
373
374 Returns
374 Returns
375 -------
375 -------
376 f : callable
376 f : callable
377 The registered formatting callable for the type.
377 The registered formatting callable for the type.
378
378
379 Raises
379 Raises
380 ------
380 ------
381 KeyError if the type has not been registered.
381 KeyError if the type has not been registered.
382 """
382 """
383 # look for singleton first
383 # look for singleton first
384 obj_id = id(obj)
384 obj_id = id(obj)
385 if obj_id in self.singleton_printers:
385 if obj_id in self.singleton_printers:
386 return self.singleton_printers[obj_id]
386 return self.singleton_printers[obj_id]
387 # then lookup by type
387 # then lookup by type
388 return self.lookup_by_type(_get_type(obj))
388 return self.lookup_by_type(_get_type(obj))
389
389
390 def lookup_by_type(self, typ):
390 def lookup_by_type(self, typ):
391 """Look up the registered formatter for a type.
391 """Look up the registered formatter for a type.
392
392
393 Parameters
393 Parameters
394 ----------
394 ----------
395 typ : type or '__module__.__name__' string for a type
395 typ : type or '__module__.__name__' string for a type
396
396
397 Returns
397 Returns
398 -------
398 -------
399 f : callable
399 f : callable
400 The registered formatting callable for the type.
400 The registered formatting callable for the type.
401
401
402 Raises
402 Raises
403 ------
403 ------
404 KeyError if the type has not been registered.
404 KeyError if the type has not been registered.
405 """
405 """
406 if isinstance(typ, string_types):
406 if isinstance(typ, string_types):
407 typ_key = tuple(typ.rsplit('.',1))
407 typ_key = tuple(typ.rsplit('.',1))
408 if typ_key not in self.deferred_printers:
408 if typ_key not in self.deferred_printers:
409 # We may have it cached in the type map. We will have to
409 # We may have it cached in the type map. We will have to
410 # iterate over all of the types to check.
410 # iterate over all of the types to check.
411 for cls in self.type_printers:
411 for cls in self.type_printers:
412 if _mod_name_key(cls) == typ_key:
412 if _mod_name_key(cls) == typ_key:
413 return self.type_printers[cls]
413 return self.type_printers[cls]
414 else:
414 else:
415 return self.deferred_printers[typ_key]
415 return self.deferred_printers[typ_key]
416 else:
416 else:
417 for cls in pretty._get_mro(typ):
417 for cls in pretty._get_mro(typ):
418 if cls in self.type_printers or self._in_deferred_types(cls):
418 if cls in self.type_printers or self._in_deferred_types(cls):
419 return self.type_printers[cls]
419 return self.type_printers[cls]
420
420
421 # If we have reached here, the lookup failed.
421 # If we have reached here, the lookup failed.
422 raise KeyError("No registered printer for {0!r}".format(typ))
422 raise KeyError("No registered printer for {0!r}".format(typ))
423
423
424 def for_type(self, typ, func=None):
424 def for_type(self, typ, func=None):
425 """Add a format function for a given type.
425 """Add a format function for a given type.
426
426
427 Parameters
427 Parameters
428 -----------
428 -----------
429 typ : type or '__module__.__name__' string for a type
429 typ : type or '__module__.__name__' string for a type
430 The class of the object that will be formatted using `func`.
430 The class of the object that will be formatted using `func`.
431 func : callable
431 func : callable
432 A callable for computing the format data.
432 A callable for computing the format data.
433 `func` will be called with the object to be formatted,
433 `func` will be called with the object to be formatted,
434 and will return the raw data in this formatter's format.
434 and will return the raw data in this formatter's format.
435 Subclasses may use a different call signature for the
435 Subclasses may use a different call signature for the
436 `func` argument.
436 `func` argument.
437
437
438 If `func` is None or not specified, there will be no change,
438 If `func` is None or not specified, there will be no change,
439 only returning the current value.
439 only returning the current value.
440
440
441 Returns
441 Returns
442 -------
442 -------
443 oldfunc : callable
443 oldfunc : callable
444 The currently registered callable.
444 The currently registered callable.
445 If you are registering a new formatter,
445 If you are registering a new formatter,
446 this will be the previous value (to enable restoring later).
446 this will be the previous value (to enable restoring later).
447 """
447 """
448 # if string given, interpret as 'pkg.module.class_name'
448 # if string given, interpret as 'pkg.module.class_name'
449 if isinstance(typ, string_types):
449 if isinstance(typ, string_types):
450 type_module, type_name = typ.rsplit('.', 1)
450 type_module, type_name = typ.rsplit('.', 1)
451 return self.for_type_by_name(type_module, type_name, func)
451 return self.for_type_by_name(type_module, type_name, func)
452
452
453 try:
453 try:
454 oldfunc = self.lookup_by_type(typ)
454 oldfunc = self.lookup_by_type(typ)
455 except KeyError:
455 except KeyError:
456 oldfunc = None
456 oldfunc = None
457
457
458 if func is not None:
458 if func is not None:
459 self.type_printers[typ] = func
459 self.type_printers[typ] = func
460
460
461 return oldfunc
461 return oldfunc
462
462
463 def for_type_by_name(self, type_module, type_name, func=None):
463 def for_type_by_name(self, type_module, type_name, func=None):
464 """Add a format function for a type specified by the full dotted
464 """Add a format function for a type specified by the full dotted
465 module and name of the type, rather than the type of the object.
465 module and name of the type, rather than the type of the object.
466
466
467 Parameters
467 Parameters
468 ----------
468 ----------
469 type_module : str
469 type_module : str
470 The full dotted name of the module the type is defined in, like
470 The full dotted name of the module the type is defined in, like
471 ``numpy``.
471 ``numpy``.
472 type_name : str
472 type_name : str
473 The name of the type (the class name), like ``dtype``
473 The name of the type (the class name), like ``dtype``
474 func : callable
474 func : callable
475 A callable for computing the format data.
475 A callable for computing the format data.
476 `func` will be called with the object to be formatted,
476 `func` will be called with the object to be formatted,
477 and will return the raw data in this formatter's format.
477 and will return the raw data in this formatter's format.
478 Subclasses may use a different call signature for the
478 Subclasses may use a different call signature for the
479 `func` argument.
479 `func` argument.
480
480
481 If `func` is None or unspecified, there will be no change,
481 If `func` is None or unspecified, there will be no change,
482 only returning the current value.
482 only returning the current value.
483
483
484 Returns
484 Returns
485 -------
485 -------
486 oldfunc : callable
486 oldfunc : callable
487 The currently registered callable.
487 The currently registered callable.
488 If you are registering a new formatter,
488 If you are registering a new formatter,
489 this will be the previous value (to enable restoring later).
489 this will be the previous value (to enable restoring later).
490 """
490 """
491 key = (type_module, type_name)
491 key = (type_module, type_name)
492
492
493 try:
493 try:
494 oldfunc = self.lookup_by_type("%s.%s" % key)
494 oldfunc = self.lookup_by_type("%s.%s" % key)
495 except KeyError:
495 except KeyError:
496 oldfunc = None
496 oldfunc = None
497
497
498 if func is not None:
498 if func is not None:
499 self.deferred_printers[key] = func
499 self.deferred_printers[key] = func
500 return oldfunc
500 return oldfunc
501
501
502 def pop(self, typ, default=_raise_key_error):
502 def pop(self, typ, default=_raise_key_error):
503 """Pop a formatter for the given type.
503 """Pop a formatter for the given type.
504
504
505 Parameters
505 Parameters
506 ----------
506 ----------
507 typ : type or '__module__.__name__' string for a type
507 typ : type or '__module__.__name__' string for a type
508 default : object
508 default : object
509 value to be returned if no formatter is registered for typ.
509 value to be returned if no formatter is registered for typ.
510
510
511 Returns
511 Returns
512 -------
512 -------
513 obj : object
513 obj : object
514 The last registered object for the type.
514 The last registered object for the type.
515
515
516 Raises
516 Raises
517 ------
517 ------
518 KeyError if the type is not registered and default is not specified.
518 KeyError if the type is not registered and default is not specified.
519 """
519 """
520
520
521 if isinstance(typ, string_types):
521 if isinstance(typ, string_types):
522 typ_key = tuple(typ.rsplit('.',1))
522 typ_key = tuple(typ.rsplit('.',1))
523 if typ_key not in self.deferred_printers:
523 if typ_key not in self.deferred_printers:
524 # We may have it cached in the type map. We will have to
524 # We may have it cached in the type map. We will have to
525 # iterate over all of the types to check.
525 # iterate over all of the types to check.
526 for cls in self.type_printers:
526 for cls in self.type_printers:
527 if _mod_name_key(cls) == typ_key:
527 if _mod_name_key(cls) == typ_key:
528 old = self.type_printers.pop(cls)
528 old = self.type_printers.pop(cls)
529 break
529 break
530 else:
530 else:
531 old = default
531 old = default
532 else:
532 else:
533 old = self.deferred_printers.pop(typ_key)
533 old = self.deferred_printers.pop(typ_key)
534 else:
534 else:
535 if typ in self.type_printers:
535 if typ in self.type_printers:
536 old = self.type_printers.pop(typ)
536 old = self.type_printers.pop(typ)
537 else:
537 else:
538 old = self.deferred_printers.pop(_mod_name_key(typ), default)
538 old = self.deferred_printers.pop(_mod_name_key(typ), default)
539 if old is _raise_key_error:
539 if old is _raise_key_error:
540 raise KeyError("No registered value for {0!r}".format(typ))
540 raise KeyError("No registered value for {0!r}".format(typ))
541 return old
541 return old
542
542
543 def _in_deferred_types(self, cls):
543 def _in_deferred_types(self, cls):
544 """
544 """
545 Check if the given class is specified in the deferred type registry.
545 Check if the given class is specified in the deferred type registry.
546
546
547 Successful matches will be moved to the regular type registry for future use.
547 Successful matches will be moved to the regular type registry for future use.
548 """
548 """
549 mod = getattr(cls, '__module__', None)
549 mod = getattr(cls, '__module__', None)
550 name = getattr(cls, '__name__', None)
550 name = getattr(cls, '__name__', None)
551 key = (mod, name)
551 key = (mod, name)
552 if key in self.deferred_printers:
552 if key in self.deferred_printers:
553 # Move the printer over to the regular registry.
553 # Move the printer over to the regular registry.
554 printer = self.deferred_printers.pop(key)
554 printer = self.deferred_printers.pop(key)
555 self.type_printers[cls] = printer
555 self.type_printers[cls] = printer
556 return True
556 return True
557 return False
557 return False
558
558
559
559
560 class PlainTextFormatter(BaseFormatter):
560 class PlainTextFormatter(BaseFormatter):
561 """The default pretty-printer.
561 """The default pretty-printer.
562
562
563 This uses :mod:`IPython.lib.pretty` to compute the format data of
563 This uses :mod:`IPython.lib.pretty` to compute the format data of
564 the object. If the object cannot be pretty printed, :func:`repr` is used.
564 the object. If the object cannot be pretty printed, :func:`repr` is used.
565 See the documentation of :mod:`IPython.lib.pretty` for details on
565 See the documentation of :mod:`IPython.lib.pretty` for details on
566 how to write pretty printers. Here is a simple example::
566 how to write pretty printers. Here is a simple example::
567
567
568 def dtype_pprinter(obj, p, cycle):
568 def dtype_pprinter(obj, p, cycle):
569 if cycle:
569 if cycle:
570 return p.text('dtype(...)')
570 return p.text('dtype(...)')
571 if hasattr(obj, 'fields'):
571 if hasattr(obj, 'fields'):
572 if obj.fields is None:
572 if obj.fields is None:
573 p.text(repr(obj))
573 p.text(repr(obj))
574 else:
574 else:
575 p.begin_group(7, 'dtype([')
575 p.begin_group(7, 'dtype([')
576 for i, field in enumerate(obj.descr):
576 for i, field in enumerate(obj.descr):
577 if i > 0:
577 if i > 0:
578 p.text(',')
578 p.text(',')
579 p.breakable()
579 p.breakable()
580 p.pretty(field)
580 p.pretty(field)
581 p.end_group(7, '])')
581 p.end_group(7, '])')
582 """
582 """
583
583
584 # The format type of data returned.
584 # The format type of data returned.
585 format_type = Unicode('text/plain')
585 format_type = Unicode('text/plain')
586
586
587 # This subclass ignores this attribute as it always need to return
587 # This subclass ignores this attribute as it always need to return
588 # something.
588 # something.
589 enabled = Bool(True).tag(config=False)
589 enabled = Bool(True).tag(config=False)
590
590
591 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH,
591 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH,
592 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
592 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
593
593
594 Set to 0 to disable truncation.
594 Set to 0 to disable truncation.
595 """
595 """
596 ).tag(config=True)
596 ).tag(config=True)
597
597
598 # Look for a _repr_pretty_ methods to use for pretty printing.
598 # Look for a _repr_pretty_ methods to use for pretty printing.
599 print_method = ObjectName('_repr_pretty_')
599 print_method = ObjectName('_repr_pretty_')
600
600
601 # Whether to pretty-print or not.
601 # Whether to pretty-print or not.
602 pprint = Bool(True).tag(config=True)
602 pprint = Bool(True).tag(config=True)
603
603
604 # Whether to be verbose or not.
604 # Whether to be verbose or not.
605 verbose = Bool(False).tag(config=True)
605 verbose = Bool(False).tag(config=True)
606
606
607 # The maximum width.
607 # The maximum width.
608 max_width = Integer(79).tag(config=True)
608 max_width = Integer(79).tag(config=True)
609
609
610 # The newline character.
610 # The newline character.
611 newline = Unicode('\n').tag(config=True)
611 newline = Unicode('\n').tag(config=True)
612
612
613 # format-string for pprinting floats
613 # format-string for pprinting floats
614 float_format = Unicode('%r')
614 float_format = Unicode('%r')
615 # setter for float precision, either int or direct format-string
615 # setter for float precision, either int or direct format-string
616 float_precision = CUnicode('').tag(config=True)
616 float_precision = CUnicode('').tag(config=True)
617
617
618 @observe('float_precision')
618 @observe('float_precision')
619 def _float_precision_changed(self, change):
619 def _float_precision_changed(self, change):
620 """float_precision changed, set float_format accordingly.
620 """float_precision changed, set float_format accordingly.
621
621
622 float_precision can be set by int or str.
622 float_precision can be set by int or str.
623 This will set float_format, after interpreting input.
623 This will set float_format, after interpreting input.
624 If numpy has been imported, numpy print precision will also be set.
624 If numpy has been imported, numpy print precision will also be set.
625
625
626 integer `n` sets format to '%.nf', otherwise, format set directly.
626 integer `n` sets format to '%.nf', otherwise, format set directly.
627
627
628 An empty string returns to defaults (repr for float, 8 for numpy).
628 An empty string returns to defaults (repr for float, 8 for numpy).
629
629
630 This parameter can be set via the '%precision' magic.
630 This parameter can be set via the '%precision' magic.
631 """
631 """
632
632
633 new = change['new']
633 new = change['new']
634 if '%' in new:
634 if '%' in new:
635 # got explicit format string
635 # got explicit format string
636 fmt = new
636 fmt = new
637 try:
637 try:
638 fmt%3.14159
638 fmt%3.14159
639 except Exception:
639 except Exception:
640 raise ValueError("Precision must be int or format string, not %r"%new)
640 raise ValueError("Precision must be int or format string, not %r"%new)
641 elif new:
641 elif new:
642 # otherwise, should be an int
642 # otherwise, should be an int
643 try:
643 try:
644 i = int(new)
644 i = int(new)
645 assert i >= 0
645 assert i >= 0
646 except ValueError:
646 except ValueError:
647 raise ValueError("Precision must be int or format string, not %r"%new)
647 raise ValueError("Precision must be int or format string, not %r"%new)
648 except AssertionError:
648 except AssertionError:
649 raise ValueError("int precision must be non-negative, not %r"%i)
649 raise ValueError("int precision must be non-negative, not %r"%i)
650
650
651 fmt = '%%.%if'%i
651 fmt = '%%.%if'%i
652 if 'numpy' in sys.modules:
652 if 'numpy' in sys.modules:
653 # set numpy precision if it has been imported
653 # set numpy precision if it has been imported
654 import numpy
654 import numpy
655 numpy.set_printoptions(precision=i)
655 numpy.set_printoptions(precision=i)
656 else:
656 else:
657 # default back to repr
657 # default back to repr
658 fmt = '%r'
658 fmt = '%r'
659 if 'numpy' in sys.modules:
659 if 'numpy' in sys.modules:
660 import numpy
660 import numpy
661 # numpy default is 8
661 # numpy default is 8
662 numpy.set_printoptions(precision=8)
662 numpy.set_printoptions(precision=8)
663 self.float_format = fmt
663 self.float_format = fmt
664
664
665 # Use the default pretty printers from IPython.lib.pretty.
665 # Use the default pretty printers from IPython.lib.pretty.
666 @default('singleton_printers')
666 @default('singleton_printers')
667 def _singleton_printers_default(self):
667 def _singleton_printers_default(self):
668 return pretty._singleton_pprinters.copy()
668 return pretty._singleton_pprinters.copy()
669
669
670 @default('type_printers')
670 @default('type_printers')
671 def _type_printers_default(self):
671 def _type_printers_default(self):
672 d = pretty._type_pprinters.copy()
672 d = pretty._type_pprinters.copy()
673 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
673 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
674 return d
674 return d
675
675
676 @default('deferred_printers')
676 @default('deferred_printers')
677 def _deferred_printers_default(self):
677 def _deferred_printers_default(self):
678 return pretty._deferred_type_pprinters.copy()
678 return pretty._deferred_type_pprinters.copy()
679
679
680 #### FormatterABC interface ####
680 #### FormatterABC interface ####
681
681
682 @catch_format_error
682 @catch_format_error
683 def __call__(self, obj):
683 def __call__(self, obj):
684 """Compute the pretty representation of the object."""
684 """Compute the pretty representation of the object."""
685 if not self.pprint:
685 if not self.pprint:
686 return repr(obj)
686 return repr(obj)
687 else:
687 else:
688 # handle str and unicode on Python 2
688 # handle str and unicode on Python 2
689 # io.StringIO only accepts unicode,
689 # io.StringIO only accepts unicode,
690 # cStringIO doesn't handle unicode on py2,
690 # cStringIO doesn't handle unicode on py2,
691 # StringIO allows str, unicode but only ascii str
691 # StringIO allows str, unicode but only ascii str
692 stream = pretty.CUnicodeIO()
692 stream = pretty.CUnicodeIO()
693 printer = pretty.RepresentationPrinter(stream, self.verbose,
693 printer = pretty.RepresentationPrinter(stream, self.verbose,
694 self.max_width, self.newline,
694 self.max_width, self.newline,
695 max_seq_length=self.max_seq_length,
695 max_seq_length=self.max_seq_length,
696 singleton_pprinters=self.singleton_printers,
696 singleton_pprinters=self.singleton_printers,
697 type_pprinters=self.type_printers,
697 type_pprinters=self.type_printers,
698 deferred_pprinters=self.deferred_printers)
698 deferred_pprinters=self.deferred_printers)
699 printer.pretty(obj)
699 printer.pretty(obj)
700 printer.flush()
700 printer.flush()
701 return stream.getvalue()
701 return stream.getvalue()
702
702
703
703
704 class HTMLFormatter(BaseFormatter):
704 class HTMLFormatter(BaseFormatter):
705 """An HTML formatter.
705 """An HTML formatter.
706
706
707 To define the callables that compute the HTML representation of your
707 To define the callables that compute the HTML representation of your
708 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
708 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
709 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
710 this.
710 this.
711
711
712 The return value of this formatter should be a valid HTML snippet that
712 The return value of this formatter should be a valid HTML snippet that
713 could be injected into an existing DOM. It should *not* include the
713 could be injected into an existing DOM. It should *not* include the
714 ```<html>`` or ```<body>`` tags.
714 ```<html>`` or ```<body>`` tags.
715 """
715 """
716 format_type = Unicode('text/html')
716 format_type = Unicode('text/html')
717
717
718 print_method = ObjectName('_repr_html_')
718 print_method = ObjectName('_repr_html_')
719
719
720
720
721 class MarkdownFormatter(BaseFormatter):
721 class MarkdownFormatter(BaseFormatter):
722 """A Markdown formatter.
722 """A Markdown formatter.
723
723
724 To define the callables that compute the Markdown representation of your
724 To define the callables that compute the Markdown representation of your
725 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
725 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
726 or :meth:`for_type_by_name` methods to register functions that handle
726 or :meth:`for_type_by_name` methods to register functions that handle
727 this.
727 this.
728
728
729 The return value of this formatter should be a valid Markdown.
729 The return value of this formatter should be a valid Markdown.
730 """
730 """
731 format_type = Unicode('text/markdown')
731 format_type = Unicode('text/markdown')
732
732
733 print_method = ObjectName('_repr_markdown_')
733 print_method = ObjectName('_repr_markdown_')
734
734
735 class SVGFormatter(BaseFormatter):
735 class SVGFormatter(BaseFormatter):
736 """An SVG formatter.
736 """An SVG formatter.
737
737
738 To define the callables that compute the SVG representation of your
738 To define the callables that compute the SVG representation of your
739 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
739 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
740 or :meth:`for_type_by_name` methods to register functions that handle
740 or :meth:`for_type_by_name` methods to register functions that handle
741 this.
741 this.
742
742
743 The return value of this formatter should be valid SVG enclosed in
743 The return value of this formatter should be valid SVG enclosed in
744 ```<svg>``` tags, that could be injected into an existing DOM. It should
744 ```<svg>``` tags, that could be injected into an existing DOM. It should
745 *not* include the ```<html>`` or ```<body>`` tags.
745 *not* include the ```<html>`` or ```<body>`` tags.
746 """
746 """
747 format_type = Unicode('image/svg+xml')
747 format_type = Unicode('image/svg+xml')
748
748
749 print_method = ObjectName('_repr_svg_')
749 print_method = ObjectName('_repr_svg_')
750
750
751
751
752 class PNGFormatter(BaseFormatter):
752 class PNGFormatter(BaseFormatter):
753 """A PNG formatter.
753 """A PNG formatter.
754
754
755 To define the callables that compute the PNG representation of your
755 To define the callables that compute the PNG representation of your
756 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
756 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
757 or :meth:`for_type_by_name` methods to register functions that handle
757 or :meth:`for_type_by_name` methods to register functions that handle
758 this.
758 this.
759
759
760 The return value of this formatter should be raw PNG data, *not*
760 The return value of this formatter should be raw PNG data, *not*
761 base64 encoded.
761 base64 encoded.
762 """
762 """
763 format_type = Unicode('image/png')
763 format_type = Unicode('image/png')
764
764
765 print_method = ObjectName('_repr_png_')
765 print_method = ObjectName('_repr_png_')
766
766
767 _return_type = (bytes, unicode_type)
767 _return_type = (bytes, unicode_type)
768
768
769
769
770 class JPEGFormatter(BaseFormatter):
770 class JPEGFormatter(BaseFormatter):
771 """A JPEG formatter.
771 """A JPEG formatter.
772
772
773 To define the callables that compute the JPEG representation of your
773 To define the callables that compute the JPEG representation of your
774 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
774 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
775 or :meth:`for_type_by_name` methods to register functions that handle
775 or :meth:`for_type_by_name` methods to register functions that handle
776 this.
776 this.
777
777
778 The return value of this formatter should be raw JPEG data, *not*
778 The return value of this formatter should be raw JPEG data, *not*
779 base64 encoded.
779 base64 encoded.
780 """
780 """
781 format_type = Unicode('image/jpeg')
781 format_type = Unicode('image/jpeg')
782
782
783 print_method = ObjectName('_repr_jpeg_')
783 print_method = ObjectName('_repr_jpeg_')
784
784
785 _return_type = (bytes, unicode_type)
785 _return_type = (bytes, unicode_type)
786
786
787
787
788 class LatexFormatter(BaseFormatter):
788 class LatexFormatter(BaseFormatter):
789 """A LaTeX formatter.
789 """A LaTeX formatter.
790
790
791 To define the callables that compute the LaTeX representation of your
791 To define the callables that compute the LaTeX representation of your
792 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
792 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
793 or :meth:`for_type_by_name` methods to register functions that handle
793 or :meth:`for_type_by_name` methods to register functions that handle
794 this.
794 this.
795
795
796 The return value of this formatter should be a valid LaTeX equation,
796 The return value of this formatter should be a valid LaTeX equation,
797 enclosed in either ```$```, ```$$``` or another LaTeX equation
797 enclosed in either ```$```, ```$$``` or another LaTeX equation
798 environment.
798 environment.
799 """
799 """
800 format_type = Unicode('text/latex')
800 format_type = Unicode('text/latex')
801
801
802 print_method = ObjectName('_repr_latex_')
802 print_method = ObjectName('_repr_latex_')
803
803
804
804
805 class JSONFormatter(BaseFormatter):
805 class JSONFormatter(BaseFormatter):
806 """A JSON string formatter.
806 """A JSON string formatter.
807
807
808 To define the callables that compute the JSONable representation of
808 To define the callables that compute the JSONable representation of
809 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
809 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
810 or :meth:`for_type_by_name` methods to register functions that handle
810 or :meth:`for_type_by_name` methods to register functions that handle
811 this.
811 this.
812
812
813 The return value of this formatter should be a JSONable list or dict.
813 The return value of this formatter should be a JSONable list or dict.
814 JSON scalars (None, number, string) are not allowed, only dict or list containers.
814 JSON scalars (None, number, string) are not allowed, only dict or list containers.
815 """
815 """
816 format_type = Unicode('application/json')
816 format_type = Unicode('application/json')
817 _return_type = (list, dict)
817 _return_type = (list, dict)
818
818
819 print_method = ObjectName('_repr_json_')
819 print_method = ObjectName('_repr_json_')
820
820
821 def _check_return(self, r, obj):
821 def _check_return(self, r, obj):
822 """Check that a return value is appropriate
822 """Check that a return value is appropriate
823
823
824 Return the value if so, None otherwise, warning if invalid.
824 Return the value if so, None otherwise, warning if invalid.
825 """
825 """
826 if r is None:
826 if r is None:
827 return
827 return
828 md = None
828 md = None
829 if isinstance(r, tuple):
829 if isinstance(r, tuple):
830 # unpack data, metadata tuple for type checking on first element
830 # unpack data, metadata tuple for type checking on first element
831 r, md = r
831 r, md = r
832
832
833 # handle deprecated JSON-as-string form from IPython < 3
833 # handle deprecated JSON-as-string form from IPython < 3
834 if isinstance(r, string_types):
834 if isinstance(r, string_types):
835 warnings.warn("JSON expects JSONable list/dict containers, not JSON strings",
835 warnings.warn("JSON expects JSONable list/dict containers, not JSON strings",
836 FormatterWarning)
836 FormatterWarning)
837 r = json.loads(r)
837 r = json.loads(r)
838
838
839 if md is not None:
839 if md is not None:
840 # put the tuple back together
840 # put the tuple back together
841 r = (r, md)
841 r = (r, md)
842 return super(JSONFormatter, self)._check_return(r, obj)
842 return super(JSONFormatter, self)._check_return(r, obj)
843
843
844
844
845 class JavascriptFormatter(BaseFormatter):
845 class JavascriptFormatter(BaseFormatter):
846 """A Javascript formatter.
846 """A Javascript formatter.
847
847
848 To define the callables that compute the Javascript representation of
848 To define the callables that compute the Javascript representation of
849 your objects, define a :meth:`_repr_javascript_` method or use the
849 your objects, define a :meth:`_repr_javascript_` method or use the
850 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
850 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
851 that handle this.
851 that handle this.
852
852
853 The return value of this formatter should be valid Javascript code and
853 The return value of this formatter should be valid Javascript code and
854 should *not* be enclosed in ```<script>``` tags.
854 should *not* be enclosed in ```<script>``` tags.
855 """
855 """
856 format_type = Unicode('application/javascript')
856 format_type = Unicode('application/javascript')
857
857
858 print_method = ObjectName('_repr_javascript_')
858 print_method = ObjectName('_repr_javascript_')
859
859
860
860
861 class PDFFormatter(BaseFormatter):
861 class PDFFormatter(BaseFormatter):
862 """A PDF formatter.
862 """A PDF formatter.
863
863
864 To define the callables that compute the PDF representation of your
864 To define the callables that compute the PDF representation of your
865 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
865 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
866 or :meth:`for_type_by_name` methods to register functions that handle
866 or :meth:`for_type_by_name` methods to register functions that handle
867 this.
867 this.
868
868
869 The return value of this formatter should be raw PDF data, *not*
869 The return value of this formatter should be raw PDF data, *not*
870 base64 encoded.
870 base64 encoded.
871 """
871 """
872 format_type = Unicode('application/pdf')
872 format_type = Unicode('application/pdf')
873
873
874 print_method = ObjectName('_repr_pdf_')
874 print_method = ObjectName('_repr_pdf_')
875
875
876 _return_type = (bytes, unicode_type)
876 _return_type = (bytes, unicode_type)
877
877
878 class IPythonDisplayFormatter(BaseFormatter):
878 class IPythonDisplayFormatter(BaseFormatter):
879 """An escape-hatch Formatter for objects that know how to display themselves.
879 """An escape-hatch Formatter for objects that know how to display themselves.
880
880
881 To define the callables that compute the representation of your
881 To define the callables that compute the representation of your
882 objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
882 objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
883 or :meth:`for_type_by_name` methods to register functions that handle
883 or :meth:`for_type_by_name` methods to register functions that handle
884 this. Unlike mime-type displays, this method should not return anything,
884 this. Unlike mime-type displays, this method should not return anything,
885 instead calling any appropriate display methods itself.
885 instead calling any appropriate display methods itself.
886
886
887 This display formatter has highest priority.
887 This display formatter has highest priority.
888 If it fires, no other display formatter will be called.
888 If it fires, no other display formatter will be called.
889
889
890 Prior to IPython 6.1, `_ipython_display_` was the only way to display custom mime-types
890 Prior to IPython 6.1, `_ipython_display_` was the only way to display custom mime-types
891 without registering a new Formatter.
891 without registering a new Formatter.
892
892
893 IPython 6.1 introduces `_repr_mimebundle_` for displaying custom mime-types,
893 IPython 6.1 introduces `_repr_mimebundle_` for displaying custom mime-types,
894 so `_ipython_display_` should only be used for objects that require unusual
894 so `_ipython_display_` should only be used for objects that require unusual
895 display patterns, such as multiple display calls.
895 display patterns, such as multiple display calls.
896 """
896 """
897 print_method = ObjectName('_ipython_display_')
897 print_method = ObjectName('_ipython_display_')
898 _return_type = (type(None), bool)
898 _return_type = (type(None), bool)
899
899
900 @catch_format_error
900 @catch_format_error
901 def __call__(self, obj):
901 def __call__(self, obj):
902 """Compute the format for an object."""
902 """Compute the format for an object."""
903 if self.enabled:
903 if self.enabled:
904 # lookup registered printer
904 # lookup registered printer
905 try:
905 try:
906 printer = self.lookup(obj)
906 printer = self.lookup(obj)
907 except KeyError:
907 except KeyError:
908 pass
908 pass
909 else:
909 else:
910 printer(obj)
910 printer(obj)
911 return True
911 return True
912 # Finally look for special method names
912 # Finally look for special method names
913 method = get_real_method(obj, self.print_method)
913 method = get_real_method(obj, self.print_method)
914 if method is not None:
914 if method is not None:
915 method()
915 method()
916 return True
916 return True
917
917
918
918
919 class MimeBundleFormatter(BaseFormatter):
919 class MimeBundleFormatter(BaseFormatter):
920 """A Formatter for arbitrary mime-types.
920 """A Formatter for arbitrary mime-types.
921
921
922 Unlike other `_repr_<mimetype>_` methods,
922 Unlike other `_repr_<mimetype>_` methods,
923 `_repr_mimebundle_` should return mime-bundle data,
923 `_repr_mimebundle_` should return mime-bundle data,
924 either the mime-keyed `data` dictionary or the tuple `(data, metadata)`.
924 either the mime-keyed `data` dictionary or the tuple `(data, metadata)`.
925 Any mime-type is valid.
925 Any mime-type is valid.
926
926
927 To define the callables that compute the mime-bundle representation of your
927 To define the callables that compute the mime-bundle representation of your
928 objects, define a :meth:`_repr_mimebundle_` method or use the :meth:`for_type`
928 objects, define a :meth:`_repr_mimebundle_` method or use the :meth:`for_type`
929 or :meth:`for_type_by_name` methods to register functions that handle
929 or :meth:`for_type_by_name` methods to register functions that handle
930 this.
930 this.
931
931
932 .. versionadded:: 6.1
932 .. versionadded:: 6.1
933 """
933 """
934 print_method = ObjectName('_repr_mimebundle_')
934 print_method = ObjectName('_repr_mimebundle_')
935 _return_type = dict
935 _return_type = dict
936
936
937 def _check_return(self, r, obj):
937 def _check_return(self, r, obj):
938 r = super(MimeBundleFormatter, self)._check_return(r, obj)
938 r = super(MimeBundleFormatter, self)._check_return(r, obj)
939 # always return (data, metadata):
939 # always return (data, metadata):
940 if r is None:
940 if r is None:
941 return {}, {}
941 return {}, {}
942 if not isinstance(r, tuple):
942 if not isinstance(r, tuple):
943 return r, {}
943 return r, {}
944 return r
944 return r
945
945
946 @catch_format_error
946 @catch_format_error
947 def __call__(self, obj, include=None, exclude=None):
947 def __call__(self, obj, include=None, exclude=None):
948 """Compute the format for an object.
948 """Compute the format for an object.
949
949
950 Identical to parent's method but we pass extra parameters to the method.
950 Identical to parent's method but we pass extra parameters to the method.
951
951
952 Unlike other _repr_*_ `_repr_mimebundle_` should allow extra kwargs, in
952 Unlike other _repr_*_ `_repr_mimebundle_` should allow extra kwargs, in
953 particular `include` and `exclude`.
953 particular `include` and `exclude`.
954 """
954 """
955 if self.enabled:
955 if self.enabled:
956 # lookup registered printer
956 # lookup registered printer
957 try:
957 try:
958 printer = self.lookup(obj)
958 printer = self.lookup(obj)
959 except KeyError:
959 except KeyError:
960 pass
960 pass
961 else:
961 else:
962 return printer(obj)
962 return printer(obj)
963 # Finally look for special method names
963 # Finally look for special method names
964 method = get_real_method(obj, self.print_method)
964 method = get_real_method(obj, self.print_method)
965
965
966 if method is not None:
966 if method is not None:
967 d = {}
967 d = {}
968 d['include'] = include
968 d['include'] = include
969 d['exclude'] = exclude
969 d['exclude'] = exclude
970 return method(**d)
970 return method(**d)
971 return None
971 return None
972 else:
972 else:
973 return None
973 return None
974
974
975
975
976 FormatterABC.register(BaseFormatter)
976 FormatterABC.register(BaseFormatter)
977 FormatterABC.register(PlainTextFormatter)
977 FormatterABC.register(PlainTextFormatter)
978 FormatterABC.register(HTMLFormatter)
978 FormatterABC.register(HTMLFormatter)
979 FormatterABC.register(MarkdownFormatter)
979 FormatterABC.register(MarkdownFormatter)
980 FormatterABC.register(SVGFormatter)
980 FormatterABC.register(SVGFormatter)
981 FormatterABC.register(PNGFormatter)
981 FormatterABC.register(PNGFormatter)
982 FormatterABC.register(PDFFormatter)
982 FormatterABC.register(PDFFormatter)
983 FormatterABC.register(JPEGFormatter)
983 FormatterABC.register(JPEGFormatter)
984 FormatterABC.register(LatexFormatter)
984 FormatterABC.register(LatexFormatter)
985 FormatterABC.register(JSONFormatter)
985 FormatterABC.register(JSONFormatter)
986 FormatterABC.register(JavascriptFormatter)
986 FormatterABC.register(JavascriptFormatter)
987 FormatterABC.register(IPythonDisplayFormatter)
987 FormatterABC.register(IPythonDisplayFormatter)
988 FormatterABC.register(MimeBundleFormatter)
988 FormatterABC.register(MimeBundleFormatter)
989
989
990
990
991 def format_display_data(obj, include=None, exclude=None):
991 def format_display_data(obj, include=None, exclude=None):
992 """Return a format data dict for an object.
992 """Return a format data dict for an object.
993
993
994 By default all format types will be computed.
994 By default all format types will be computed.
995
995
996 The following MIME types are currently implemented:
996 The following MIME types are currently implemented:
997
997
998 * text/plain
998 * text/plain
999 * text/html
999 * text/html
1000 * text/markdown
1000 * text/markdown
1001 * text/latex
1001 * text/latex
1002 * application/json
1002 * application/json
1003 * application/javascript
1003 * application/javascript
1004 * application/pdf
1004 * application/pdf
1005 * image/png
1005 * image/png
1006 * image/jpeg
1006 * image/jpeg
1007 * image/svg+xml
1007 * image/svg+xml
1008
1008
1009 Parameters
1009 Parameters
1010 ----------
1010 ----------
1011 obj : object
1011 obj : object
1012 The Python object whose format data will be computed.
1012 The Python object whose format data will be computed.
1013
1013
1014 Returns
1014 Returns
1015 -------
1015 -------
1016 format_dict : dict
1016 format_dict : dict
1017 A dictionary of key/value pairs, one or each format that was
1017 A dictionary of key/value pairs, one or each format that was
1018 generated for the object. The keys are the format types, which
1018 generated for the object. The keys are the format types, which
1019 will usually be MIME type strings and the values and JSON'able
1019 will usually be MIME type strings and the values and JSON'able
1020 data structure containing the raw data for the representation in
1020 data structure containing the raw data for the representation in
1021 that format.
1021 that format.
1022 include : list or tuple, optional
1022 include : list or tuple, optional
1023 A list of format type strings (MIME types) to include in the
1023 A list of format type strings (MIME types) to include in the
1024 format data dict. If this is set *only* the format types included
1024 format data dict. If this is set *only* the format types included
1025 in this list will be computed.
1025 in this list will be computed.
1026 exclude : list or tuple, optional
1026 exclude : list or tuple, optional
1027 A list of format type string (MIME types) to exclue in the format
1027 A list of format type string (MIME types) to exclue in the format
1028 data dict. If this is set all format types will be computed,
1028 data dict. If this is set all format types will be computed,
1029 except for those included in this argument.
1029 except for those included in this argument.
1030 """
1030 """
1031 from IPython.core.interactiveshell import InteractiveShell
1031 from IPython.core.interactiveshell import InteractiveShell
1032
1032
1033 return InteractiveShell.instance().display_formatter.format(
1033 return InteractiveShell.instance().display_formatter.format(
1034 obj,
1034 obj,
1035 include,
1035 include,
1036 exclude
1036 exclude
1037 )
1037 )
@@ -1,523 +1,533 b''
1 """Tests for the Formatters."""
1 """Tests for the Formatters."""
2
2
3 import warnings
3 import warnings
4 from math import pi
4 from math import pi
5
5
6 try:
6 try:
7 import numpy
7 import numpy
8 except:
8 except:
9 numpy = None
9 numpy = None
10 import nose.tools as nt
10 import nose.tools as nt
11
11
12 from IPython import get_ipython
12 from IPython import get_ipython
13 from traitlets.config import Config
13 from traitlets.config import Config
14 from IPython.core.formatters import (
14 from IPython.core.formatters import (
15 PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key,
15 PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key,
16 DisplayFormatter, JSONFormatter,
16 DisplayFormatter, JSONFormatter,
17 )
17 )
18 from IPython.utils.io import capture_output
18 from IPython.utils.io import capture_output
19
19
20 class A(object):
20 class A(object):
21 def __repr__(self):
21 def __repr__(self):
22 return 'A()'
22 return 'A()'
23
23
24 class B(A):
24 class B(A):
25 def __repr__(self):
25 def __repr__(self):
26 return 'B()'
26 return 'B()'
27
27
28 class C:
28 class C:
29 pass
29 pass
30
30
31 class BadRepr(object):
31 class BadRepr(object):
32 def __repr__(self):
32 def __repr__(self):
33 raise ValueError("bad repr")
33 raise ValueError("bad repr")
34
34
35 class BadPretty(object):
35 class BadPretty(object):
36 _repr_pretty_ = None
36 _repr_pretty_ = None
37
37
38 class GoodPretty(object):
38 class GoodPretty(object):
39 def _repr_pretty_(self, pp, cycle):
39 def _repr_pretty_(self, pp, cycle):
40 pp.text('foo')
40 pp.text('foo')
41
41
42 def __repr__(self):
42 def __repr__(self):
43 return 'GoodPretty()'
43 return 'GoodPretty()'
44
44
45 def foo_printer(obj, pp, cycle):
45 def foo_printer(obj, pp, cycle):
46 pp.text('foo')
46 pp.text('foo')
47
47
48 def test_pretty():
48 def test_pretty():
49 f = PlainTextFormatter()
49 f = PlainTextFormatter()
50 f.for_type(A, foo_printer)
50 f.for_type(A, foo_printer)
51 nt.assert_equal(f(A()), 'foo')
51 nt.assert_equal(f(A()), 'foo')
52 nt.assert_equal(f(B()), 'foo')
52 nt.assert_equal(f(B()), 'foo')
53 nt.assert_equal(f(GoodPretty()), 'foo')
53 nt.assert_equal(f(GoodPretty()), 'foo')
54 # Just don't raise an exception for the following:
54 # Just don't raise an exception for the following:
55 f(BadPretty())
55 f(BadPretty())
56
56
57 f.pprint = False
57 f.pprint = False
58 nt.assert_equal(f(A()), 'A()')
58 nt.assert_equal(f(A()), 'A()')
59 nt.assert_equal(f(B()), 'B()')
59 nt.assert_equal(f(B()), 'B()')
60 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
60 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
61
61
62
62
63 def test_deferred():
63 def test_deferred():
64 f = PlainTextFormatter()
64 f = PlainTextFormatter()
65
65
66 def test_precision():
66 def test_precision():
67 """test various values for float_precision."""
67 """test various values for float_precision."""
68 f = PlainTextFormatter()
68 f = PlainTextFormatter()
69 nt.assert_equal(f(pi), repr(pi))
69 nt.assert_equal(f(pi), repr(pi))
70 f.float_precision = 0
70 f.float_precision = 0
71 if numpy:
71 if numpy:
72 po = numpy.get_printoptions()
72 po = numpy.get_printoptions()
73 nt.assert_equal(po['precision'], 0)
73 nt.assert_equal(po['precision'], 0)
74 nt.assert_equal(f(pi), '3')
74 nt.assert_equal(f(pi), '3')
75 f.float_precision = 2
75 f.float_precision = 2
76 if numpy:
76 if numpy:
77 po = numpy.get_printoptions()
77 po = numpy.get_printoptions()
78 nt.assert_equal(po['precision'], 2)
78 nt.assert_equal(po['precision'], 2)
79 nt.assert_equal(f(pi), '3.14')
79 nt.assert_equal(f(pi), '3.14')
80 f.float_precision = '%g'
80 f.float_precision = '%g'
81 if numpy:
81 if numpy:
82 po = numpy.get_printoptions()
82 po = numpy.get_printoptions()
83 nt.assert_equal(po['precision'], 2)
83 nt.assert_equal(po['precision'], 2)
84 nt.assert_equal(f(pi), '3.14159')
84 nt.assert_equal(f(pi), '3.14159')
85 f.float_precision = '%e'
85 f.float_precision = '%e'
86 nt.assert_equal(f(pi), '3.141593e+00')
86 nt.assert_equal(f(pi), '3.141593e+00')
87 f.float_precision = ''
87 f.float_precision = ''
88 if numpy:
88 if numpy:
89 po = numpy.get_printoptions()
89 po = numpy.get_printoptions()
90 nt.assert_equal(po['precision'], 8)
90 nt.assert_equal(po['precision'], 8)
91 nt.assert_equal(f(pi), repr(pi))
91 nt.assert_equal(f(pi), repr(pi))
92
92
93 def test_bad_precision():
93 def test_bad_precision():
94 """test various invalid values for float_precision."""
94 """test various invalid values for float_precision."""
95 f = PlainTextFormatter()
95 f = PlainTextFormatter()
96 def set_fp(p):
96 def set_fp(p):
97 f.float_precision=p
97 f.float_precision=p
98 nt.assert_raises(ValueError, set_fp, '%')
98 nt.assert_raises(ValueError, set_fp, '%')
99 nt.assert_raises(ValueError, set_fp, '%.3f%i')
99 nt.assert_raises(ValueError, set_fp, '%.3f%i')
100 nt.assert_raises(ValueError, set_fp, 'foo')
100 nt.assert_raises(ValueError, set_fp, 'foo')
101 nt.assert_raises(ValueError, set_fp, -1)
101 nt.assert_raises(ValueError, set_fp, -1)
102
102
103 def test_for_type():
103 def test_for_type():
104 f = PlainTextFormatter()
104 f = PlainTextFormatter()
105
105
106 # initial return, None
106 # initial return, None
107 nt.assert_is(f.for_type(C, foo_printer), None)
107 nt.assert_is(f.for_type(C, foo_printer), None)
108 # no func queries
108 # no func queries
109 nt.assert_is(f.for_type(C), foo_printer)
109 nt.assert_is(f.for_type(C), foo_printer)
110 # shouldn't change anything
110 # shouldn't change anything
111 nt.assert_is(f.for_type(C), foo_printer)
111 nt.assert_is(f.for_type(C), foo_printer)
112 # None should do the same
112 # None should do the same
113 nt.assert_is(f.for_type(C, None), foo_printer)
113 nt.assert_is(f.for_type(C, None), foo_printer)
114 nt.assert_is(f.for_type(C, None), foo_printer)
114 nt.assert_is(f.for_type(C, None), foo_printer)
115
115
116 def test_for_type_string():
116 def test_for_type_string():
117 f = PlainTextFormatter()
117 f = PlainTextFormatter()
118
118
119 type_str = '%s.%s' % (C.__module__, 'C')
119 type_str = '%s.%s' % (C.__module__, 'C')
120
120
121 # initial return, None
121 # initial return, None
122 nt.assert_is(f.for_type(type_str, foo_printer), None)
122 nt.assert_is(f.for_type(type_str, foo_printer), None)
123 # no func queries
123 # no func queries
124 nt.assert_is(f.for_type(type_str), foo_printer)
124 nt.assert_is(f.for_type(type_str), foo_printer)
125 nt.assert_in(_mod_name_key(C), f.deferred_printers)
125 nt.assert_in(_mod_name_key(C), f.deferred_printers)
126 nt.assert_is(f.for_type(C), foo_printer)
126 nt.assert_is(f.for_type(C), foo_printer)
127 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
127 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
128 nt.assert_in(C, f.type_printers)
128 nt.assert_in(C, f.type_printers)
129
129
130 def test_for_type_by_name():
130 def test_for_type_by_name():
131 f = PlainTextFormatter()
131 f = PlainTextFormatter()
132
132
133 mod = C.__module__
133 mod = C.__module__
134
134
135 # initial return, None
135 # initial return, None
136 nt.assert_is(f.for_type_by_name(mod, 'C', foo_printer), None)
136 nt.assert_is(f.for_type_by_name(mod, 'C', foo_printer), None)
137 # no func queries
137 # no func queries
138 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
138 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
139 # shouldn't change anything
139 # shouldn't change anything
140 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
140 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
141 # None should do the same
141 # None should do the same
142 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
142 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
143 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
143 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
144
144
145 def test_lookup():
145 def test_lookup():
146 f = PlainTextFormatter()
146 f = PlainTextFormatter()
147
147
148 f.for_type(C, foo_printer)
148 f.for_type(C, foo_printer)
149 nt.assert_is(f.lookup(C()), foo_printer)
149 nt.assert_is(f.lookup(C()), foo_printer)
150 with nt.assert_raises(KeyError):
150 with nt.assert_raises(KeyError):
151 f.lookup(A())
151 f.lookup(A())
152
152
153 def test_lookup_string():
153 def test_lookup_string():
154 f = PlainTextFormatter()
154 f = PlainTextFormatter()
155 type_str = '%s.%s' % (C.__module__, 'C')
155 type_str = '%s.%s' % (C.__module__, 'C')
156
156
157 f.for_type(type_str, foo_printer)
157 f.for_type(type_str, foo_printer)
158 nt.assert_is(f.lookup(C()), foo_printer)
158 nt.assert_is(f.lookup(C()), foo_printer)
159 # should move from deferred to imported dict
159 # should move from deferred to imported dict
160 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
160 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
161 nt.assert_in(C, f.type_printers)
161 nt.assert_in(C, f.type_printers)
162
162
163 def test_lookup_by_type():
163 def test_lookup_by_type():
164 f = PlainTextFormatter()
164 f = PlainTextFormatter()
165 f.for_type(C, foo_printer)
165 f.for_type(C, foo_printer)
166 nt.assert_is(f.lookup_by_type(C), foo_printer)
166 nt.assert_is(f.lookup_by_type(C), foo_printer)
167 with nt.assert_raises(KeyError):
167 with nt.assert_raises(KeyError):
168 f.lookup_by_type(A)
168 f.lookup_by_type(A)
169
169
170 def test_lookup_by_type_string():
170 def test_lookup_by_type_string():
171 f = PlainTextFormatter()
171 f = PlainTextFormatter()
172 type_str = '%s.%s' % (C.__module__, 'C')
172 type_str = '%s.%s' % (C.__module__, 'C')
173 f.for_type(type_str, foo_printer)
173 f.for_type(type_str, foo_printer)
174
174
175 # verify insertion
175 # verify insertion
176 nt.assert_in(_mod_name_key(C), f.deferred_printers)
176 nt.assert_in(_mod_name_key(C), f.deferred_printers)
177 nt.assert_not_in(C, f.type_printers)
177 nt.assert_not_in(C, f.type_printers)
178
178
179 nt.assert_is(f.lookup_by_type(type_str), foo_printer)
179 nt.assert_is(f.lookup_by_type(type_str), foo_printer)
180 # lookup by string doesn't cause import
180 # lookup by string doesn't cause import
181 nt.assert_in(_mod_name_key(C), f.deferred_printers)
181 nt.assert_in(_mod_name_key(C), f.deferred_printers)
182 nt.assert_not_in(C, f.type_printers)
182 nt.assert_not_in(C, f.type_printers)
183
183
184 nt.assert_is(f.lookup_by_type(C), foo_printer)
184 nt.assert_is(f.lookup_by_type(C), foo_printer)
185 # should move from deferred to imported dict
185 # should move from deferred to imported dict
186 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
186 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
187 nt.assert_in(C, f.type_printers)
187 nt.assert_in(C, f.type_printers)
188
188
189 def test_in_formatter():
189 def test_in_formatter():
190 f = PlainTextFormatter()
190 f = PlainTextFormatter()
191 f.for_type(C, foo_printer)
191 f.for_type(C, foo_printer)
192 type_str = '%s.%s' % (C.__module__, 'C')
192 type_str = '%s.%s' % (C.__module__, 'C')
193 nt.assert_in(C, f)
193 nt.assert_in(C, f)
194 nt.assert_in(type_str, f)
194 nt.assert_in(type_str, f)
195
195
196 def test_string_in_formatter():
196 def test_string_in_formatter():
197 f = PlainTextFormatter()
197 f = PlainTextFormatter()
198 type_str = '%s.%s' % (C.__module__, 'C')
198 type_str = '%s.%s' % (C.__module__, 'C')
199 f.for_type(type_str, foo_printer)
199 f.for_type(type_str, foo_printer)
200 nt.assert_in(type_str, f)
200 nt.assert_in(type_str, f)
201 nt.assert_in(C, f)
201 nt.assert_in(C, f)
202
202
203 def test_pop():
203 def test_pop():
204 f = PlainTextFormatter()
204 f = PlainTextFormatter()
205 f.for_type(C, foo_printer)
205 f.for_type(C, foo_printer)
206 nt.assert_is(f.lookup_by_type(C), foo_printer)
206 nt.assert_is(f.lookup_by_type(C), foo_printer)
207 nt.assert_is(f.pop(C, None), foo_printer)
207 nt.assert_is(f.pop(C, None), foo_printer)
208 f.for_type(C, foo_printer)
208 f.for_type(C, foo_printer)
209 nt.assert_is(f.pop(C), foo_printer)
209 nt.assert_is(f.pop(C), foo_printer)
210 with nt.assert_raises(KeyError):
210 with nt.assert_raises(KeyError):
211 f.lookup_by_type(C)
211 f.lookup_by_type(C)
212 with nt.assert_raises(KeyError):
212 with nt.assert_raises(KeyError):
213 f.pop(C)
213 f.pop(C)
214 with nt.assert_raises(KeyError):
214 with nt.assert_raises(KeyError):
215 f.pop(A)
215 f.pop(A)
216 nt.assert_is(f.pop(A, None), None)
216 nt.assert_is(f.pop(A, None), None)
217
217
218 def test_pop_string():
218 def test_pop_string():
219 f = PlainTextFormatter()
219 f = PlainTextFormatter()
220 type_str = '%s.%s' % (C.__module__, 'C')
220 type_str = '%s.%s' % (C.__module__, 'C')
221
221
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(type_str, foo_printer)
225 f.for_type(type_str, foo_printer)
226 f.pop(type_str)
226 f.pop(type_str)
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
231
232 f.for_type(C, foo_printer)
232 f.for_type(C, foo_printer)
233 nt.assert_is(f.pop(type_str, None), foo_printer)
233 nt.assert_is(f.pop(type_str, None), foo_printer)
234 with nt.assert_raises(KeyError):
234 with nt.assert_raises(KeyError):
235 f.lookup_by_type(C)
235 f.lookup_by_type(C)
236 with nt.assert_raises(KeyError):
236 with nt.assert_raises(KeyError):
237 f.pop(type_str)
237 f.pop(type_str)
238 nt.assert_is(f.pop(type_str, None), None)
238 nt.assert_is(f.pop(type_str, None), None)
239
239
240
240
241 def test_error_method():
241 def test_error_method():
242 f = HTMLFormatter()
242 f = HTMLFormatter()
243 class BadHTML(object):
243 class BadHTML(object):
244 def _repr_html_(self):
244 def _repr_html_(self):
245 raise ValueError("Bad HTML")
245 raise ValueError("Bad HTML")
246 bad = BadHTML()
246 bad = BadHTML()
247 with capture_output() as captured:
247 with capture_output() as captured:
248 result = f(bad)
248 result = f(bad)
249 nt.assert_is(result, None)
249 nt.assert_is(result, None)
250 nt.assert_in("Traceback", captured.stdout)
250 nt.assert_in("Traceback", captured.stdout)
251 nt.assert_in("Bad HTML", captured.stdout)
251 nt.assert_in("Bad HTML", captured.stdout)
252 nt.assert_in("_repr_html_", captured.stdout)
252 nt.assert_in("_repr_html_", captured.stdout)
253
253
254 def test_nowarn_notimplemented():
254 def test_nowarn_notimplemented():
255 f = HTMLFormatter()
255 f = HTMLFormatter()
256 class HTMLNotImplemented(object):
256 class HTMLNotImplemented(object):
257 def _repr_html_(self):
257 def _repr_html_(self):
258 raise NotImplementedError
258 raise NotImplementedError
259 h = HTMLNotImplemented()
259 h = HTMLNotImplemented()
260 with capture_output() as captured:
260 with capture_output() as captured:
261 result = f(h)
261 result = f(h)
262 nt.assert_is(result, None)
262 nt.assert_is(result, None)
263 nt.assert_equal("", captured.stderr)
263 nt.assert_equal("", captured.stderr)
264 nt.assert_equal("", captured.stdout)
264 nt.assert_equal("", captured.stdout)
265
265
266 def test_warn_error_for_type():
266 def test_warn_error_for_type():
267 f = HTMLFormatter()
267 f = HTMLFormatter()
268 f.for_type(int, lambda i: name_error)
268 f.for_type(int, lambda i: name_error)
269 with capture_output() as captured:
269 with capture_output() as captured:
270 result = f(5)
270 result = f(5)
271 nt.assert_is(result, None)
271 nt.assert_is(result, None)
272 nt.assert_in("Traceback", captured.stdout)
272 nt.assert_in("Traceback", captured.stdout)
273 nt.assert_in("NameError", captured.stdout)
273 nt.assert_in("NameError", captured.stdout)
274 nt.assert_in("name_error", captured.stdout)
274 nt.assert_in("name_error", captured.stdout)
275
275
276 def test_error_pretty_method():
276 def test_error_pretty_method():
277 f = PlainTextFormatter()
277 f = PlainTextFormatter()
278 class BadPretty(object):
278 class BadPretty(object):
279 def _repr_pretty_(self):
279 def _repr_pretty_(self):
280 return "hello"
280 return "hello"
281 bad = BadPretty()
281 bad = BadPretty()
282 with capture_output() as captured:
282 with capture_output() as captured:
283 result = f(bad)
283 result = f(bad)
284 nt.assert_is(result, None)
284 nt.assert_is(result, None)
285 nt.assert_in("Traceback", captured.stdout)
285 nt.assert_in("Traceback", captured.stdout)
286 nt.assert_in("_repr_pretty_", captured.stdout)
286 nt.assert_in("_repr_pretty_", captured.stdout)
287 nt.assert_in("given", captured.stdout)
287 nt.assert_in("given", captured.stdout)
288 nt.assert_in("argument", captured.stdout)
288 nt.assert_in("argument", captured.stdout)
289
289
290
290
291 def test_bad_repr_traceback():
291 def test_bad_repr_traceback():
292 f = PlainTextFormatter()
292 f = PlainTextFormatter()
293 bad = BadRepr()
293 bad = BadRepr()
294 with capture_output() as captured:
294 with capture_output() as captured:
295 result = f(bad)
295 result = f(bad)
296 # catches error, returns None
296 # catches error, returns None
297 nt.assert_is(result, None)
297 nt.assert_is(result, None)
298 nt.assert_in("Traceback", captured.stdout)
298 nt.assert_in("Traceback", captured.stdout)
299 nt.assert_in("__repr__", captured.stdout)
299 nt.assert_in("__repr__", captured.stdout)
300 nt.assert_in("ValueError", captured.stdout)
300 nt.assert_in("ValueError", captured.stdout)
301
301
302
302
303 class MakePDF(object):
303 class MakePDF(object):
304 def _repr_pdf_(self):
304 def _repr_pdf_(self):
305 return 'PDF'
305 return 'PDF'
306
306
307 def test_pdf_formatter():
307 def test_pdf_formatter():
308 pdf = MakePDF()
308 pdf = MakePDF()
309 f = PDFFormatter()
309 f = PDFFormatter()
310 nt.assert_equal(f(pdf), 'PDF')
310 nt.assert_equal(f(pdf), 'PDF')
311
311
312 def test_print_method_bound():
312 def test_print_method_bound():
313 f = HTMLFormatter()
313 f = HTMLFormatter()
314 class MyHTML(object):
314 class MyHTML(object):
315 def _repr_html_(self):
315 def _repr_html_(self):
316 return "hello"
316 return "hello"
317 with capture_output() as captured:
317 with capture_output() as captured:
318 result = f(MyHTML)
318 result = f(MyHTML)
319 nt.assert_is(result, None)
319 nt.assert_is(result, None)
320 nt.assert_not_in("FormatterWarning", captured.stderr)
320 nt.assert_not_in("FormatterWarning", captured.stderr)
321
321
322 with capture_output() as captured:
322 with capture_output() as captured:
323 result = f(MyHTML())
323 result = f(MyHTML())
324 nt.assert_equal(result, "hello")
324 nt.assert_equal(result, "hello")
325 nt.assert_equal(captured.stderr, "")
325 nt.assert_equal(captured.stderr, "")
326
326
327 def test_print_method_weird():
327 def test_print_method_weird():
328
328
329 class TextMagicHat(object):
329 class TextMagicHat(object):
330 def __getattr__(self, key):
330 def __getattr__(self, key):
331 return key
331 return key
332
332
333 f = HTMLFormatter()
333 f = HTMLFormatter()
334
334
335 text_hat = TextMagicHat()
335 text_hat = TextMagicHat()
336 nt.assert_equal(text_hat._repr_html_, '_repr_html_')
336 nt.assert_equal(text_hat._repr_html_, '_repr_html_')
337 with capture_output() as captured:
337 with capture_output() as captured:
338 result = f(text_hat)
338 result = f(text_hat)
339
339
340 nt.assert_is(result, None)
340 nt.assert_is(result, None)
341 nt.assert_not_in("FormatterWarning", captured.stderr)
341 nt.assert_not_in("FormatterWarning", captured.stderr)
342
342
343 class CallableMagicHat(object):
343 class CallableMagicHat(object):
344 def __getattr__(self, key):
344 def __getattr__(self, key):
345 return lambda : key
345 return lambda : key
346
346
347 call_hat = CallableMagicHat()
347 call_hat = CallableMagicHat()
348 with capture_output() as captured:
348 with capture_output() as captured:
349 result = f(call_hat)
349 result = f(call_hat)
350
350
351 nt.assert_equal(result, None)
351 nt.assert_equal(result, None)
352
352
353 class BadReprArgs(object):
353 class BadReprArgs(object):
354 def _repr_html_(self, extra, args):
354 def _repr_html_(self, extra, args):
355 return "html"
355 return "html"
356
356
357 bad = BadReprArgs()
357 bad = BadReprArgs()
358 with capture_output() as captured:
358 with capture_output() as captured:
359 result = f(bad)
359 result = f(bad)
360
360
361 nt.assert_is(result, None)
361 nt.assert_is(result, None)
362 nt.assert_not_in("FormatterWarning", captured.stderr)
362 nt.assert_not_in("FormatterWarning", captured.stderr)
363
363
364
364
365 def test_format_config():
365 def test_format_config():
366 """config objects don't pretend to support fancy reprs with lazy attrs"""
366 """config objects don't pretend to support fancy reprs with lazy attrs"""
367 f = HTMLFormatter()
367 f = HTMLFormatter()
368 cfg = Config()
368 cfg = Config()
369 with capture_output() as captured:
369 with capture_output() as captured:
370 result = f(cfg)
370 result = f(cfg)
371 nt.assert_is(result, None)
371 nt.assert_is(result, None)
372 nt.assert_equal(captured.stderr, "")
372 nt.assert_equal(captured.stderr, "")
373
373
374 with capture_output() as captured:
374 with capture_output() as captured:
375 result = f(Config)
375 result = f(Config)
376 nt.assert_is(result, None)
376 nt.assert_is(result, None)
377 nt.assert_equal(captured.stderr, "")
377 nt.assert_equal(captured.stderr, "")
378
378
379 def test_pretty_max_seq_length():
379 def test_pretty_max_seq_length():
380 f = PlainTextFormatter(max_seq_length=1)
380 f = PlainTextFormatter(max_seq_length=1)
381 lis = list(range(3))
381 lis = list(range(3))
382 text = f(lis)
382 text = f(lis)
383 nt.assert_equal(text, '[0, ...]')
383 nt.assert_equal(text, '[0, ...]')
384 f.max_seq_length = 0
384 f.max_seq_length = 0
385 text = f(lis)
385 text = f(lis)
386 nt.assert_equal(text, '[0, 1, 2]')
386 nt.assert_equal(text, '[0, 1, 2]')
387 text = f(list(range(1024)))
387 text = f(list(range(1024)))
388 lines = text.splitlines()
388 lines = text.splitlines()
389 nt.assert_equal(len(lines), 1024)
389 nt.assert_equal(len(lines), 1024)
390
390
391
391
392 def test_ipython_display_formatter():
392 def test_ipython_display_formatter():
393 """Objects with _ipython_display_ defined bypass other formatters"""
393 """Objects with _ipython_display_ defined bypass other formatters"""
394 f = get_ipython().display_formatter
394 f = get_ipython().display_formatter
395 catcher = []
395 catcher = []
396 class SelfDisplaying(object):
396 class SelfDisplaying(object):
397 def _ipython_display_(self):
397 def _ipython_display_(self):
398 catcher.append(self)
398 catcher.append(self)
399
399
400 class NotSelfDisplaying(object):
400 class NotSelfDisplaying(object):
401 def __repr__(self):
401 def __repr__(self):
402 return "NotSelfDisplaying"
402 return "NotSelfDisplaying"
403
403
404 def _ipython_display_(self):
404 def _ipython_display_(self):
405 raise NotImplementedError
405 raise NotImplementedError
406
406
407 save_enabled = f.ipython_display_formatter.enabled
407 save_enabled = f.ipython_display_formatter.enabled
408 f.ipython_display_formatter.enabled = True
408 f.ipython_display_formatter.enabled = True
409
409
410 yes = SelfDisplaying()
410 yes = SelfDisplaying()
411 no = NotSelfDisplaying()
411 no = NotSelfDisplaying()
412
412
413 d, md = f.format(no)
413 d, md = f.format(no)
414 nt.assert_equal(d, {'text/plain': repr(no)})
414 nt.assert_equal(d, {'text/plain': repr(no)})
415 nt.assert_equal(md, {})
415 nt.assert_equal(md, {})
416 nt.assert_equal(catcher, [])
416 nt.assert_equal(catcher, [])
417
417
418 d, md = f.format(yes)
418 d, md = f.format(yes)
419 nt.assert_equal(d, {})
419 nt.assert_equal(d, {})
420 nt.assert_equal(md, {})
420 nt.assert_equal(md, {})
421 nt.assert_equal(catcher, [yes])
421 nt.assert_equal(catcher, [yes])
422
422
423 f.ipython_display_formatter.enabled = save_enabled
423 f.ipython_display_formatter.enabled = save_enabled
424
424
425
425
426 def test_json_as_string_deprecated():
426 def test_json_as_string_deprecated():
427 class JSONString(object):
427 class JSONString(object):
428 def _repr_json_(self):
428 def _repr_json_(self):
429 return '{}'
429 return '{}'
430
430
431 f = JSONFormatter()
431 f = JSONFormatter()
432 with warnings.catch_warnings(record=True) as w:
432 with warnings.catch_warnings(record=True) as w:
433 d = f(JSONString())
433 d = f(JSONString())
434 nt.assert_equal(d, {})
434 nt.assert_equal(d, {})
435 nt.assert_equal(len(w), 1)
435 nt.assert_equal(len(w), 1)
436
436
437
437
438 def test_repr_mime():
438 def test_repr_mime():
439 class HasReprMime(object):
439 class HasReprMime(object):
440 def _repr_mimebundle_(self, include=None, exclude=None):
440 def _repr_mimebundle_(self, include=None, exclude=None):
441 return {
441 return {
442 'application/json+test.v2': {
442 'application/json+test.v2': {
443 'x': 'y'
443 'x': 'y'
444 },
444 },
445 'plain/text' : '<HasReprMime>',
445 'plain/text' : '<HasReprMime>',
446 'image/png' : 'i-overwrite'
446 'image/png' : 'i-overwrite'
447 }
447 }
448
448
449 def _repr_png_(self):
449 def _repr_png_(self):
450 return 'should-be-overwritten'
450 return 'should-be-overwritten'
451 def _repr_html_(self):
451 def _repr_html_(self):
452 return '<b>hi!</b>'
452 return '<b>hi!</b>'
453
453
454 f = get_ipython().display_formatter
454 f = get_ipython().display_formatter
455 html_f = f.formatters['text/html']
455 html_f = f.formatters['text/html']
456 save_enabled = html_f.enabled
456 save_enabled = html_f.enabled
457 html_f.enabled = True
457 html_f.enabled = True
458 obj = HasReprMime()
458 obj = HasReprMime()
459 d, md = f.format(obj)
459 d, md = f.format(obj)
460 html_f.enabled = save_enabled
460 html_f.enabled = save_enabled
461
461
462 nt.assert_equal(sorted(d), ['application/json+test.v2',
462 nt.assert_equal(sorted(d), ['application/json+test.v2',
463 'image/png',
463 'image/png',
464 'plain/text',
464 'plain/text',
465 'text/html',
465 'text/html',
466 'text/plain'])
466 'text/plain'])
467 nt.assert_equal(md, {})
467 nt.assert_equal(md, {})
468
468
469 d, md = f.format(obj, include={'image/png'})
469 d, md = f.format(obj, include={'image/png'})
470 nt.assert_equal(list(d.keys()), ['image/png'],
470 nt.assert_equal(list(d.keys()), ['image/png'],
471 'Include should filter out even things from repr_mimebundle')
471 'Include should filter out even things from repr_mimebundle')
472 nt.assert_equal(d['image/png'], 'i-overwrite', '_repr_mimebundle_ take precedence')
472 nt.assert_equal(d['image/png'], 'i-overwrite', '_repr_mimebundle_ take precedence')
473
473
474
474
475
475
476 def test_pass_correct_include_exclude():
476 def test_pass_correct_include_exclude():
477 class Tester(object):
477 class Tester(object):
478
478
479 def __init__(self, include=None, exclude=None):
479 def __init__(self, include=None, exclude=None):
480 self.include = include
480 self.include = include
481 self.exclude = exclude
481 self.exclude = exclude
482
482
483 def _repr_mimebundle_(self, include, exclude, **kwargs):
483 def _repr_mimebundle_(self, include, exclude, **kwargs):
484 if include and (include != self.include):
484 if include and (include != self.include):
485 raise ValueError('include got modified: display() may be broken.')
485 raise ValueError('include got modified: display() may be broken.')
486 if exclude and (exclude != self.exclude):
486 if exclude and (exclude != self.exclude):
487 raise ValueError('exclude got modified: display() may be broken.')
487 raise ValueError('exclude got modified: display() may be broken.')
488
488
489 return None
489 return None
490
490
491 include = {'a', 'b', 'c'}
491 include = {'a', 'b', 'c'}
492 exclude = {'c', 'e' , 'f'}
492 exclude = {'c', 'e' , 'f'}
493
493
494 f = get_ipython().display_formatter
494 f = get_ipython().display_formatter
495 f.format(Tester(include=include, exclude=exclude), include=include, exclude=exclude)
495 f.format(Tester(include=include, exclude=exclude), include=include, exclude=exclude)
496 f.format(Tester(exclude=exclude), exclude=exclude)
496 f.format(Tester(exclude=exclude), exclude=exclude)
497 f.format(Tester(include=include), include=include)
497 f.format(Tester(include=include), include=include)
498
498
499
499
500 def test_repr_mime_meta():
500 def test_repr_mime_meta():
501 class HasReprMimeMeta(object):
501 class HasReprMimeMeta(object):
502 def _repr_mimebundle_(self, include=None, exclude=None):
502 def _repr_mimebundle_(self, include=None, exclude=None):
503 data = {
503 data = {
504 'image/png': 'base64-image-data',
504 'image/png': 'base64-image-data',
505 }
505 }
506 metadata = {
506 metadata = {
507 'image/png': {
507 'image/png': {
508 'width': 5,
508 'width': 5,
509 'height': 10,
509 'height': 10,
510 }
510 }
511 }
511 }
512 return (data, metadata)
512 return (data, metadata)
513
513
514 f = get_ipython().display_formatter
514 f = get_ipython().display_formatter
515 obj = HasReprMimeMeta()
515 obj = HasReprMimeMeta()
516 d, md = f.format(obj)
516 d, md = f.format(obj)
517 nt.assert_equal(sorted(d), ['image/png', 'text/plain'])
517 nt.assert_equal(sorted(d), ['image/png', 'text/plain'])
518 nt.assert_equal(md, {
518 nt.assert_equal(md, {
519 'image/png': {
519 'image/png': {
520 'width': 5,
520 'width': 5,
521 'height': 10,
521 'height': 10,
522 }
522 }
523 })
523 })
524
525 def test_repr_mime_failure():
526 class BadReprMime(object):
527 def _repr_mimebundle_(self, include=None, exclude=None):
528 raise RuntimeError
529
530 f = get_ipython().display_formatter
531 obj = BadReprMime()
532 d, md = f.format(obj)
533 nt.assert_in('text/plain', d)
General Comments 0
You need to be logged in to leave comments. Login now