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