##// END OF EJS Templates
Merge pull request #4459 from minrk/bad-repr...
Thomas Kluyver -
r13489:49af4ae9 merge
parent child Browse files
Show More
@@ -202,7 +202,7 b' class FormatterABC(with_metaclass(abc.ABCMeta, object)):'
202 """
202 """
203 try:
203 try:
204 return repr(obj)
204 return repr(obj)
205 except TypeError:
205 except Exception:
206 return None
206 return None
207
207
208
208
@@ -465,10 +465,7 b' class PlainTextFormatter(BaseFormatter):'
465 def __call__(self, obj):
465 def __call__(self, obj):
466 """Compute the pretty representation of the object."""
466 """Compute the pretty representation of the object."""
467 if not self.pprint:
467 if not self.pprint:
468 try:
468 return pretty._safe_repr(obj)
469 return repr(obj)
470 except TypeError:
471 return ''
472 else:
469 else:
473 # This uses use StringIO, as cStringIO doesn't handle unicode.
470 # This uses use StringIO, as cStringIO doesn't handle unicode.
474 stream = StringIO()
471 stream = StringIO()
@@ -125,6 +125,60 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
172 def _safe_getattr(obj, attr, default=None):
173 """Safe version of getattr.
174
175 Same as getattr, but will return ``default`` on any Exception,
176 rather than raising.
177 """
178 try:
179 return getattr(obj, attr, default)
180 except Exception:
181 return default
128
182
129 def pretty(obj, verbose=False, max_width=79, newline='\n'):
183 def pretty(obj, verbose=False, max_width=79, newline='\n'):
130 """
184 """
@@ -346,7 +400,7 b' class RepresentationPrinter(PrettyPrinter):'
346 self.stack.append(obj_id)
400 self.stack.append(obj_id)
347 self.begin_group()
401 self.begin_group()
348 try:
402 try:
349 obj_class = getattr(obj, '__class__', None) or type(obj)
403 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
350 # First try to find registered singleton printers for the type.
404 # First try to find registered singleton printers for the type.
351 try:
405 try:
352 printer = self.singleton_pprinters[obj_id]
406 printer = self.singleton_pprinters[obj_id]
@@ -388,8 +442,8 b' class RepresentationPrinter(PrettyPrinter):'
388 class is not in the registry. Successful matches will be moved to the
442 class is not in the registry. Successful matches will be moved to the
389 regular type registry for future use.
443 regular type registry for future use.
390 """
444 """
391 mod = getattr(cls, '__module__', None)
445 mod = _safe_getattr(cls, '__module__', None)
392 name = getattr(cls, '__name__', None)
446 name = _safe_getattr(cls, '__name__', None)
393 key = (mod, name)
447 key = (mod, name)
394 printer = None
448 printer = None
395 if key in self.deferred_pprinters:
449 if key in self.deferred_pprinters:
@@ -492,10 +546,10 b' def _default_pprint(obj, p, cycle):'
492 The default print function. Used if an object does not provide one and
546 The default print function. Used if an object does not provide one and
493 it's none of the builtin objects.
547 it's none of the builtin objects.
494 """
548 """
495 klass = getattr(obj, '__class__', None) or type(obj)
549 klass = _safe_getattr(obj, '__class__', None) or type(obj)
496 if getattr(klass, '__repr__', None) not in _baseclass_reprs:
550 if _safe_getattr(klass, '__repr__', None) not in _baseclass_reprs:
497 # A user-provided repr. Find newlines and replace them with p.break_()
551 # A user-provided repr. Find newlines and replace them with p.break_()
498 output = repr(obj)
552 output = _safe_repr(obj)
499 for idx,output_line in enumerate(output.splitlines()):
553 for idx,output_line in enumerate(output.splitlines()):
500 if idx:
554 if idx:
501 p.break_()
555 p.break_()
@@ -658,7 +712,7 b' def _re_pattern_pprint(obj, p, cycle):'
658
712
659 def _type_pprint(obj, p, cycle):
713 def _type_pprint(obj, p, cycle):
660 """The pprint for classes and types."""
714 """The pprint for classes and types."""
661 mod = getattr(obj, '__module__', None)
715 mod = _safe_getattr(obj, '__module__', None)
662 if mod is None:
716 if mod is None:
663 # Heap allocated types might not have the module attribute,
717 # Heap allocated types might not have the module attribute,
664 # and others may set it to None.
718 # and others may set it to None.
@@ -673,7 +727,7 b' def _type_pprint(obj, p, cycle):'
673
727
674 def _repr_pprint(obj, p, cycle):
728 def _repr_pprint(obj, p, cycle):
675 """A pprint that just redirects to the normal repr function."""
729 """A pprint that just redirects to the normal repr function."""
676 p.text(repr(obj))
730 p.text(_safe_repr(obj))
677
731
678
732
679 def _function_pprint(obj, p, cycle):
733 def _function_pprint(obj, p, cycle):
@@ -74,6 +74,10 b' class BreakingReprParent(object):'
74 with p.group(4,"TG: ",":"):
74 with p.group(4,"TG: ",":"):
75 p.pretty(BreakingRepr())
75 p.pretty(BreakingRepr())
76
76
77 class BadRepr(object):
78
79 def __repr__(self):
80 return 1/0
77
81
78
82
79 def test_indentation():
83 def test_indentation():
@@ -151,3 +155,30 b' def test_pprint_break_repr():'
151 output = pretty.pretty(BreakingReprParent())
155 output = pretty.pretty(BreakingReprParent())
152 expected = "TG: Breaking(\n ):"
156 expected = "TG: Breaking(\n ):"
153 nt.assert_equal(output, expected)
157 nt.assert_equal(output, expected)
158
159 def test_bad_repr():
160 """Don't raise, even when repr fails"""
161 output = pretty.pretty(BadRepr())
162 nt.assert_in("failed", output)
163 nt.assert_in("at 0x", output)
164 nt.assert_in("test_pretty", output)
165
166 class BadException(Exception):
167 def __str__(self):
168 return -1
169
170 class ReallyBadRepr(object):
171 __module__ = 1
172 @property
173 def __class__(self):
174 raise ValueError("I am horrible")
175
176 def __repr__(self):
177 raise BadException()
178
179 def test_really_bad_repr():
180 output = pretty.pretty(ReallyBadRepr())
181 nt.assert_in("failed", output)
182 nt.assert_in("BadException: unknown", output)
183 nt.assert_in("unknown type", output)
184 No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now