From 873e364771bf39acbf1b8332ed0fdb14389e1a3b 2012-03-16 23:12:12 From: Min RK Date: 2012-03-16 23:12:12 Subject: [PATCH] Merge pull request #1495 from rkern/fix-hyperobject-pprint BUG: Fix pretty-printing for overzealous objects Some classes use __getattr__ to automatically create requested attributes. The recent trend of LINQ-like query objects is what I ran into. This confuses the pretty-printing machinery that tests for _repr_pretty_. This pull request fixes many of these problems by simply testing if the _repr_pretty_ attribute is callable. This may still be confused by certain mocking frameworks, but it's a good start. --- diff --git a/IPython/core/tests/test_formatters.py b/IPython/core/tests/test_formatters.py index ea1b834..5e7e0c4 100644 --- a/IPython/core/tests/test_formatters.py +++ b/IPython/core/tests/test_formatters.py @@ -10,6 +10,7 @@ except: import nose.tools as nt from IPython.core.formatters import FormatterABC, PlainTextFormatter +from IPython.lib import pretty class A(object): def __repr__(self): @@ -19,6 +20,16 @@ class B(A): def __repr__(self): return 'B()' +class BadPretty(object): + _repr_pretty_ = None + +class GoodPretty(object): + def _repr_pretty_(self, pp, cycle): + pp.text('foo') + + def __repr__(self): + return 'GoodPretty()' + def foo_printer(obj, pp, cycle): pp.text('foo') @@ -27,9 +38,15 @@ def test_pretty(): f.for_type(A, foo_printer) nt.assert_equals(f(A()), 'foo') nt.assert_equals(f(B()), 'foo') + nt.assert_equals(f(GoodPretty()), 'foo') + # Just don't raise an exception for the following: + f(BadPretty()) + f.pprint = False nt.assert_equals(f(A()), 'A()') nt.assert_equals(f(B()), 'B()') + nt.assert_equals(f(GoodPretty()), 'GoodPretty()') + def test_deferred(): f = PlainTextFormatter() diff --git a/IPython/lib/pretty.py b/IPython/lib/pretty.py index f6f109c..61792fd 100644 --- a/IPython/lib/pretty.py +++ b/IPython/lib/pretty.py @@ -347,7 +347,11 @@ class RepresentationPrinter(PrettyPrinter): return printer(obj, self, cycle) # Finally look for special method names. if hasattr(obj_class, '_repr_pretty_'): - return obj_class._repr_pretty_(obj, self, cycle) + # Some objects automatically create any requested + # attribute. Try to ignore most of them by checking for + # callability. + if callable(obj_class._repr_pretty_): + return obj_class._repr_pretty_(obj, self, cycle) return _default_pprint(obj, self, cycle) finally: self.end_group()