Show More
@@ -0,0 +1,160 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | """Displayhook formatters. | |
|
3 | ||
|
4 | The DefaultFormatter is always present and may be configured from the | |
|
5 | ipython_config.py file. For example, to add a pretty-printer for a numpy.dtype | |
|
6 | object:: | |
|
7 | ||
|
8 | def dtype_pprinter(obj, p, cycle): | |
|
9 | if cycle: | |
|
10 | return p.text('dtype(...)') | |
|
11 | if hasattr(obj, 'fields'): | |
|
12 | if obj.fields is None: | |
|
13 | p.text(repr(obj)) | |
|
14 | else: | |
|
15 | p.begin_group(7, 'dtype([') | |
|
16 | for i, field in enumerate(obj.descr): | |
|
17 | if i > 0: | |
|
18 | p.text(',') | |
|
19 | p.breakable() | |
|
20 | p.pretty(field) | |
|
21 | p.end_group(7, '])') | |
|
22 | ||
|
23 | c.DefaultFormatter.deferred_pprinters = { | |
|
24 | ('numpy', 'dtype'): dtype_pprinter, | |
|
25 | } | |
|
26 | ||
|
27 | The deferred_pprinters dictionary is the preferred way to configure these | |
|
28 | pretty-printers. This allows you to define the pretty-printer without needing to | |
|
29 | import the type itself. The dictionary maps (modulename, typename) pairs to | |
|
30 | a function. | |
|
31 | ||
|
32 | See the `IPython.external.pretty` documentation for how to write | |
|
33 | pretty-printer functions. | |
|
34 | ||
|
35 | Authors: | |
|
36 | ||
|
37 | * Robert Kern | |
|
38 | """ | |
|
39 | ||
|
40 | import abc | |
|
41 | from cStringIO import StringIO | |
|
42 | ||
|
43 | from IPython.config.configurable import Configurable | |
|
44 | from IPython.external import pretty | |
|
45 | from IPython.utils.traitlets import Bool, Dict, Int, Str | |
|
46 | ||
|
47 | ||
|
48 | class DefaultFormatter(Configurable): | |
|
49 | """ The default pretty-printer. | |
|
50 | """ | |
|
51 | ||
|
52 | # The ID of the formatter. | |
|
53 | id = Str('default') | |
|
54 | ||
|
55 | # The kind of data returned. | |
|
56 | # This is often, but not always a MIME type. | |
|
57 | format = Str('text/plain') | |
|
58 | ||
|
59 | # Whether to pretty-print or not. | |
|
60 | pprint = Bool(True, config=True) | |
|
61 | ||
|
62 | # Whether to be verbose or not. | |
|
63 | verbose = Bool(False, config=True) | |
|
64 | ||
|
65 | # The maximum width. | |
|
66 | max_width = Int(79, config=True) | |
|
67 | ||
|
68 | # The newline character. | |
|
69 | newline = Str('\n', config=True) | |
|
70 | ||
|
71 | # The singleton prettyprinters. | |
|
72 | # Maps the IDs of the builtin singleton objects to the format functions. | |
|
73 | singleton_pprinters = Dict(config=True) | |
|
74 | def _singleton_pprinters_default(self): | |
|
75 | return pretty._singleton_pprinters.copy() | |
|
76 | ||
|
77 | # The type-specific prettyprinters. | |
|
78 | # Map type objects to the format functions. | |
|
79 | type_pprinters = Dict(config=True) | |
|
80 | def _type_pprinters_default(self): | |
|
81 | return pretty._type_pprinters.copy() | |
|
82 | ||
|
83 | # The deferred-import type-specific prettyprinters. | |
|
84 | # Map (modulename, classname) pairs to the format functions. | |
|
85 | deferred_pprinters = Dict(config=True) | |
|
86 | def _deferred_pprinters_default(self): | |
|
87 | return pretty._deferred_type_pprinters.copy() | |
|
88 | ||
|
89 | #### FormatterABC interface #### | |
|
90 | ||
|
91 | def __call__(self, obj): | |
|
92 | """ Format the object. | |
|
93 | """ | |
|
94 | if not self.pprint: | |
|
95 | try: | |
|
96 | return repr(obj) | |
|
97 | except TypeError: | |
|
98 | return '' | |
|
99 | else: | |
|
100 | stream = StringIO() | |
|
101 | printer = pretty.RepresentationPrinter(stream, self.verbose, | |
|
102 | self.max_width, self.newline, | |
|
103 | singleton_pprinters=self.singleton_pprinters, | |
|
104 | type_pprinters=self.type_pprinters, | |
|
105 | deferred_pprinters=self.deferred_pprinters) | |
|
106 | printer.pretty(obj) | |
|
107 | printer.flush() | |
|
108 | return stream.getvalue() | |
|
109 | ||
|
110 | ||
|
111 | #### DefaultFormatter interface #### | |
|
112 | ||
|
113 | def for_type(self, typ, func): | |
|
114 | """ | |
|
115 | Add a pretty printer for a given type. | |
|
116 | """ | |
|
117 | oldfunc = self.type_pprinters.get(typ, None) | |
|
118 | if func is not None: | |
|
119 | # To support easy restoration of old pprinters, we need to ignore | |
|
120 | # Nones. | |
|
121 | self.type_pprinters[typ] = func | |
|
122 | return oldfunc | |
|
123 | ||
|
124 | def for_type_by_name(self, type_module, type_name, func): | |
|
125 | """ | |
|
126 | Add a pretty printer for a type specified by the module and name of | |
|
127 | a type rather than the type object itself. | |
|
128 | """ | |
|
129 | key = (type_module, type_name) | |
|
130 | oldfunc = self.deferred_pprinters.get(key, None) | |
|
131 | if func is not None: | |
|
132 | # To support easy restoration of old pprinters, we need to ignore | |
|
133 | # Nones. | |
|
134 | self.deferred_pprinters[key] = func | |
|
135 | return oldfunc | |
|
136 | ||
|
137 | ||
|
138 | class FormatterABC(object): | |
|
139 | """ Abstract base class for Formatters. | |
|
140 | """ | |
|
141 | __metaclass__ = abc.ABCMeta | |
|
142 | ||
|
143 | # The ID of the formatter. | |
|
144 | id = 'abstract' | |
|
145 | ||
|
146 | # The kind of data returned. | |
|
147 | format = 'text/plain' | |
|
148 | ||
|
149 | @abc.abstractmethod | |
|
150 | def __call__(self, obj): | |
|
151 | """ Return a JSONable representation of the object. | |
|
152 | ||
|
153 | If the object cannot be formatted by this formatter, then return None | |
|
154 | """ | |
|
155 | try: | |
|
156 | return repr(obj) | |
|
157 | except TypeError: | |
|
158 | return None | |
|
159 | ||
|
160 | FormatterABC.register(DefaultFormatter) |
@@ -0,0 +1,30 b'' | |||
|
1 | """Tests for the Formatters. | |
|
2 | """ | |
|
3 | ||
|
4 | import nose.tools as nt | |
|
5 | ||
|
6 | from IPython.core.formatters import FormatterABC, DefaultFormatter | |
|
7 | ||
|
8 | class A(object): | |
|
9 | def __repr__(self): | |
|
10 | return 'A()' | |
|
11 | ||
|
12 | class B(A): | |
|
13 | def __repr__(self): | |
|
14 | return 'B()' | |
|
15 | ||
|
16 | def foo_printer(obj, pp, cycle): | |
|
17 | pp.text('foo') | |
|
18 | ||
|
19 | def test_pretty(): | |
|
20 | f = DefaultFormatter() | |
|
21 | f.for_type(A, foo_printer) | |
|
22 | nt.assert_equals(f(A()), 'foo') | |
|
23 | nt.assert_equals(f(B()), 'foo') | |
|
24 | f.pprint = False | |
|
25 | nt.assert_equals(f(A()), 'A()') | |
|
26 | nt.assert_equals(f(B()), 'B()') | |
|
27 | ||
|
28 | def test_deferred(): | |
|
29 | f = DefaultFormatter() | |
|
30 |
@@ -20,15 +20,14 b' Authors:' | |||
|
20 | 20 | #----------------------------------------------------------------------------- |
|
21 | 21 | |
|
22 | 22 | import __builtin__ |
|
23 | from pprint import PrettyPrinter | |
|
24 | pformat = PrettyPrinter().pformat | |
|
25 | 23 | |
|
26 | 24 | from IPython.config.configurable import Configurable |
|
27 | 25 | from IPython.core import prompts |
|
28 | 26 | import IPython.utils.generics |
|
29 | 27 | import IPython.utils.io |
|
30 |
from IPython.utils.traitlets import Instance, |
|
|
28 | from IPython.utils.traitlets import Instance, List | |
|
31 | 29 | from IPython.utils.warn import warn |
|
30 | from IPython.core.formatters import DefaultFormatter | |
|
32 | 31 | |
|
33 | 32 | #----------------------------------------------------------------------------- |
|
34 | 33 | # Main displayhook class |
@@ -55,6 +54,16 b' class DisplayHook(Configurable):' | |||
|
55 | 54 | |
|
56 | 55 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') |
|
57 | 56 | |
|
57 | # The default formatter. | |
|
58 | default_formatter = Instance('IPython.core.formatters.FormatterABC') | |
|
59 | def _default_formatter_default(self): | |
|
60 | # FIXME: backwards compatibility for the InteractiveShell.pprint option? | |
|
61 | return DefaultFormatter(config=self.config) | |
|
62 | ||
|
63 | # Any additional FormatterABC instances we use. | |
|
64 | # FIXME: currently unused. | |
|
65 | extra_formatters = List(config=True) | |
|
66 | ||
|
58 | 67 | # Each call to the In[] prompt raises it by 1, even the first. |
|
59 | 68 | #prompt_count = Int(0) |
|
60 | 69 | |
@@ -109,7 +118,6 b' class DisplayHook(Configurable):' | |||
|
109 | 118 | self.output_sep = output_sep |
|
110 | 119 | self.output_sep2 = output_sep2 |
|
111 | 120 | self._,self.__,self.___ = '','','' |
|
112 | self.pprint_types = map(type,[(),[],{}]) | |
|
113 | 121 | |
|
114 | 122 | # these are deliberately global: |
|
115 | 123 | to_user_ns = {'_':self._,'__':self.__,'___':self.___} |
@@ -184,39 +192,35 b' class DisplayHook(Configurable):' | |||
|
184 | 192 | if self.do_full_cache: |
|
185 | 193 | IPython.utils.io.Term.cout.write(outprompt) |
|
186 | 194 | |
|
187 | # TODO: Make this method an extension point. The previous implementation | |
|
188 | # has both a result_display hook as well as a result_display generic | |
|
189 | # function to customize the repr on a per class basis. We need to rethink | |
|
190 | # the hooks mechanism before doing this though. | |
|
191 | 195 | def compute_result_repr(self, result): |
|
192 | 196 | """Compute and return the repr of the object to be displayed. |
|
193 | 197 | |
|
194 | 198 | This method only compute the string form of the repr and should NOT |
|
195 |
actual print or write that to a stream. |
|
|
196 | the result itself, but the default implementation passes the original | |
|
197 | through. | |
|
199 | actual print or write that to a stream. | |
|
198 | 200 | """ |
|
199 | try: | |
|
200 | if self.shell.pprint: | |
|
201 | try: | |
|
202 | result_repr = pformat(result) | |
|
203 | except: | |
|
204 | # Work around possible bugs in pformat | |
|
205 | result_repr = repr(result) | |
|
206 | if '\n' in result_repr: | |
|
207 | # So that multi-line strings line up with the left column of | |
|
208 | # the screen, instead of having the output prompt mess up | |
|
209 | # their first line. | |
|
210 | result_repr = '\n' + result_repr | |
|
211 |
|
|
|
212 |
|
|
|
213 |
except |
|
|
214 | # This happens when result.__repr__ doesn't return a string, | |
|
215 | # such as when it returns None. | |
|
216 | result_repr = '\n' | |
|
217 | return result, result_repr | |
|
218 | ||
|
219 | def write_result_repr(self, result_repr): | |
|
201 | result_repr = self.default_formatter(result) | |
|
202 | if '\n' in result_repr: | |
|
203 | # So that multi-line strings line up with the left column of | |
|
204 | # the screen, instead of having the output prompt mess up | |
|
205 | # their first line. | |
|
206 | outprompt = str(self.prompt_out) | |
|
207 | if outprompt and not outprompt.endswith('\n'): | |
|
208 | # But avoid extraneous empty lines. | |
|
209 | result_repr = '\n' + result_repr | |
|
210 | ||
|
211 | extra_formats = [] | |
|
212 | for f in self.extra_formatters: | |
|
213 | try: | |
|
214 | data = f(result) | |
|
215 | except Exception: | |
|
216 | # FIXME: log the exception. | |
|
217 | continue | |
|
218 | if data is not None: | |
|
219 | extra_formats.append((f.id, f.format, data)) | |
|
220 | ||
|
221 | return result_repr, extra_formats | |
|
222 | ||
|
223 | def write_result_repr(self, result_repr, extra_formats): | |
|
220 | 224 | # We want to print because we want to always make sure we have a |
|
221 | 225 | # newline, even if all the prompt separators are ''. This is the |
|
222 | 226 | # standard IPython behavior. |
@@ -271,8 +275,8 b' class DisplayHook(Configurable):' | |||
|
271 | 275 | if result is not None and not self.quiet(): |
|
272 | 276 | self.start_displayhook() |
|
273 | 277 | self.write_output_prompt() |
|
274 |
result, |
|
|
275 | self.write_result_repr(result_repr) | |
|
278 | result_repr, extra_formats = self.compute_result_repr(result) | |
|
279 | self.write_result_repr(result_repr, extra_formats) | |
|
276 | 280 | self.update_user_ns(result) |
|
277 | 281 | self.log_output(result) |
|
278 | 282 | self.finish_displayhook() |
@@ -475,6 +475,7 b' class InteractiveShell(Configurable, Magic):' | |||
|
475 | 475 | def init_displayhook(self): |
|
476 | 476 | # Initialize displayhook, set in/out prompts and printing system |
|
477 | 477 | self.displayhook = self.displayhook_class( |
|
478 | config=self.config, | |
|
478 | 479 | shell=self, |
|
479 | 480 | cache_size=self.cache_size, |
|
480 | 481 | input_sep = self.separate_in, |
@@ -306,10 +306,21 b' class RepresentationPrinter(PrettyPrinter):' | |||
|
306 | 306 | verbose mode. |
|
307 | 307 | """ |
|
308 | 308 | |
|
309 |
def __init__(self, output, verbose=False, max_width=79, newline='\n' |
|
|
309 | def __init__(self, output, verbose=False, max_width=79, newline='\n', | |
|
310 | singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None): | |
|
311 | ||
|
310 | 312 | PrettyPrinter.__init__(self, output, max_width, newline) |
|
311 | 313 | self.verbose = verbose |
|
312 | 314 | self.stack = [] |
|
315 | if singleton_pprinters is None: | |
|
316 | singleton_pprinters = _singleton_pprinters.copy() | |
|
317 | self.singleton_pprinters = singleton_pprinters | |
|
318 | if type_pprinters is None: | |
|
319 | type_pprinters = _type_pprinters.copy() | |
|
320 | self.type_pprinters = type_pprinters | |
|
321 | if deferred_pprinters is None: | |
|
322 | deferred_pprinters = _deferred_type_pprinters.copy() | |
|
323 | self.deferred_pprinters = deferred_pprinters | |
|
313 | 324 | |
|
314 | 325 | def pretty(self, obj): |
|
315 | 326 | """Pretty print the given object.""" |
@@ -322,14 +333,14 b' class RepresentationPrinter(PrettyPrinter):' | |||
|
322 | 333 | if hasattr(obj_class, '__pretty__'): |
|
323 | 334 | return obj_class.__pretty__(obj, self, cycle) |
|
324 | 335 | try: |
|
325 |
printer = |
|
|
336 | printer = self.singleton_pprinters[obj_id] | |
|
326 | 337 | except (TypeError, KeyError): |
|
327 | 338 | pass |
|
328 | 339 | else: |
|
329 | 340 | return printer(obj, self, cycle) |
|
330 | 341 | for cls in _get_mro(obj_class): |
|
331 |
if cls in |
|
|
332 |
return |
|
|
342 | if cls in self.type_pprinters: | |
|
343 | return self.type_pprinters[cls](obj, self, cycle) | |
|
333 | 344 | else: |
|
334 | 345 | printer = self._in_deferred_types(cls) |
|
335 | 346 | if printer is not None: |
@@ -351,14 +362,13 b' class RepresentationPrinter(PrettyPrinter):' | |||
|
351 | 362 | name = getattr(cls, '__name__', None) |
|
352 | 363 | key = (mod, name) |
|
353 | 364 | printer = None |
|
354 |
if key in |
|
|
365 | if key in self.deferred_pprinters: | |
|
355 | 366 | # Move the printer over to the regular registry. |
|
356 |
printer = |
|
|
357 |
|
|
|
367 | printer = self.deferred_pprinters.pop(key) | |
|
368 | self.type_pprinters[cls] = printer | |
|
358 | 369 | return printer |
|
359 | 370 | |
|
360 | 371 | |
|
361 | ||
|
362 | 372 | class Printable(object): |
|
363 | 373 | |
|
364 | 374 | def output(self, stream, output_width): |
@@ -1,11 +1,14 b'' | |||
|
1 | 1 | """ Defines miscellaneous Qt-related helper classes and functions. |
|
2 | 2 | """ |
|
3 | 3 | |
|
4 | # Standard library imports. | |
|
5 | import inspect | |
|
6 | ||
|
4 | 7 | # System library imports. |
|
5 | 8 | from PyQt4 import QtCore, QtGui |
|
6 | 9 | |
|
7 | 10 | # IPython imports. |
|
8 | from IPython.utils.traitlets import HasTraits | |
|
11 | from IPython.utils.traitlets import HasTraits, TraitType | |
|
9 | 12 | |
|
10 | 13 | #----------------------------------------------------------------------------- |
|
11 | 14 | # Metaclasses |
@@ -14,7 +17,6 b' from IPython.utils.traitlets import HasTraits' | |||
|
14 | 17 | MetaHasTraits = type(HasTraits) |
|
15 | 18 | MetaQObject = type(QtCore.QObject) |
|
16 | 19 | |
|
17 | # You can switch the order of the parents here and it doesn't seem to matter. | |
|
18 | 20 | class MetaQObjectHasTraits(MetaQObject, MetaHasTraits): |
|
19 | 21 | """ A metaclass that inherits from the metaclasses of HasTraits and QObject. |
|
20 | 22 | |
@@ -22,7 +24,24 b' class MetaQObjectHasTraits(MetaQObject, MetaHasTraits):' | |||
|
22 | 24 | QObject. Using SuperQObject instead of QObject is highly recommended. See |
|
23 | 25 | QtKernelManager for an example. |
|
24 | 26 | """ |
|
25 | pass | |
|
27 | def __new__(mcls, name, bases, classdict): | |
|
28 | # FIXME: this duplicates the code from MetaHasTraits. | |
|
29 | # I don't think a super() call will help me here. | |
|
30 | for k,v in classdict.iteritems(): | |
|
31 | if isinstance(v, TraitType): | |
|
32 | v.name = k | |
|
33 | elif inspect.isclass(v): | |
|
34 | if issubclass(v, TraitType): | |
|
35 | vinst = v() | |
|
36 | vinst.name = k | |
|
37 | classdict[k] = vinst | |
|
38 | cls = MetaQObject.__new__(mcls, name, bases, classdict) | |
|
39 | return cls | |
|
40 | ||
|
41 | def __init__(mcls, name, bases, classdict): | |
|
42 | # Note: super() did not work, so we explicitly call these. | |
|
43 | MetaQObject.__init__(mcls, name, bases, classdict) | |
|
44 | MetaHasTraits.__init__(mcls, name, bases, classdict) | |
|
26 | 45 | |
|
27 | 46 | #----------------------------------------------------------------------------- |
|
28 | 47 | # Classes |
@@ -129,6 +129,29 b' class TestTraitType(TestCase):' | |||
|
129 | 129 | a = A() |
|
130 | 130 | self.assertRaises(TraitError, A.tt.error, a, 10) |
|
131 | 131 | |
|
132 | def test_dynamic_initializer(self): | |
|
133 | class A(HasTraits): | |
|
134 | x = Int(10) | |
|
135 | def _x_default(self): | |
|
136 | return 11 | |
|
137 | class B(A): | |
|
138 | x = Int(20) | |
|
139 | class C(A): | |
|
140 | def _x_default(self): | |
|
141 | return 21 | |
|
142 | ||
|
143 | a = A() | |
|
144 | self.assertEquals(a._trait_values, {}) | |
|
145 | self.assertEquals(a.x, 11) | |
|
146 | self.assertEquals(a._trait_values, {'x': 11}) | |
|
147 | b = B() | |
|
148 | self.assertEquals(b._trait_values, {'x': 20}) | |
|
149 | self.assertEquals(b.x, 20) | |
|
150 | c = C() | |
|
151 | self.assertEquals(c._trait_values, {}) | |
|
152 | self.assertEquals(c.x, 21) | |
|
153 | self.assertEquals(c._trait_values, {'x': 21}) | |
|
154 | ||
|
132 | 155 | |
|
133 | 156 | class TestHasTraitsMeta(TestCase): |
|
134 | 157 |
@@ -248,9 +248,21 b' class TraitType(object):' | |||
|
248 | 248 | default values must be delayed until the parent :class:`HasTraits` |
|
249 | 249 | class has been instantiated. |
|
250 | 250 | """ |
|
251 | dv = self.get_default_value() | |
|
252 | newdv = self._validate(obj, dv) | |
|
253 | obj._trait_values[self.name] = newdv | |
|
251 | # Check for a deferred initializer defined in the same class as the | |
|
252 | # trait declaration or above. | |
|
253 | mro = type(obj).mro() | |
|
254 | meth_name = '_%s_default' % self.name | |
|
255 | for cls in mro[:mro.index(self.this_class)+1]: | |
|
256 | if meth_name in cls.__dict__: | |
|
257 | break | |
|
258 | else: | |
|
259 | # We didn't find one. Do static initialization. | |
|
260 | dv = self.get_default_value() | |
|
261 | newdv = self._validate(obj, dv) | |
|
262 | obj._trait_values[self.name] = newdv | |
|
263 | return | |
|
264 | # Complete the dynamic initialization. | |
|
265 | self.dynamic_initializer = cls.__dict__[meth_name] | |
|
254 | 266 | |
|
255 | 267 | def __get__(self, obj, cls=None): |
|
256 | 268 | """Get the value of the trait by self.name for the instance. |
@@ -265,7 +277,19 b' class TraitType(object):' | |||
|
265 | 277 | else: |
|
266 | 278 | try: |
|
267 | 279 | value = obj._trait_values[self.name] |
|
268 | except: | |
|
280 | except KeyError: | |
|
281 | # Check for a dynamic initializer. | |
|
282 | if hasattr(self, 'dynamic_initializer'): | |
|
283 | value = self.dynamic_initializer(obj) | |
|
284 | # FIXME: Do we really validate here? | |
|
285 | value = self._validate(obj, value) | |
|
286 | obj._trait_values[self.name] = value | |
|
287 | return value | |
|
288 | else: | |
|
289 | raise TraitError('Unexpected error in TraitType: ' | |
|
290 | 'both default value and dynamic initializer are ' | |
|
291 | 'absent.') | |
|
292 | except Exception: | |
|
269 | 293 | # HasTraits should call set_default_value to populate |
|
270 | 294 | # this. So this should never be reached. |
|
271 | 295 | raise TraitError('Unexpected error in TraitType: ' |
@@ -294,6 +318,11 b' class TraitType(object):' | |||
|
294 | 318 | else: |
|
295 | 319 | return value |
|
296 | 320 | |
|
321 | def set_dynamic_initializer(self, method): | |
|
322 | """ Set the dynamic initializer method, if any. | |
|
323 | """ | |
|
324 | self.dynamic_initializer = method | |
|
325 | ||
|
297 | 326 | def info(self): |
|
298 | 327 | return self.info_text |
|
299 | 328 |
@@ -65,8 +65,9 b' class ZMQDisplayHook(DisplayHook):' | |||
|
65 | 65 | if self.do_full_cache: |
|
66 | 66 | self.msg['content']['execution_count'] = self.prompt_count |
|
67 | 67 | |
|
68 | def write_result_repr(self, result_repr): | |
|
68 | def write_result_repr(self, result_repr, extra_formats): | |
|
69 | 69 | self.msg['content']['data'] = result_repr |
|
70 | self.msg['content']['extra_formats'] = extra_formats | |
|
70 | 71 | |
|
71 | 72 | def finish_displayhook(self): |
|
72 | 73 | """Finish up all displayhook activities.""" |
@@ -725,16 +725,35 b' case, the kernel instantiates as ``sys.displayhook`` an object which has' | |||
|
725 | 725 | similar behavior, but which instead of printing to stdout, broadcasts these |
|
726 | 726 | values as ``pyout`` messages for clients to display appropriately. |
|
727 | 727 | |
|
728 | IPython's displayhook can handle multiple simultaneous formats depending on its | |
|
729 | configuration. The default pretty-printed repr text is always given with the | |
|
730 | ``data`` entry in this message. Any other formats are provided in the | |
|
731 | ``extra_formats`` list. Frontends are free to display any or all of these | |
|
732 | according to its capabilities. ``extra_formats`` list contains 3-tuples of an ID | |
|
733 | string, a type string, and the data. The ID is unique to the formatter | |
|
734 | implementation that created the data. Frontends will typically ignore the ID | |
|
735 | unless if it has requested a particular formatter. The type string tells the | |
|
736 | frontend how to interpret the data. It is often, but not always a MIME type. | |
|
737 | Frontends should ignore types that it does not understand. The data itself is | |
|
738 | any JSON object and depends on the format. It is often, but not always a string. | |
|
739 | ||
|
728 | 740 | Message type: ``pyout``:: |
|
729 | 741 | |
|
730 | 742 | content = { |
|
731 | # The data is typically the repr() of the object. | |
|
732 | 'data' : str, | |
|
743 | # The data is typically the repr() of the object. It should be displayed | |
|
744 | # as monospaced text. | |
|
745 | 'data' : str, | |
|
733 | 746 | |
|
734 | # The counter for this execution is also provided so that clients can | |
|
735 |
# display it, since IPython automatically creates variables called _N |
|
|
736 | # prompt N). | |
|
737 | 'execution_count' : int, | |
|
747 | # The counter for this execution is also provided so that clients can | |
|
748 | # display it, since IPython automatically creates variables called _N | |
|
749 | # (for prompt N). | |
|
750 | 'execution_count' : int, | |
|
751 | ||
|
752 | # Any extra formats. | |
|
753 | # The tuples are of the form (ID, type, data). | |
|
754 | 'extra_formats' : [ | |
|
755 | [str, str, object] | |
|
756 | ] | |
|
738 | 757 | } |
|
739 | 758 | |
|
740 | 759 | Python errors |
General Comments 0
You need to be logged in to leave comments.
Login now