##// END OF EJS Templates
Work in multiple places to improve state of the test suite....
Work in multiple places to improve state of the test suite. With these changes, on my system now all the test sub-suites pass except for the Twisted one (see https://bugs.launchpad.net/ipython/+bug/504515 for details on that one).

File last commit:

r2282:1fd4b9de
r2398:f173ff8e
Show More
pretty.py
222 lines | 6.9 KiB | text/x-python | PythonLexer
"""Use pretty.py for configurable pretty-printing.
To enable this extension in your configuration
file, add the following to :file:`ipython_config.py`::
c.Global.extensions = ['IPython.extensions.pretty']
def dict_pprinter(obj, p, cycle):
return p.text("<dict>")
c.PrettyResultDisplay.verbose = True
c.PrettyResultDisplay.defaults_for_type = [
(dict, dict_pprinter)
]
c.PrettyResultDisplay.defaults_for_type_by_name = [
('numpy', 'dtype', 'IPython.extensions.pretty.dtype_pprinter')
]
This extension can also be loaded by using the ``%load_ext`` magic::
%load_ext IPython.extensions.pretty
If this extension is enabled, you can always add additional pretty printers
by doing::
ip = get_ipython()
prd = ip.get_component('pretty_result_display')
import numpy
from IPython.extensions.pretty import dtype_pprinter
prd.for_type(numpy.dtype, dtype_pprinter)
# If you don't want to have numpy imported until it needs to be:
prd.for_type_by_name('numpy', 'dtype', dtype_pprinter)
"""
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
from IPython.core.error import TryNext
from IPython.external import pretty
from IPython.core.component import Component
from IPython.utils.traitlets import Bool, List
from IPython.utils.genutils import Term
from IPython.utils.autoattr import auto_attr
from IPython.utils.importstring import import_item
#-----------------------------------------------------------------------------
# Code
#-----------------------------------------------------------------------------
_loaded = False
class PrettyResultDisplay(Component):
"""A component for pretty printing on steroids."""
verbose = Bool(False, config=True)
# A list of (type, func_name), like
# [(dict, 'my_dict_printer')]
# The final argument can also be a callable
defaults_for_type = List(default_value=[], config=True)
# A list of (module_name, type_name, func_name), like
# [('numpy', 'dtype', 'IPython.extensions.pretty.dtype_pprinter')]
# The final argument can also be a callable
defaults_for_type_by_name = List(default_value=[], config=True)
def __init__(self, parent, name=None, config=None):
super(PrettyResultDisplay, self).__init__(parent, name=name, config=config)
self._setup_defaults()
def _setup_defaults(self):
"""Initialize the default pretty printers."""
for typ, func_name in self.defaults_for_type:
func = self._resolve_func_name(func_name)
self.for_type(typ, func)
for type_module, type_name, func_name in self.defaults_for_type_by_name:
func = self._resolve_func_name(func_name)
self.for_type_by_name(type_module, type_name, func)
def _resolve_func_name(self, func_name):
if callable(func_name):
return func_name
elif isinstance(func_name, basestring):
return import_item(func_name)
else:
raise TypeError('func_name must be a str or callable, got: %r' % func_name)
# Access other components like this rather than by a regular attribute.
# This won't lookup the InteractiveShell object until it is used and
# then it is cached. This is both efficient and couples this class
# more loosely to InteractiveShell.
@auto_attr
def shell(self):
return Component.get_instances(
root=self.root,
klass='IPython.core.iplib.InteractiveShell')[0]
def __call__(self, otherself, arg):
"""Uber-pretty-printing display hook.
Called for displaying the result to the user.
"""
if self.shell.pprint:
out = pretty.pretty(arg, verbose=self.verbose)
if '\n' in out:
# So that multi-line strings line up with the left column of
# the screen, instead of having the output prompt mess up
# their first line.
Term.cout.write('\n')
print >>Term.cout, out
else:
raise TryNext
def for_type(self, typ, func):
"""Add a pretty printer for a type."""
return pretty.for_type(typ, func)
def for_type_by_name(self, type_module, type_name, func):
"""Add a pretty printer for a type by its name and module name."""
return pretty.for_type_by_name(type_module, type_name, func)
#-----------------------------------------------------------------------------
# Initialization code for the extension
#-----------------------------------------------------------------------------
def load_ipython_extension(ip):
"""Load the extension in IPython as a hook."""
global _loaded
if not _loaded:
prd = PrettyResultDisplay(ip, name='pretty_result_display')
ip.set_hook('result_display', prd, priority=99)
_loaded = True
def unload_ipython_extension(ip):
"""Unload the extension."""
# The hook system does not have a way to remove a hook so this is a pass
pass
#-----------------------------------------------------------------------------
# Example pretty printers
#-----------------------------------------------------------------------------
def dtype_pprinter(obj, p, cycle):
""" A pretty-printer for numpy dtype objects.
"""
if cycle:
return p.text('dtype(...)')
if hasattr(obj, 'fields'):
if obj.fields is None:
p.text(repr(obj))
else:
p.begin_group(7, 'dtype([')
for i, field in enumerate(obj.descr):
if i > 0:
p.text(',')
p.breakable()
p.pretty(field)
p.end_group(7, '])')
#-----------------------------------------------------------------------------
# Tests
#-----------------------------------------------------------------------------
def test_pretty():
"""
In [1]: from IPython.extensions import ipy_pretty
In [2]: ipy_pretty.activate()
In [3]: class A(object):
...: def __repr__(self):
...: return 'A()'
...:
...:
In [4]: a = A()
In [5]: a
Out[5]: A()
In [6]: def a_pretty_printer(obj, p, cycle):
...: p.text('<A>')
...:
...:
In [7]: ipy_pretty.for_type(A, a_pretty_printer)
In [8]: a
Out[8]: <A>
In [9]: class B(object):
...: def __repr__(self):
...: return 'B()'
...:
...:
In [10]: B.__module__, B.__name__
Out[10]: ('__main__', 'B')
In [11]: def b_pretty_printer(obj, p, cycle):
....: p.text('<B>')
....:
....:
In [12]: ipy_pretty.for_type_by_name('__main__', 'B', b_pretty_printer)
In [13]: b = B()
In [14]: b
Out[14]: <B>
"""
assert False, "This should only be doctested, not run."