##// END OF EJS Templates
Cleaner access to log call....
Cleaner access to log call. At least now we're not walking the component tree manually... A bigger refactor is still needed here, but this code is less brittle than multiple .parent access.

File last commit:

r2282:1fd4b9de
r2383:48d63c68
Show More
pretty.py
222 lines | 6.9 KiB | text/x-python | PythonLexer
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281 """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']
Brian Granger
Completed work on pretty.py extension....
r2282 def dict_pprinter(obj, p, cycle):
return p.text("<dict>")
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281 c.PrettyResultDisplay.verbose = True
Brian Granger
Completed work on pretty.py extension....
r2282 c.PrettyResultDisplay.defaults_for_type = [
(dict, dict_pprinter)
]
c.PrettyResultDisplay.defaults_for_type_by_name = [
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281 ('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
#-----------------------------------------------------------------------------
Brian Granger
Completed work on pretty.py extension....
r2282
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281 _loaded = False
class PrettyResultDisplay(Component):
Brian Granger
Completed work on pretty.py extension....
r2282 """A component for pretty printing on steroids."""
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281
verbose = Bool(False, config=True)
Brian Granger
Completed work on pretty.py extension....
r2282
# 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)
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281 # A list of (module_name, type_name, func_name), like
# [('numpy', 'dtype', 'IPython.extensions.pretty.dtype_pprinter')]
Brian Granger
Completed work on pretty.py extension....
r2282 # The final argument can also be a callable
defaults_for_type_by_name = List(default_value=[], config=True)
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281
def __init__(self, parent, name=None, config=None):
super(PrettyResultDisplay, self).__init__(parent, name=name, config=config)
Brian Granger
Completed work on pretty.py extension....
r2282 self._setup_defaults()
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281
Brian Granger
Completed work on pretty.py extension....
r2282 def _setup_defaults(self):
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281 """Initialize the default pretty printers."""
Brian Granger
Completed work on pretty.py extension....
r2282 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)
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281 self.for_type_by_name(type_module, type_name, func)
Brian Granger
Completed work on pretty.py extension....
r2282 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.
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281 @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."""
Brian Granger
Completed work on pretty.py extension....
r2282 return pretty.for_type_by_name(type_module, type_name, func)
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281
#-----------------------------------------------------------------------------
# Initialization code for the extension
#-----------------------------------------------------------------------------
def load_ipython_extension(ip):
Brian Granger
Completed work on pretty.py extension....
r2282 """Load the extension in IPython as a hook."""
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281 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):
Brian Granger
Completed work on pretty.py extension....
r2282 """Unload the extension."""
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281 # 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(...)')
Brian Granger
Completed work on pretty.py extension....
r2282 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, '])')
Brian Granger
The pretty.py extension has been ported to the new extension API....
r2281
#-----------------------------------------------------------------------------
# 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."