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 | 61 | if self._nested_level == 1: |
|
62 | 62 | self.unset() |
|
63 | 63 | self._nested_level -= 1 |
|
64 | return True | |
|
64 | # Returning False will cause exceptions to propagate | |
|
65 | return False | |
|
65 | 66 | |
|
66 | 67 | def add_builtin(self, key, value): |
|
67 | 68 | """Add a builtin and save the original.""" |
@@ -62,7 +62,8 b' class DisplayTrap(Component):' | |||
|
62 | 62 | if self._nested_level == 1: |
|
63 | 63 | self.unset() |
|
64 | 64 | self._nested_level -= 1 |
|
65 | return True | |
|
65 | # Returning False will cause exceptions to propagate | |
|
66 | return False | |
|
66 | 67 | |
|
67 | 68 | def set(self): |
|
68 | 69 | """Set the hook.""" |
@@ -1603,9 +1603,7 b' class InteractiveShell(Component, Magic):' | |||
|
1603 | 1603 | magic_args = self.var_expand(magic_args,1) |
|
1604 | 1604 | with nested(self.builtin_trap,): |
|
1605 | 1605 | result = fn(magic_args) |
|
1606 | # Unfortunately, the return statement is what will trigger | |
|
1607 | # the displayhook, but it is no longer set! | |
|
1608 | return result | |
|
1606 | return result | |
|
1609 | 1607 | |
|
1610 | 1608 | def define_magic(self, magicname, func): |
|
1611 | 1609 | """Expose own function as magic function for ipython |
@@ -2274,16 +2272,28 b' class InteractiveShell(Component, Magic):' | |||
|
2274 | 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 | 2287 | # IPython extensions |
|
2278 | 2288 | #------------------------------------------------------------------------- |
|
2279 | 2289 | |
|
2280 | 2290 | def load_extension(self, module_str): |
|
2281 | """Load an IPython extension. | |
|
2291 | """Load an IPython extension by its module name. | |
|
2282 | 2292 | |
|
2283 | 2293 | An IPython extension is an importable Python module that has |
|
2284 | 2294 | a function with the signature:: |
|
2285 | 2295 | |
|
2286 |
def load_i |
|
|
2296 | def load_ipython_extension(ipython): | |
|
2287 | 2297 | # Do things with ipython |
|
2288 | 2298 | |
|
2289 | 2299 | This function is called after your extension is imported and the |
@@ -2292,6 +2302,10 b' class InteractiveShell(Component, Magic):' | |||
|
2292 | 2302 | that point, including defining new magic and aliases, adding new |
|
2293 | 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 | 2309 | You can put your extension modules anywhere you want, as long as |
|
2296 | 2310 | they can be imported by Python's standard import mechanism. However, |
|
2297 | 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 | 2315 | from IPython.utils.syspathcontext import prepended_to_syspath |
|
2302 | 2316 | |
|
2303 | if module_str in sys.modules: | |
|
2304 | return | |
|
2317 | if module_str not in sys.modules: | |
|
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): | |
|
2307 | __import__(module_str) | |
|
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: | |
|
2308 | 2330 | mod = sys.modules[module_str] |
|
2309 |
self._call_load_i |
|
|
2331 | self._call_unload_ipython_extension(mod) | |
|
2310 | 2332 | |
|
2311 | 2333 | def reload_extension(self, module_str): |
|
2312 |
"""Reload an IPython extension by |
|
|
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 | 2341 | from IPython.utils.syspathcontext import prepended_to_syspath |
|
2314 | 2342 | |
|
2315 | 2343 | with prepended_to_syspath(self.ipython_extension_dir): |
|
2316 | 2344 | if module_str in sys.modules: |
|
2317 | 2345 | mod = sys.modules[module_str] |
|
2318 | 2346 | reload(mod) |
|
2319 |
self._call_load_i |
|
|
2347 | self._call_load_ipython_extension(mod) | |
|
2320 | 2348 | else: |
|
2321 |
self.load_extension( |
|
|
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_i |
|
|
2324 |
if hasattr(mod, 'load_i |
|
|
2325 |
mod.load_i |
|
|
2355 | def _call_unload_ipython_extension(self, mod): | |
|
2356 | if hasattr(mod, 'unload_ipython_extension'): | |
|
2357 | mod.unload_ipython_extension(self) | |
|
2326 | 2358 | |
|
2327 | 2359 | #------------------------------------------------------------------------- |
|
2328 | 2360 | # Things related to the prefilter |
@@ -3538,5 +3538,16 b' Defaulting color scheme to \'NoColor\'"""' | |||
|
3538 | 3538 | elif 'tk' in parameter_s: |
|
3539 | 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 | 3553 | # end Magic |
@@ -54,15 +54,17 b' the following attributes can be set in the ``Global`` section.' | |||
|
54 | 54 | :attr:`c.Global.extensions` |
|
55 | 55 | A list of strings, each of which is an importable IPython extension. An |
|
56 | 56 | IPython extension is a regular Python module or package that has a |
|
57 |
:func:`load_i |
|
|
58 | extension is loaded with the currently running | |
|
57 | :func:`load_ipython_extension(ip)` method. This method gets called when | |
|
58 | the extension is loaded with the currently running | |
|
59 | 59 | :class:`~IPython.core.iplib.InteractiveShell` as its only argument. You |
|
60 | 60 | can put your extensions anywhere they can be imported but we add the |
|
61 | 61 | :file:`extensions` subdirectory of the ipython directory to ``sys.path`` |
|
62 |
during extension loading, so you can put them there as well. |
|
|
63 | are not executed in the user's interactive namespace and they must | |
|
64 |
|
|
|
65 | :command:`ipython`. | |
|
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 be pure | |
|
64 | Python code. Extensions are the recommended way of customizing | |
|
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 | 69 | :attr:`c.Global.exec_lines` |
|
68 | 70 | A list of strings, each of which is Python code that is run in the user's |
|
1 | NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now