##// END OF EJS Templates
The pretty.py extension has been ported to the new extension API....
Brian Granger -
Show More
@@ -0,0 +1,193 b''
1 """Use pretty.py for configurable pretty-printing.
2
3 To enable this extension in your configuration
4 file, add the following to :file:`ipython_config.py`::
5
6 c.Global.extensions = ['IPython.extensions.pretty']
7 c.PrettyResultDisplay.verbose = True
8 c.PrettyResultDisplay.defaults = [
9 ('numpy', 'dtype', 'IPython.extensions.pretty.dtype_pprinter')
10 ]
11
12 This extension can also be loaded by using the ``%load_ext`` magic::
13
14 %load_ext IPython.extensions.pretty
15
16 If this extension is enabled, you can always add additional pretty printers
17 by doing::
18
19 ip = get_ipython()
20 prd = ip.get_component('pretty_result_display')
21 import numpy
22 from IPython.extensions.pretty import dtype_pprinter
23 prd.for_type(numpy.dtype, dtype_pprinter)
24
25 # If you don't want to have numpy imported until it needs to be:
26 prd.for_type_by_name('numpy', 'dtype', dtype_pprinter)
27 """
28
29 #-----------------------------------------------------------------------------
30 # Imports
31 #-----------------------------------------------------------------------------
32
33 from IPython.core.error import TryNext
34 from IPython.external import pretty
35 from IPython.core.component import Component
36 from IPython.utils.traitlets import Bool, List
37 from IPython.utils.genutils import Term
38 from IPython.utils.autoattr import auto_attr
39 from IPython.utils.importstring import import_item
40
41 #-----------------------------------------------------------------------------
42 # Code
43 #-----------------------------------------------------------------------------
44
45 _loaded = False
46
47
48 class PrettyResultDisplay(Component):
49
50 verbose = Bool(False, config=True)
51 # A list of (module_name, type_name, func_name), like
52 # [('numpy', 'dtype', 'IPython.extensions.pretty.dtype_pprinter')]
53 defaults = List(default_value=[], config=True)
54
55 def __init__(self, parent, name=None, config=None):
56 super(PrettyResultDisplay, self).__init__(parent, name=name, config=config)
57 self.setup_defaults()
58
59 def setup_defaults(self):
60 """Initialize the default pretty printers."""
61 for type_module, type_name, func_name in self.defaults:
62 func = import_item(func_name)
63 self.for_type_by_name(type_module, type_name, func)
64
65 # Access other components like this rather than by regular attribute
66 # access.
67 @auto_attr
68 def shell(self):
69 return Component.get_instances(
70 root=self.root,
71 klass='IPython.core.iplib.InteractiveShell')[0]
72
73 def __call__(self, otherself, arg):
74 """Uber-pretty-printing display hook.
75
76 Called for displaying the result to the user.
77 """
78
79 if self.shell.pprint:
80 out = pretty.pretty(arg, verbose=self.verbose)
81 if '\n' in out:
82 # So that multi-line strings line up with the left column of
83 # the screen, instead of having the output prompt mess up
84 # their first line.
85 Term.cout.write('\n')
86 print >>Term.cout, out
87 else:
88 raise TryNext
89
90 def for_type(self, typ, func):
91 """Add a pretty printer for a type."""
92 return pretty.for_type(typ, func)
93
94 def for_type_by_name(self, type_module, type_name, func):
95 """Add a pretty printer for a type by its name and module name."""
96 print type_module, type_name, func
97 return pretty.for_type_by_name(type_name, type_name, func)
98
99
100 #-----------------------------------------------------------------------------
101 # Initialization code for the extension
102 #-----------------------------------------------------------------------------
103
104
105 def load_ipython_extension(ip):
106 global _loaded
107 if not _loaded:
108 prd = PrettyResultDisplay(ip, name='pretty_result_display')
109 ip.set_hook('result_display', prd, priority=99)
110 _loaded = True
111
112 def unload_ipython_extension(ip):
113 # The hook system does not have a way to remove a hook so this is a pass
114 pass
115
116
117 #-----------------------------------------------------------------------------
118 # Example pretty printers
119 #-----------------------------------------------------------------------------
120
121
122 def dtype_pprinter(obj, p, cycle):
123 """ A pretty-printer for numpy dtype objects.
124 """
125 if cycle:
126 return p.text('dtype(...)')
127 if obj.fields is None:
128 p.text(repr(obj))
129 else:
130 p.begin_group(7, 'dtype([')
131 for i, field in enumerate(obj.descr):
132 if i > 0:
133 p.text(',')
134 p.breakable()
135 p.pretty(field)
136 p.end_group(7, '])')
137
138
139 #-----------------------------------------------------------------------------
140 # Tests
141 #-----------------------------------------------------------------------------
142
143
144 def test_pretty():
145 """
146 In [1]: from IPython.extensions import ipy_pretty
147
148 In [2]: ipy_pretty.activate()
149
150 In [3]: class A(object):
151 ...: def __repr__(self):
152 ...: return 'A()'
153 ...:
154 ...:
155
156 In [4]: a = A()
157
158 In [5]: a
159 Out[5]: A()
160
161 In [6]: def a_pretty_printer(obj, p, cycle):
162 ...: p.text('<A>')
163 ...:
164 ...:
165
166 In [7]: ipy_pretty.for_type(A, a_pretty_printer)
167
168 In [8]: a
169 Out[8]: <A>
170
171 In [9]: class B(object):
172 ...: def __repr__(self):
173 ...: return 'B()'
174 ...:
175 ...:
176
177 In [10]: B.__module__, B.__name__
178 Out[10]: ('__main__', 'B')
179
180 In [11]: def b_pretty_printer(obj, p, cycle):
181 ....: p.text('<B>')
182 ....:
183 ....:
184
185 In [12]: ipy_pretty.for_type_by_name('__main__', 'B', b_pretty_printer)
186
187 In [13]: b = B()
188
189 In [14]: b
190 Out[14]: <B>
191 """
192 assert False, "This should only be doctested, not run."
193
@@ -61,7 +61,8 b' class BuiltinTrap(Component):'
61 if self._nested_level == 1:
61 if self._nested_level == 1:
62 self.unset()
62 self.unset()
63 self._nested_level -= 1
63 self._nested_level -= 1
64 return True
64 # Returning False will cause exceptions to propagate
65 return False
65
66
66 def add_builtin(self, key, value):
67 def add_builtin(self, key, value):
67 """Add a builtin and save the original."""
68 """Add a builtin and save the original."""
@@ -62,7 +62,8 b' class DisplayTrap(Component):'
62 if self._nested_level == 1:
62 if self._nested_level == 1:
63 self.unset()
63 self.unset()
64 self._nested_level -= 1
64 self._nested_level -= 1
65 return True
65 # Returning False will cause exceptions to propagate
66 return False
66
67
67 def set(self):
68 def set(self):
68 """Set the hook."""
69 """Set the hook."""
@@ -1603,9 +1603,7 b' class InteractiveShell(Component, Magic):'
1603 magic_args = self.var_expand(magic_args,1)
1603 magic_args = self.var_expand(magic_args,1)
1604 with nested(self.builtin_trap,):
1604 with nested(self.builtin_trap,):
1605 result = fn(magic_args)
1605 result = fn(magic_args)
1606 # Unfortunately, the return statement is what will trigger
1606 return result
1607 # the displayhook, but it is no longer set!
1608 return result
1609
1607
1610 def define_magic(self, magicname, func):
1608 def define_magic(self, magicname, func):
1611 """Expose own function as magic function for ipython
1609 """Expose own function as magic function for ipython
@@ -2274,16 +2272,28 b' class InteractiveShell(Component, Magic):'
2274 return lineout
2272 return lineout
2275
2273
2276 #-------------------------------------------------------------------------
2274 #-------------------------------------------------------------------------
2275 # Working with components
2276 #-------------------------------------------------------------------------
2277
2278 def get_component(self, name=None, klass=None):
2279 """Fetch a component by name and klass in my tree."""
2280 c = Component.get_instances(root=self, name=name, klass=klass)
2281 if len(c) == 1:
2282 return c[0]
2283 else:
2284 return c
2285
2286 #-------------------------------------------------------------------------
2277 # IPython extensions
2287 # IPython extensions
2278 #-------------------------------------------------------------------------
2288 #-------------------------------------------------------------------------
2279
2289
2280 def load_extension(self, module_str):
2290 def load_extension(self, module_str):
2281 """Load an IPython extension.
2291 """Load an IPython extension by its module name.
2282
2292
2283 An IPython extension is an importable Python module that has
2293 An IPython extension is an importable Python module that has
2284 a function with the signature::
2294 a function with the signature::
2285
2295
2286 def load_in_ipython(ipython):
2296 def load_ipython_extension(ipython):
2287 # Do things with ipython
2297 # Do things with ipython
2288
2298
2289 This function is called after your extension is imported and the
2299 This function is called after your extension is imported and the
@@ -2292,6 +2302,10 b' class InteractiveShell(Component, Magic):'
2292 that point, including defining new magic and aliases, adding new
2302 that point, including defining new magic and aliases, adding new
2293 components, etc.
2303 components, etc.
2294
2304
2305 The :func:`load_ipython_extension` will be called again is you
2306 load or reload the extension again. It is up to the extension
2307 author to add code to manage that.
2308
2295 You can put your extension modules anywhere you want, as long as
2309 You can put your extension modules anywhere you want, as long as
2296 they can be imported by Python's standard import mechanism. However,
2310 they can be imported by Python's standard import mechanism. However,
2297 to make it easy to write extensions, you can also put your extensions
2311 to make it easy to write extensions, you can also put your extensions
@@ -2300,29 +2314,47 b' class InteractiveShell(Component, Magic):'
2300 """
2314 """
2301 from IPython.utils.syspathcontext import prepended_to_syspath
2315 from IPython.utils.syspathcontext import prepended_to_syspath
2302
2316
2303 if module_str in sys.modules:
2317 if module_str not in sys.modules:
2304 return
2318 with prepended_to_syspath(self.ipython_extension_dir):
2319 __import__(module_str)
2320 mod = sys.modules[module_str]
2321 self._call_load_ipython_extension(mod)
2305
2322
2306 with prepended_to_syspath(self.ipython_extension_dir):
2323 def unload_extension(self, module_str):
2307 __import__(module_str)
2324 """Unload an IPython extension by its module name.
2325
2326 This function looks up the extension's name in ``sys.modules`` and
2327 simply calls ``mod.unload_ipython_extension(self)``.
2328 """
2329 if module_str in sys.modules:
2308 mod = sys.modules[module_str]
2330 mod = sys.modules[module_str]
2309 self._call_load_in_ipython(mod)
2331 self._call_unload_ipython_extension(mod)
2310
2332
2311 def reload_extension(self, module_str):
2333 def reload_extension(self, module_str):
2312 """Reload an IPython extension by doing reload."""
2334 """Reload an IPython extension by calling reload.
2335
2336 If the module has not been loaded before,
2337 :meth:`InteractiveShell.load_extension` is called. Otherwise
2338 :func:`reload` is called and then the :func:`load_ipython_extension`
2339 function of the module, if it exists is called.
2340 """
2313 from IPython.utils.syspathcontext import prepended_to_syspath
2341 from IPython.utils.syspathcontext import prepended_to_syspath
2314
2342
2315 with prepended_to_syspath(self.ipython_extension_dir):
2343 with prepended_to_syspath(self.ipython_extension_dir):
2316 if module_str in sys.modules:
2344 if module_str in sys.modules:
2317 mod = sys.modules[module_str]
2345 mod = sys.modules[module_str]
2318 reload(mod)
2346 reload(mod)
2319 self._call_load_in_ipython(mod)
2347 self._call_load_ipython_extension(mod)
2320 else:
2348 else:
2321 self.load_extension(self, module_str)
2349 self.load_extension(module_str)
2350
2351 def _call_load_ipython_extension(self, mod):
2352 if hasattr(mod, 'load_ipython_extension'):
2353 mod.load_ipython_extension(self)
2322
2354
2323 def _call_load_in_ipython(self, mod):
2355 def _call_unload_ipython_extension(self, mod):
2324 if hasattr(mod, 'load_in_ipython'):
2356 if hasattr(mod, 'unload_ipython_extension'):
2325 mod.load_in_ipython(self)
2357 mod.unload_ipython_extension(self)
2326
2358
2327 #-------------------------------------------------------------------------
2359 #-------------------------------------------------------------------------
2328 # Things related to the prefilter
2360 # Things related to the prefilter
@@ -3538,5 +3538,16 b' Defaulting color scheme to \'NoColor\'"""'
3538 elif 'tk' in parameter_s:
3538 elif 'tk' in parameter_s:
3539 return inputhook.enable_tk(app)
3539 return inputhook.enable_tk(app)
3540
3540
3541 def magic_load_ext(self, module_str):
3542 """Load an IPython extension by its module name."""
3543 self.load_extension(module_str)
3544
3545 def magic_unload_ext(self, module_str):
3546 """Unload an IPython extension by its module name."""
3547 self.unload_extension(module_str)
3548
3549 def magic_reload_ext(self, module_str):
3550 """Reload an IPython extension by its module name."""
3551 self.reload_extension(module_str)
3541
3552
3542 # end Magic
3553 # end Magic
@@ -54,15 +54,17 b' the following attributes can be set in the ``Global`` section.'
54 :attr:`c.Global.extensions`
54 :attr:`c.Global.extensions`
55 A list of strings, each of which is an importable IPython extension. An
55 A list of strings, each of which is an importable IPython extension. An
56 IPython extension is a regular Python module or package that has a
56 IPython extension is a regular Python module or package that has a
57 :func:`load_in_ipython(ip)` method. This method gets called when the
57 :func:`load_ipython_extension(ip)` method. This method gets called when
58 extension is loaded with the currently running
58 the extension is loaded with the currently running
59 :class:`~IPython.core.iplib.InteractiveShell` as its only argument. You
59 :class:`~IPython.core.iplib.InteractiveShell` as its only argument. You
60 can put your extensions anywhere they can be imported but we add the
60 can put your extensions anywhere they can be imported but we add the
61 :file:`extensions` subdirectory of the ipython directory to ``sys.path``
61 :file:`extensions` subdirectory of the ipython directory to ``sys.path``
62 during extension loading, so you can put them there as well. Extensions
62 during extension loading, so you can put them there as well. Extensions
63 are not executed in the user's interactive namespace and they must
63 are not executed in the user's interactive namespace and they must be pure
64 be pure Python code. Extensions are the recommended way of customizing
64 Python code. Extensions are the recommended way of customizing
65 :command:`ipython`.
65 :command:`ipython`. Extensions can provide an
66 :func:`unload_ipython_extension` that will be called when the extension is
67 unloaded.
66
68
67 :attr:`c.Global.exec_lines`
69 :attr:`c.Global.exec_lines`
68 A list of strings, each of which is Python code that is run in the user's
70 A list of strings, each of which is Python code that is run in the user's
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now