##// END OF EJS Templates
Don't catch repr-errors in pretty...
MinRK -
Show More
@@ -125,49 +125,6 b" __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',"
125
125
126 _re_pattern_type = type(re.compile(''))
126 _re_pattern_type = type(re.compile(''))
127
127
128 def _failed_repr(obj, e):
129 """Render a failed repr, including the exception.
130
131 Tries to get exception and type info
132 """
133 # get exception name
134 if e.__class__.__module__ in ('exceptions', 'builtins'):
135 ename = e.__class__.__name__
136 else:
137 ename = '{}.{}'.format(
138 e.__class__.__module__,
139 e.__class__.__name__,
140 )
141 # and exception string, which sometimes fails
142 # (usually due to unicode error message)
143 try:
144 estr = str(e)
145 except Exception:
146 estr = "unknown"
147
148 # and class name
149 try:
150 klass = _safe_getattr(obj, '__class__', None) or type(obj)
151 mod = _safe_getattr(klass, '__module__', None)
152 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
153 classname = klass.__name__
154 else:
155 classname = mod + '.' + klass.__name__
156 except Exception:
157 # this may be paranoid, but we already know repr is broken
158 classname = "unknown type"
159
160 # the informative repr
161 return "<repr(<{} at 0x{:x}>) failed: {}: {}>".format(
162 classname, id(obj), ename, estr,
163 )
164
165 def _safe_repr(obj):
166 """Don't assume repr is not broken."""
167 try:
168 return repr(obj)
169 except Exception as e:
170 return _failed_repr(obj, e)
171
128
172 def _safe_getattr(obj, attr, default=None):
129 def _safe_getattr(obj, attr, default=None):
173 """Safe version of getattr.
130 """Safe version of getattr.
@@ -560,7 +517,7 b' def _default_pprint(obj, p, cycle):'
560 klass = _safe_getattr(obj, '__class__', None) or type(obj)
517 klass = _safe_getattr(obj, '__class__', None) or type(obj)
561 if _safe_getattr(klass, '__repr__', None) not in _baseclass_reprs:
518 if _safe_getattr(klass, '__repr__', None) not in _baseclass_reprs:
562 # A user-provided repr. Find newlines and replace them with p.break_()
519 # A user-provided repr. Find newlines and replace them with p.break_()
563 output = _safe_repr(obj)
520 output = repr(obj)
564 for idx,output_line in enumerate(output.splitlines()):
521 for idx,output_line in enumerate(output.splitlines()):
565 if idx:
522 if idx:
566 p.break_()
523 p.break_()
@@ -736,7 +693,7 b' def _type_pprint(obj, p, cycle):'
736
693
737 def _repr_pprint(obj, p, cycle):
694 def _repr_pprint(obj, p, cycle):
738 """A pprint that just redirects to the normal repr function."""
695 """A pprint that just redirects to the normal repr function."""
739 p.text(_safe_repr(obj))
696 p.text(repr(obj))
740
697
741
698
742 def _function_pprint(obj, p, cycle):
699 def _function_pprint(obj, p, cycle):
@@ -1,16 +1,8 b''
1 """Tests for IPython.lib.pretty.
1 """Tests for IPython.lib.pretty."""
2 """
2
3 #-----------------------------------------------------------------------------
3 # Copyright (c) IPython Development Team.
4 # Copyright (c) 2011, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
4 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
5
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14 from __future__ import print_function
6 from __future__ import print_function
15
7
16 # Third-party imports
8 # Third-party imports
@@ -20,9 +12,6 b' import nose.tools as nt'
20 from IPython.lib import pretty
12 from IPython.lib import pretty
21 from IPython.testing.decorators import skip_without
13 from IPython.testing.decorators import skip_without
22
14
23 #-----------------------------------------------------------------------------
24 # Classes and functions
25 #-----------------------------------------------------------------------------
26
15
27 class MyList(object):
16 class MyList(object):
28 def __init__(self, content):
17 def __init__(self, content):
@@ -161,11 +150,9 b' def test_pprint_break_repr():'
161 nt.assert_equal(output, expected)
150 nt.assert_equal(output, expected)
162
151
163 def test_bad_repr():
152 def test_bad_repr():
164 """Don't raise, even when repr fails"""
153 """Don't catch bad repr errors"""
165 output = pretty.pretty(BadRepr())
154 with nt.assert_raises(ZeroDivisionError):
166 nt.assert_in("failed", output)
155 output = pretty.pretty(BadRepr())
167 nt.assert_in("at 0x", output)
168 nt.assert_in("test_pretty", output)
169
156
170 class BadException(Exception):
157 class BadException(Exception):
171 def __str__(self):
158 def __str__(self):
@@ -181,10 +168,8 b' class ReallyBadRepr(object):'
181 raise BadException()
168 raise BadException()
182
169
183 def test_really_bad_repr():
170 def test_really_bad_repr():
184 output = pretty.pretty(ReallyBadRepr())
171 with nt.assert_raises(BadException):
185 nt.assert_in("failed", output)
172 output = pretty.pretty(ReallyBadRepr())
186 nt.assert_in("BadException: unknown", output)
187 nt.assert_in("unknown type", output)
188
173
189
174
190 class SA(object):
175 class SA(object):
General Comments 0
You need to be logged in to leave comments. Login now