##// END OF EJS Templates
show tracebacks for errors in formatters...
MinRK -
Show More
@@ -5,25 +5,11 b' Inheritance diagram:'
5 5
6 6 .. inheritance-diagram:: IPython.core.formatters
7 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 #-----------------------------------------------------------------------------
23 # Imports
24 #-----------------------------------------------------------------------------
10 # Copyright (c) IPython Development Team.
11 # Distributed under the terms of the Modified BSD License.
25 12
26 # Stdlib imports
27 13 import abc
28 14 import inspect
29 15 import sys
@@ -32,8 +18,8 b' import warnings'
32 18
33 19 from IPython.external.decorator import decorator
34 20
35 # Our own imports
36 21 from IPython.config.configurable import Configurable
22 from IPython.core.getipython import get_ipython
37 23 from IPython.lib import pretty
38 24 from IPython.utils.traitlets import (
39 25 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
@@ -223,6 +209,18 b' class DisplayFormatter(Configurable):'
223 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 224 class FormatterWarning(UserWarning):
227 225 """Warning class for errors in formatters"""
228 226
@@ -234,10 +232,13 b' def warn_format_error(method, self, *args, **kwargs):'
234 232 except NotImplementedError as e:
235 233 # don't warn on NotImplementedErrors
236 234 return None
237 except Exception as e:
238 warnings.warn("Exception in %s formatter: %s" % (self.format_type, e),
239 FormatterWarning,
240 )
235 except Exception:
236 exc_info = sys.exc_info()
237 ip = get_ipython()
238 if ip is not None:
239 ip.showtraceback(exc_info)
240 else:
241 traceback.print_exception(*exc_info)
241 242 return None
242 243 if r is None or isinstance(r, self._return_type) or \
243 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 246 else:
246 247 warnings.warn(
247 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 250 FormatterWarning
250 251 )
251 252
@@ -672,7 +673,7 b' class PlainTextFormatter(BaseFormatter):'
672 673 def __call__(self, obj):
673 674 """Compute the pretty representation of the object."""
674 675 if not self.pprint:
675 return pretty._safe_repr(obj)
676 return repr(obj)
676 677 else:
677 678 # This uses use StringIO, as cStringIO doesn't handle unicode.
678 679 stream = StringIO()
@@ -25,6 +25,10 b' class B(A):'
25 25 class C:
26 26 pass
27 27
28 class BadRepr(object):
29 def __repr__(self):
30 raise ValueError("bad repr")
31
28 32 class BadPretty(object):
29 33 _repr_pretty_ = None
30 34
@@ -234,30 +238,30 b' def test_pop_string():'
234 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 242 f = HTMLFormatter()
239 243 class BadHTML(object):
240 244 def _repr_html_(self):
241 return 1/0
245 raise ValueError("Bad HTML")
242 246 bad = BadHTML()
243 247 with capture_output() as captured:
244 248 result = f(bad)
245 249 nt.assert_is(result, None)
246 nt.assert_in("FormatterWarning", captured.stderr)
247 nt.assert_in("text/html", captured.stderr)
248 nt.assert_in("zero", captured.stderr)
250 nt.assert_in("Traceback", captured.stdout)
251 nt.assert_in("Bad HTML", captured.stdout)
252 nt.assert_in("_repr_html_", captured.stdout)
249 253
250 254 def test_nowarn_notimplemented():
251 255 f = HTMLFormatter()
252 256 class HTMLNotImplemented(object):
253 257 def _repr_html_(self):
254 258 raise NotImplementedError
255 return 1/0
256 259 h = HTMLNotImplemented()
257 260 with capture_output() as captured:
258 261 result = f(h)
259 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 266 def test_warn_error_for_type():
263 267 f = HTMLFormatter()
@@ -265,11 +269,11 b' def test_warn_error_for_type():'
265 269 with capture_output() as captured:
266 270 result = f(5)
267 271 nt.assert_is(result, None)
268 nt.assert_in("FormatterWarning", captured.stderr)
269 nt.assert_in("text/html", captured.stderr)
270 nt.assert_in("name_error", captured.stderr)
272 nt.assert_in("Traceback", captured.stdout)
273 nt.assert_in("NameError", captured.stdout)
274 nt.assert_in("name_error", captured.stdout)
271 275
272 def test_warn_error_pretty_method():
276 def test_error_pretty_method():
273 277 f = PlainTextFormatter()
274 278 class BadPretty(object):
275 279 def _repr_pretty_(self):
@@ -278,9 +282,23 b' def test_warn_error_pretty_method():'
278 282 with capture_output() as captured:
279 283 result = f(bad)
280 284 nt.assert_is(result, None)
281 nt.assert_in("FormatterWarning", captured.stderr)
282 nt.assert_in("text/plain", captured.stderr)
283 nt.assert_in("argument", captured.stderr)
285 nt.assert_in("Traceback", captured.stdout)
286 nt.assert_in("_repr_pretty_", captured.stdout)
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 303 class MakePDF(object):
286 304 def _repr_pdf_(self):
General Comments 0
You need to be logged in to leave comments. Login now