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