##// END OF EJS Templates
Merging upstream from trunk.
Brian Granger -
r2289:e432bee0 merge
parent child Browse files
Show More
@@ -0,0 +1,222 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 def dict_pprinter(obj, p, cycle):
8 return p.text("<dict>")
9 c.PrettyResultDisplay.verbose = True
10 c.PrettyResultDisplay.defaults_for_type = [
11 (dict, dict_pprinter)
12 ]
13 c.PrettyResultDisplay.defaults_for_type_by_name = [
14 ('numpy', 'dtype', 'IPython.extensions.pretty.dtype_pprinter')
15 ]
16
17 This extension can also be loaded by using the ``%load_ext`` magic::
18
19 %load_ext IPython.extensions.pretty
20
21 If this extension is enabled, you can always add additional pretty printers
22 by doing::
23
24 ip = get_ipython()
25 prd = ip.get_component('pretty_result_display')
26 import numpy
27 from IPython.extensions.pretty import dtype_pprinter
28 prd.for_type(numpy.dtype, dtype_pprinter)
29
30 # If you don't want to have numpy imported until it needs to be:
31 prd.for_type_by_name('numpy', 'dtype', dtype_pprinter)
32 """
33
34 #-----------------------------------------------------------------------------
35 # Imports
36 #-----------------------------------------------------------------------------
37
38 from IPython.core.error import TryNext
39 from IPython.external import pretty
40 from IPython.core.component import Component
41 from IPython.utils.traitlets import Bool, List
42 from IPython.utils.genutils import Term
43 from IPython.utils.autoattr import auto_attr
44 from IPython.utils.importstring import import_item
45
46 #-----------------------------------------------------------------------------
47 # Code
48 #-----------------------------------------------------------------------------
49
50
51 _loaded = False
52
53
54 class PrettyResultDisplay(Component):
55 """A component for pretty printing on steroids."""
56
57 verbose = Bool(False, config=True)
58
59 # A list of (type, func_name), like
60 # [(dict, 'my_dict_printer')]
61 # The final argument can also be a callable
62 defaults_for_type = List(default_value=[], config=True)
63
64 # A list of (module_name, type_name, func_name), like
65 # [('numpy', 'dtype', 'IPython.extensions.pretty.dtype_pprinter')]
66 # The final argument can also be a callable
67 defaults_for_type_by_name = List(default_value=[], config=True)
68
69 def __init__(self, parent, name=None, config=None):
70 super(PrettyResultDisplay, self).__init__(parent, name=name, config=config)
71 self._setup_defaults()
72
73 def _setup_defaults(self):
74 """Initialize the default pretty printers."""
75 for typ, func_name in self.defaults_for_type:
76 func = self._resolve_func_name(func_name)
77 self.for_type(typ, func)
78 for type_module, type_name, func_name in self.defaults_for_type_by_name:
79 func = self._resolve_func_name(func_name)
80 self.for_type_by_name(type_module, type_name, func)
81
82 def _resolve_func_name(self, func_name):
83 if callable(func_name):
84 return func_name
85 elif isinstance(func_name, basestring):
86 return import_item(func_name)
87 else:
88 raise TypeError('func_name must be a str or callable, got: %r' % func_name)
89
90 # Access other components like this rather than by a regular attribute.
91 # This won't lookup the InteractiveShell object until it is used and
92 # then it is cached. This is both efficient and couples this class
93 # more loosely to InteractiveShell.
94 @auto_attr
95 def shell(self):
96 return Component.get_instances(
97 root=self.root,
98 klass='IPython.core.iplib.InteractiveShell')[0]
99
100 def __call__(self, otherself, arg):
101 """Uber-pretty-printing display hook.
102
103 Called for displaying the result to the user.
104 """
105
106 if self.shell.pprint:
107 out = pretty.pretty(arg, verbose=self.verbose)
108 if '\n' in out:
109 # So that multi-line strings line up with the left column of
110 # the screen, instead of having the output prompt mess up
111 # their first line.
112 Term.cout.write('\n')
113 print >>Term.cout, out
114 else:
115 raise TryNext
116
117 def for_type(self, typ, func):
118 """Add a pretty printer for a type."""
119 return pretty.for_type(typ, func)
120
121 def for_type_by_name(self, type_module, type_name, func):
122 """Add a pretty printer for a type by its name and module name."""
123 return pretty.for_type_by_name(type_module, type_name, func)
124
125
126 #-----------------------------------------------------------------------------
127 # Initialization code for the extension
128 #-----------------------------------------------------------------------------
129
130
131 def load_ipython_extension(ip):
132 """Load the extension in IPython as a hook."""
133 global _loaded
134 if not _loaded:
135 prd = PrettyResultDisplay(ip, name='pretty_result_display')
136 ip.set_hook('result_display', prd, priority=99)
137 _loaded = True
138
139 def unload_ipython_extension(ip):
140 """Unload the extension."""
141 # The hook system does not have a way to remove a hook so this is a pass
142 pass
143
144
145 #-----------------------------------------------------------------------------
146 # Example pretty printers
147 #-----------------------------------------------------------------------------
148
149
150 def dtype_pprinter(obj, p, cycle):
151 """ A pretty-printer for numpy dtype objects.
152 """
153 if cycle:
154 return p.text('dtype(...)')
155 if hasattr(obj, 'fields'):
156 if obj.fields is None:
157 p.text(repr(obj))
158 else:
159 p.begin_group(7, 'dtype([')
160 for i, field in enumerate(obj.descr):
161 if i > 0:
162 p.text(',')
163 p.breakable()
164 p.pretty(field)
165 p.end_group(7, '])')
166
167
168 #-----------------------------------------------------------------------------
169 # Tests
170 #-----------------------------------------------------------------------------
171
172
173 def test_pretty():
174 """
175 In [1]: from IPython.extensions import ipy_pretty
176
177 In [2]: ipy_pretty.activate()
178
179 In [3]: class A(object):
180 ...: def __repr__(self):
181 ...: return 'A()'
182 ...:
183 ...:
184
185 In [4]: a = A()
186
187 In [5]: a
188 Out[5]: A()
189
190 In [6]: def a_pretty_printer(obj, p, cycle):
191 ...: p.text('<A>')
192 ...:
193 ...:
194
195 In [7]: ipy_pretty.for_type(A, a_pretty_printer)
196
197 In [8]: a
198 Out[8]: <A>
199
200 In [9]: class B(object):
201 ...: def __repr__(self):
202 ...: return 'B()'
203 ...:
204 ...:
205
206 In [10]: B.__module__, B.__name__
207 Out[10]: ('__main__', 'B')
208
209 In [11]: def b_pretty_printer(obj, p, cycle):
210 ....: p.text('<B>')
211 ....:
212 ....:
213
214 In [12]: ipy_pretty.for_type_by_name('__main__', 'B', b_pretty_printer)
215
216 In [13]: b = B()
217
218 In [14]: b
219 Out[14]: <B>
220 """
221 assert False, "This should only be doctested, not run."
222
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
@@ -0,0 +1,56 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
3 """
4 Simple tests for :mod:`IPython.extensions.pretty`.
5 """
6
7 #-----------------------------------------------------------------------------
8 # Copyright (C) 2008-2009 The IPython Development Team
9 #
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
13
14 #-----------------------------------------------------------------------------
15 # Imports
16 #-----------------------------------------------------------------------------
17
18 import sys
19 from unittest import TestCase
20
21 from IPython.core.component import Component, masquerade_as
22 from IPython.core.iplib import InteractiveShell
23 from IPython.extensions import pretty as pretty_ext
24 from IPython.external import pretty
25
26 from IPython.utils.traitlets import Bool
27
28 #-----------------------------------------------------------------------------
29 # Tests
30 #-----------------------------------------------------------------------------
31
32
33 class InteractiveShellStub(Component):
34 pprint = Bool(True)
35
36 class A(object):
37 pass
38
39 def a_pprinter(o, p, c):
40 return p.text("<A>")
41
42 class TestPrettyResultDisplay(TestCase):
43
44 def setUp(self):
45 self.ip = InteractiveShellStub(None)
46 # This allows our stub to be retrieved instead of the real InteractiveShell
47 masquerade_as(self.ip, InteractiveShell)
48 self.prd = pretty_ext.PrettyResultDisplay(self.ip, name='pretty_result_display')
49
50 def test_for_type(self):
51 self.prd.for_type(A, a_pprinter)
52 a = A()
53 result = pretty.pretty(a)
54 self.assertEquals(result, "<A>")
55
56
@@ -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."""
@@ -1602,10 +1602,8 b' class InteractiveShell(Component, Magic):'
1602 else:
1602 else:
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 return 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
2305
2306 with prepended_to_syspath(self.ipython_extension_dir):
2318 with prepended_to_syspath(self.ipython_extension_dir):
2307 __import__(module_str)
2319 __import__(module_str)
2308 mod = sys.modules[module_str]
2320 mod = sys.modules[module_str]
2309 self._call_load_in_ipython(mod)
2321 self._call_load_ipython_extension(mod)
2322
2323 def unload_extension(self, 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:
2330 mod = sys.modules[module_str]
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
@@ -3537,5 +3537,16 b' Defaulting color scheme to \'NoColor\'"""'
3537 elif 'tk' in parameter_s:
3537 elif 'tk' in parameter_s:
3538 return inputhook.enable_tk(app)
3538 return inputhook.enable_tk(app)
3539
3539
3540 def magic_load_ext(self, module_str):
3541 """Load an IPython extension by its module name."""
3542 self.load_extension(module_str)
3543
3544 def magic_unload_ext(self, module_str):
3545 """Unload an IPython extension by its module name."""
3546 self.unload_extension(module_str)
3547
3548 def magic_reload_ext(self, module_str):
3549 """Reload an IPython extension by its module name."""
3550 self.reload_extension(module_str)
3540
3551
3541 # end Magic
3552 # end Magic
@@ -164,7 +164,7 b" latex_font_size = '11pt'"
164
164
165 latex_documents = [ ('index', 'ipython.tex', 'IPython Documentation',
165 latex_documents = [ ('index', 'ipython.tex', 'IPython Documentation',
166 ur"""The IPython Development Team""",
166 ur"""The IPython Development Team""",
167 'manual'),
167 'manual', True),
168 ]
168 ]
169
169
170 # The name of an image file (relative to this directory) to place at the top of
170 # The name of an image file (relative to this directory) to place at the top of
@@ -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
@@ -23,11 +23,16 b' Subpackage descriptions'
23 this code will either i) be revived by someone willing to maintain it with
23 this code will either i) be revived by someone willing to maintain it with
24 tests and docs and re-included into IPython or 2) be removed from IPython
24 tests and docs and re-included into IPython or 2) be removed from IPython
25 proper, but put into a separate third-party Python package. No new code will
25 proper, but put into a separate third-party Python package. No new code will
26 be allowed here.
26 be allowed here. If your favorite extension has been moved here please
27 contact the IPython developer mailing list to help us determine the best
28 course of action.
27
29
28 * :mod:`IPython.extensions`. This package contains fully supported IPython
30 * :mod:`IPython.extensions`. This package contains fully supported IPython
29 extensions. These extensions adhere to the official IPython extension API
31 extensions. These extensions adhere to the official IPython extension API
30 and can be enabled by adding them to a field in the configuration file.
32 and can be enabled by adding them to a field in the configuration file.
33 If your extension is no longer in this location, please look in
34 :mod:`IPython.quarantine` and :mod:`IPython.deathrow` and contact the
35 IPython developer mailing list.
31
36
32 * :mod:`IPython.external`. This package contains third party packages and
37 * :mod:`IPython.external`. This package contains third party packages and
33 modules that IPython ships internally to reduce the number of dependencies.
38 modules that IPython ships internally to reduce the number of dependencies.
@@ -49,7 +54,9 b' Subpackage descriptions'
49 * :mod:`IPython.quarantine`. This is for code that doesn't meet IPython's
54 * :mod:`IPython.quarantine`. This is for code that doesn't meet IPython's
50 standards, but that we plan on keeping. To be moved out of this sub-package
55 standards, but that we plan on keeping. To be moved out of this sub-package
51 a module needs to have approval of the core IPython developers, tests and
56 a module needs to have approval of the core IPython developers, tests and
52 documentation.
57 documentation. If your favorite extension has been moved here please contact
58 the IPython developer mailing list to help us determine the best course of
59 action.
53
60
54 * :mod:`IPython.scripts`. This package contains a variety of top-level
61 * :mod:`IPython.scripts`. This package contains a variety of top-level
55 command line scripts. Eventually, these should be moved to the
62 command line scripts. Eventually, these should be moved to the
@@ -85,7 +85,7 b' Actually using MPI'
85 Once the engines are running with MPI enabled, you are ready to go. You can
85 Once the engines are running with MPI enabled, you are ready to go. You can
86 now call any code that uses MPI in the IPython engines. And, all of this can
86 now call any code that uses MPI in the IPython engines. And, all of this can
87 be done interactively. Here we show a simple example that uses mpi4py
87 be done interactively. Here we show a simple example that uses mpi4py
88 [mpi4py]_.
88 [mpi4py]_ version 1.1.0 or later.
89
89
90 First, lets define a simply function that uses MPI to calculate the sum of a
90 First, lets define a simply function that uses MPI to calculate the sum of a
91 distributed array. Save the following text in a file called :file:`psum.py`:
91 distributed array. Save the following text in a file called :file:`psum.py`:
@@ -97,7 +97,11 b' distributed array. Save the following text in a file called :file:`psum.py`:'
97
97
98 def psum(a):
98 def psum(a):
99 s = np.sum(a)
99 s = np.sum(a)
100 return MPI.COMM_WORLD.Allreduce(s,MPI.SUM)
100 rcvBuf = np.array(0.0,'d')
101 MPI.COMM_WORLD.Allreduce([s, MPI.DOUBLE],
102 [rcvBuf, MPI.DOUBLE],
103 op=MPI.SUM)
104 return rcvBuf
101
105
102 Now, start an IPython cluster in the same directory as :file:`psum.py`::
106 Now, start an IPython cluster in the same directory as :file:`psum.py`::
103
107
@@ -26,6 +26,12 b' For more details, please consult the actual source.'
26 New features
26 New features
27 ------------
27 ------------
28
28
29 * The :mod:`IPython.extensions.pretty` extension has been moved out of
30 quarantine and fully updated to the new extension API.
31
32 * New magics for loading/unloading/reloading extensions have been added:
33 ``%load_ext``, ``%unload_ext`` and ``%reload_ext``.
34
29 * The configuration system and configuration files are brand new. See the
35 * The configuration system and configuration files are brand new. See the
30 configuration system :ref:`documentation <config_index>` for more details.
36 configuration system :ref:`documentation <config_index>` for more details.
31
37
@@ -133,12 +139,25 b' New features'
133 Bug fixes
139 Bug fixes
134 ---------
140 ---------
135
141
142 * Previously, the latex Sphinx docs were in a single chapter. This has been
143 fixed by adding a sixth argument of True to the ``latex_documents``
144 attribute of :file:`conf.py`.
145
146 * The ``psum`` example in the MPI documentation has been updated to mpi4py
147 version 1.1.0. Thanks to J. Thomas for this fix.
148
149 * The top-level, zero-install :file:`ipython.py` script has been updated to
150 the new application launching API.
151
136 * Keyboard interrupts now work with GUI support enabled across all platforms
152 * Keyboard interrupts now work with GUI support enabled across all platforms
137 and all GUI toolkits reliably.
153 and all GUI toolkits reliably.
138
154
139 Backwards incompatible changes
155 Backwards incompatible changes
140 ------------------------------
156 ------------------------------
141
157
158 * The extension loading functions have been renamed to
159 :func:`load_ipython_extension` and :func:`unload_ipython_extension`.
160
142 * :class:`~IPython.core.iplib.InteractiveShell` no longer takes an
161 * :class:`~IPython.core.iplib.InteractiveShell` no longer takes an
143 ``embedded`` argument. Instead just use the
162 ``embedded`` argument. Instead just use the
144 :class:`~IPython.core.iplib.InteractiveShellEmbed` class.
163 :class:`~IPython.core.iplib.InteractiveShellEmbed` class.
@@ -7,5 +7,6 b" in './scripts' directory. This file is here (ipython source root directory)"
7 to facilitate non-root 'zero-installation' (just copy the source tree
7 to facilitate non-root 'zero-installation' (just copy the source tree
8 somewhere and run ipython.py) and development. """
8 somewhere and run ipython.py) and development. """
9
9
10 import IPython.core.shell
10 from IPython.core.ipapp import launch_new_instance
11 IPython.core.shell.start().mainloop()
11
12 launch_new_instance()
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