Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fix pretty printing dispatch #1535

Merged
merged 2 commits into from

3 participants

@doerwalter

This patch fixes a problem mentioned here:

http://mail.scipy.org/pipermail/ipython-dev/2012-March/008874.html

Search for the best method to use for pretty printing an object now no longer prefers any registered printer in type_printers for the class or any of the base classes over a _repr_pretty_ method defined in the class or any of its base classes.

Instead the mro is walked, looking for both registered printers and _repr_pretty_ methods, so that the inheritance hierarchy will be taken into account.

doerwalter added some commits
@doerwalter doerwalter Fix dispatching in the pretty printing module.
Search for the best method to use for pretty printing an object
now no longer prefers any registered printer in type_printers for
the class or any of the base classes over a _repr_pretty_ method
defined in the class or any of its base classes.

Instead the mro is walked, looking for both registered printers
and _repr_pretty_ methods, so that the inheritance hierarchy will
be taken into account.
63f389b
@doerwalter doerwalter Don't use getattr() when searching for the _repr_pretty_ method.
Using getattr() might find a method in a base class, when a registered
printer for a baseclass later in the mro is the better fit.
bbd672e
@minrk
Owner

Looks pretty sound to me. If anyone with more experience here wants to have a peek, please do.

@fperez
Owner

Great, thanks @doerwalter for this fix! Sorry it took us a while to review, March and early April were insane for most of the core devs.

Code is clean, with tests; merging now.

@fperez fperez merged commit 81039be into ipython:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 30, 2012
  1. @doerwalter

    Fix dispatching in the pretty printing module.

    doerwalter authored
    Search for the best method to use for pretty printing an object
    now no longer prefers any registered printer in type_printers for
    the class or any of the base classes over a _repr_pretty_ method
    defined in the class or any of its base classes.
    
    Instead the mro is walked, looking for both registered printers
    and _repr_pretty_ methods, so that the inheritance hierarchy will
    be taken into account.
  2. @doerwalter

    Don't use getattr() when searching for the _repr_pretty_ method.

    doerwalter authored
    Using getattr() might find a method in a base class, when a registered
    printer for a baseclass later in the mro is the better fit.
This page is out of date. Refresh to see the latest.
Showing with 30 additions and 8 deletions.
  1. +14 −8 IPython/lib/pretty.py
  2. +16 −0 IPython/lib/tests/test_pretty.py
View
22 IPython/lib/pretty.py
@@ -336,21 +336,27 @@ def pretty(self, obj):
pass
else:
return printer(obj, self, cycle)
- # Next look for type_printers.
+ # Next walk the mro and check for either:
+ # 1) a registered printer
+ # 2) a _repr_pretty_ method
for cls in _get_mro(obj_class):
if cls in self.type_pprinters:
+ # printer registered in self.type_pprinters
return self.type_pprinters[cls](obj, self, cycle)
else:
+ # deferred printer
printer = self._in_deferred_types(cls)
if printer is not None:
return printer(obj, self, cycle)
- # Finally look for special method names.
- if hasattr(obj_class, '_repr_pretty_'):
- # 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)
+ else:
+ # Finally look for special method names.
+ # Some objects automatically create any requested
+ # attribute. Try to ignore most of them by checking for
+ # callability.
+ if '_repr_pretty_' in obj_class.__dict__:
+ meth = obj_class._repr_pretty_
+ if callable(meth):
+ return meth(obj, self, cycle)
return _default_pprint(obj, self, cycle)
finally:
self.end_group()
View
16 IPython/lib/tests/test_pretty.py
@@ -40,6 +40,11 @@ def _repr_pretty_(self, p, cycle):
p.pretty(child)
+class MyDict(dict):
+ def _repr_pretty_(self, p, cycle):
+ p.text("MyDict(...)")
+
+
def test_indentation():
"""Test correct indentation in groups"""
count = 40
@@ -47,3 +52,14 @@ def test_indentation():
expectedoutput = "MyList(\n" + ",\n".join(" %d" % i for i in range(count)) + ")"
nt.assert_equals(gotoutput, expectedoutput)
+
+
+def test_dispatch():
+ """
+ Test correct dispatching: The _repr_pretty_ method for MyDict
+ must be found before the registered printer for dict.
+ """
+ gotoutput = pretty.pretty(MyDict())
+ expectedoutput = "MyDict(...)"
+
+ nt.assert_equals(gotoutput, expectedoutput)
Something went wrong with that request. Please try again.