##// END OF EJS Templates
show tracebacks for errors in formatters...
MinRK -
Show More
@@ -5,25 +5,11 b' 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
@@ -32,8 +18,8 b' 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,
@@ -223,6 +209,18 b' class DisplayFormatter(Configurable):'
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
@@ -234,10 +232,13 b' def warn_format_error(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)):
@@ -245,7 +246,7 b' def warn_format_error(method, self, *args, **kwargs):'
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
@@ -672,7 +673,7 b' class PlainTextFormatter(BaseFormatter):'
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()
@@ -25,6 +25,10 b' class B(A):'
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
@@ -234,30 +238,30 b' def test_pop_string():'
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()
@@ -265,11 +269,11 b' def test_warn_error_for_type():'
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):
@@ -278,9 +282,23 b' def test_warn_error_pretty_method():'
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):
General Comments 0
You need to be logged in to leave comments. Login now