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