##// END OF EJS Templates
catch NotImplementedError, not NotImplemented...
MinRK -
Show More
@@ -1,695 +1,701 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Top-level display functions for displaying object in different formats.
2 """Top-level display functions for displaying object in different formats.
3
3
4 Authors:
4 Authors:
5
5
6 * Brian Granger
6 * Brian Granger
7 """
7 """
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2013 The IPython Development Team
10 # Copyright (C) 2013 The IPython Development Team
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Imports
17 # Imports
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 from __future__ import print_function
20 from __future__ import print_function
21
21
22 import os
22 import os
23 import struct
23 import struct
24
24
25 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
25 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
26 unicode_type)
26 unicode_type)
27
27
28 from .displaypub import publish_display_data
28 from .displaypub import publish_display_data
29
29
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31 # utility functions
31 # utility functions
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33
33
34 def _safe_exists(path):
34 def _safe_exists(path):
35 """Check path, but don't let exceptions raise"""
35 """Check path, but don't let exceptions raise"""
36 try:
36 try:
37 return os.path.exists(path)
37 return os.path.exists(path)
38 except Exception:
38 except Exception:
39 return False
39 return False
40
40
41 def _merge(d1, d2):
41 def _merge(d1, d2):
42 """Like update, but merges sub-dicts instead of clobbering at the top level.
42 """Like update, but merges sub-dicts instead of clobbering at the top level.
43
43
44 Updates d1 in-place
44 Updates d1 in-place
45 """
45 """
46
46
47 if not isinstance(d2, dict) or not isinstance(d1, dict):
47 if not isinstance(d2, dict) or not isinstance(d1, dict):
48 return d2
48 return d2
49 for key, value in d2.items():
49 for key, value in d2.items():
50 d1[key] = _merge(d1.get(key), value)
50 d1[key] = _merge(d1.get(key), value)
51 return d1
51 return d1
52
52
53 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
53 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
54 """internal implementation of all display_foo methods
54 """internal implementation of all display_foo methods
55
55
56 Parameters
56 Parameters
57 ----------
57 ----------
58 mimetype : str
58 mimetype : str
59 The mimetype to be published (e.g. 'image/png')
59 The mimetype to be published (e.g. 'image/png')
60 objs : tuple of objects
60 objs : tuple of objects
61 The Python objects to display, or if raw=True raw text data to
61 The Python objects to display, or if raw=True raw text data to
62 display.
62 display.
63 raw : bool
63 raw : bool
64 Are the data objects raw data or Python objects that need to be
64 Are the data objects raw data or Python objects that need to be
65 formatted before display? [default: False]
65 formatted before display? [default: False]
66 metadata : dict (optional)
66 metadata : dict (optional)
67 Metadata to be associated with the specific mimetype output.
67 Metadata to be associated with the specific mimetype output.
68 """
68 """
69 if metadata:
69 if metadata:
70 metadata = {mimetype: metadata}
70 metadata = {mimetype: metadata}
71 if raw:
71 if raw:
72 # turn list of pngdata into list of { 'image/png': pngdata }
72 # turn list of pngdata into list of { 'image/png': pngdata }
73 objs = [ {mimetype: obj} for obj in objs ]
73 objs = [ {mimetype: obj} for obj in objs ]
74 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
74 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
75
75
76 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
77 # Main functions
77 # Main functions
78 #-----------------------------------------------------------------------------
78 #-----------------------------------------------------------------------------
79
79
80 def display(*objs, **kwargs):
80 def display(*objs, **kwargs):
81 """Display a Python object in all frontends.
81 """Display a Python object in all frontends.
82
82
83 By default all representations will be computed and sent to the frontends.
83 By default all representations will be computed and sent to the frontends.
84 Frontends can decide which representation is used and how.
84 Frontends can decide which representation is used and how.
85
85
86 Parameters
86 Parameters
87 ----------
87 ----------
88 objs : tuple of objects
88 objs : tuple of objects
89 The Python objects to display.
89 The Python objects to display.
90 raw : bool, optional
90 raw : bool, optional
91 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
91 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
92 or Python objects that need to be formatted before display? [default: False]
92 or Python objects that need to be formatted before display? [default: False]
93 include : list or tuple, optional
93 include : list or tuple, optional
94 A list of format type strings (MIME types) to include in the
94 A list of format type strings (MIME types) to include in the
95 format data dict. If this is set *only* the format types included
95 format data dict. If this is set *only* the format types included
96 in this list will be computed.
96 in this list will be computed.
97 exclude : list or tuple, optional
97 exclude : list or tuple, optional
98 A list of format type strings (MIME types) to exclude in the format
98 A list of format type strings (MIME types) to exclude in the format
99 data dict. If this is set all format types will be computed,
99 data dict. If this is set all format types will be computed,
100 except for those included in this argument.
100 except for those included in this argument.
101 metadata : dict, optional
101 metadata : dict, optional
102 A dictionary of metadata to associate with the output.
102 A dictionary of metadata to associate with the output.
103 mime-type keys in this dictionary will be associated with the individual
103 mime-type keys in this dictionary will be associated with the individual
104 representation formats, if they exist.
104 representation formats, if they exist.
105 """
105 """
106 raw = kwargs.get('raw', False)
106 raw = kwargs.get('raw', False)
107 include = kwargs.get('include')
107 include = kwargs.get('include')
108 exclude = kwargs.get('exclude')
108 exclude = kwargs.get('exclude')
109 metadata = kwargs.get('metadata')
109 metadata = kwargs.get('metadata')
110
110
111 from IPython.core.interactiveshell import InteractiveShell
111 from IPython.core.interactiveshell import InteractiveShell
112
112
113 if not raw:
113 if not raw:
114 format = InteractiveShell.instance().display_formatter.format
114 format = InteractiveShell.instance().display_formatter.format
115
115
116 for obj in objs:
116 for obj in objs:
117
117
118 # If _ipython_display_ is defined, use that to display this object. If
118 # If _ipython_display_ is defined, use that to display this object.
119 # it returns NotImplemented, use the _repr_ logic (default).
119 display_method = getattr(obj, '_ipython_display_', None)
120 if not hasattr(obj, '_ipython_display_') or obj._ipython_display_(**kwargs) is NotImplemented:
120 if display_method is not None:
121 if raw:
121 try:
122 publish_display_data('display', obj, metadata)
122 display_method(**kwargs)
123 else:
123 except NotImplementedError:
124 format_dict, md_dict = format(obj, include=include, exclude=exclude)
124 pass
125 if metadata:
125 else:
126 # kwarg-specified metadata gets precedence
126 continue
127 _merge(md_dict, metadata)
127 if raw:
128 publish_display_data('display', format_dict, md_dict)
128 publish_display_data('display', obj, metadata)
129 else:
130 format_dict, md_dict = format(obj, include=include, exclude=exclude)
131 if metadata:
132 # kwarg-specified metadata gets precedence
133 _merge(md_dict, metadata)
134 publish_display_data('display', format_dict, md_dict)
129
135
130
136
131 def display_pretty(*objs, **kwargs):
137 def display_pretty(*objs, **kwargs):
132 """Display the pretty (default) representation of an object.
138 """Display the pretty (default) representation of an object.
133
139
134 Parameters
140 Parameters
135 ----------
141 ----------
136 objs : tuple of objects
142 objs : tuple of objects
137 The Python objects to display, or if raw=True raw text data to
143 The Python objects to display, or if raw=True raw text data to
138 display.
144 display.
139 raw : bool
145 raw : bool
140 Are the data objects raw data or Python objects that need to be
146 Are the data objects raw data or Python objects that need to be
141 formatted before display? [default: False]
147 formatted before display? [default: False]
142 metadata : dict (optional)
148 metadata : dict (optional)
143 Metadata to be associated with the specific mimetype output.
149 Metadata to be associated with the specific mimetype output.
144 """
150 """
145 _display_mimetype('text/plain', objs, **kwargs)
151 _display_mimetype('text/plain', objs, **kwargs)
146
152
147
153
148 def display_html(*objs, **kwargs):
154 def display_html(*objs, **kwargs):
149 """Display the HTML representation of an object.
155 """Display the HTML representation of an object.
150
156
151 Parameters
157 Parameters
152 ----------
158 ----------
153 objs : tuple of objects
159 objs : tuple of objects
154 The Python objects to display, or if raw=True raw HTML data to
160 The Python objects to display, or if raw=True raw HTML data to
155 display.
161 display.
156 raw : bool
162 raw : bool
157 Are the data objects raw data or Python objects that need to be
163 Are the data objects raw data or Python objects that need to be
158 formatted before display? [default: False]
164 formatted before display? [default: False]
159 metadata : dict (optional)
165 metadata : dict (optional)
160 Metadata to be associated with the specific mimetype output.
166 Metadata to be associated with the specific mimetype output.
161 """
167 """
162 _display_mimetype('text/html', objs, **kwargs)
168 _display_mimetype('text/html', objs, **kwargs)
163
169
164
170
165 def display_svg(*objs, **kwargs):
171 def display_svg(*objs, **kwargs):
166 """Display the SVG representation of an object.
172 """Display the SVG representation of an object.
167
173
168 Parameters
174 Parameters
169 ----------
175 ----------
170 objs : tuple of objects
176 objs : tuple of objects
171 The Python objects to display, or if raw=True raw svg data to
177 The Python objects to display, or if raw=True raw svg data to
172 display.
178 display.
173 raw : bool
179 raw : bool
174 Are the data objects raw data or Python objects that need to be
180 Are the data objects raw data or Python objects that need to be
175 formatted before display? [default: False]
181 formatted before display? [default: False]
176 metadata : dict (optional)
182 metadata : dict (optional)
177 Metadata to be associated with the specific mimetype output.
183 Metadata to be associated with the specific mimetype output.
178 """
184 """
179 _display_mimetype('image/svg+xml', objs, **kwargs)
185 _display_mimetype('image/svg+xml', objs, **kwargs)
180
186
181
187
182 def display_png(*objs, **kwargs):
188 def display_png(*objs, **kwargs):
183 """Display the PNG representation of an object.
189 """Display the PNG representation of an object.
184
190
185 Parameters
191 Parameters
186 ----------
192 ----------
187 objs : tuple of objects
193 objs : tuple of objects
188 The Python objects to display, or if raw=True raw png data to
194 The Python objects to display, or if raw=True raw png data to
189 display.
195 display.
190 raw : bool
196 raw : bool
191 Are the data objects raw data or Python objects that need to be
197 Are the data objects raw data or Python objects that need to be
192 formatted before display? [default: False]
198 formatted before display? [default: False]
193 metadata : dict (optional)
199 metadata : dict (optional)
194 Metadata to be associated with the specific mimetype output.
200 Metadata to be associated with the specific mimetype output.
195 """
201 """
196 _display_mimetype('image/png', objs, **kwargs)
202 _display_mimetype('image/png', objs, **kwargs)
197
203
198
204
199 def display_jpeg(*objs, **kwargs):
205 def display_jpeg(*objs, **kwargs):
200 """Display the JPEG representation of an object.
206 """Display the JPEG representation of an object.
201
207
202 Parameters
208 Parameters
203 ----------
209 ----------
204 objs : tuple of objects
210 objs : tuple of objects
205 The Python objects to display, or if raw=True raw JPEG data to
211 The Python objects to display, or if raw=True raw JPEG data to
206 display.
212 display.
207 raw : bool
213 raw : bool
208 Are the data objects raw data or Python objects that need to be
214 Are the data objects raw data or Python objects that need to be
209 formatted before display? [default: False]
215 formatted before display? [default: False]
210 metadata : dict (optional)
216 metadata : dict (optional)
211 Metadata to be associated with the specific mimetype output.
217 Metadata to be associated with the specific mimetype output.
212 """
218 """
213 _display_mimetype('image/jpeg', objs, **kwargs)
219 _display_mimetype('image/jpeg', objs, **kwargs)
214
220
215
221
216 def display_latex(*objs, **kwargs):
222 def display_latex(*objs, **kwargs):
217 """Display the LaTeX representation of an object.
223 """Display the LaTeX representation of an object.
218
224
219 Parameters
225 Parameters
220 ----------
226 ----------
221 objs : tuple of objects
227 objs : tuple of objects
222 The Python objects to display, or if raw=True raw latex data to
228 The Python objects to display, or if raw=True raw latex data to
223 display.
229 display.
224 raw : bool
230 raw : bool
225 Are the data objects raw data or Python objects that need to be
231 Are the data objects raw data or Python objects that need to be
226 formatted before display? [default: False]
232 formatted before display? [default: False]
227 metadata : dict (optional)
233 metadata : dict (optional)
228 Metadata to be associated with the specific mimetype output.
234 Metadata to be associated with the specific mimetype output.
229 """
235 """
230 _display_mimetype('text/latex', objs, **kwargs)
236 _display_mimetype('text/latex', objs, **kwargs)
231
237
232
238
233 def display_json(*objs, **kwargs):
239 def display_json(*objs, **kwargs):
234 """Display the JSON representation of an object.
240 """Display the JSON representation of an object.
235
241
236 Note that not many frontends support displaying JSON.
242 Note that not many frontends support displaying JSON.
237
243
238 Parameters
244 Parameters
239 ----------
245 ----------
240 objs : tuple of objects
246 objs : tuple of objects
241 The Python objects to display, or if raw=True raw json data to
247 The Python objects to display, or if raw=True raw json data to
242 display.
248 display.
243 raw : bool
249 raw : bool
244 Are the data objects raw data or Python objects that need to be
250 Are the data objects raw data or Python objects that need to be
245 formatted before display? [default: False]
251 formatted before display? [default: False]
246 metadata : dict (optional)
252 metadata : dict (optional)
247 Metadata to be associated with the specific mimetype output.
253 Metadata to be associated with the specific mimetype output.
248 """
254 """
249 _display_mimetype('application/json', objs, **kwargs)
255 _display_mimetype('application/json', objs, **kwargs)
250
256
251
257
252 def display_javascript(*objs, **kwargs):
258 def display_javascript(*objs, **kwargs):
253 """Display the Javascript representation of an object.
259 """Display the Javascript representation of an object.
254
260
255 Parameters
261 Parameters
256 ----------
262 ----------
257 objs : tuple of objects
263 objs : tuple of objects
258 The Python objects to display, or if raw=True raw javascript data to
264 The Python objects to display, or if raw=True raw javascript data to
259 display.
265 display.
260 raw : bool
266 raw : bool
261 Are the data objects raw data or Python objects that need to be
267 Are the data objects raw data or Python objects that need to be
262 formatted before display? [default: False]
268 formatted before display? [default: False]
263 metadata : dict (optional)
269 metadata : dict (optional)
264 Metadata to be associated with the specific mimetype output.
270 Metadata to be associated with the specific mimetype output.
265 """
271 """
266 _display_mimetype('application/javascript', objs, **kwargs)
272 _display_mimetype('application/javascript', objs, **kwargs)
267
273
268 #-----------------------------------------------------------------------------
274 #-----------------------------------------------------------------------------
269 # Smart classes
275 # Smart classes
270 #-----------------------------------------------------------------------------
276 #-----------------------------------------------------------------------------
271
277
272
278
273 class DisplayObject(object):
279 class DisplayObject(object):
274 """An object that wraps data to be displayed."""
280 """An object that wraps data to be displayed."""
275
281
276 _read_flags = 'r'
282 _read_flags = 'r'
277
283
278 def __init__(self, data=None, url=None, filename=None):
284 def __init__(self, data=None, url=None, filename=None):
279 """Create a display object given raw data.
285 """Create a display object given raw data.
280
286
281 When this object is returned by an expression or passed to the
287 When this object is returned by an expression or passed to the
282 display function, it will result in the data being displayed
288 display function, it will result in the data being displayed
283 in the frontend. The MIME type of the data should match the
289 in the frontend. The MIME type of the data should match the
284 subclasses used, so the Png subclass should be used for 'image/png'
290 subclasses used, so the Png subclass should be used for 'image/png'
285 data. If the data is a URL, the data will first be downloaded
291 data. If the data is a URL, the data will first be downloaded
286 and then displayed. If
292 and then displayed. If
287
293
288 Parameters
294 Parameters
289 ----------
295 ----------
290 data : unicode, str or bytes
296 data : unicode, str or bytes
291 The raw data or a URL or file to load the data from
297 The raw data or a URL or file to load the data from
292 url : unicode
298 url : unicode
293 A URL to download the data from.
299 A URL to download the data from.
294 filename : unicode
300 filename : unicode
295 Path to a local file to load the data from.
301 Path to a local file to load the data from.
296 """
302 """
297 if data is not None and isinstance(data, string_types):
303 if data is not None and isinstance(data, string_types):
298 if data.startswith('http') and url is None:
304 if data.startswith('http') and url is None:
299 url = data
305 url = data
300 filename = None
306 filename = None
301 data = None
307 data = None
302 elif _safe_exists(data) and filename is None:
308 elif _safe_exists(data) and filename is None:
303 url = None
309 url = None
304 filename = data
310 filename = data
305 data = None
311 data = None
306
312
307 self.data = data
313 self.data = data
308 self.url = url
314 self.url = url
309 self.filename = None if filename is None else unicode_type(filename)
315 self.filename = None if filename is None else unicode_type(filename)
310
316
311 self.reload()
317 self.reload()
312 self._check_data()
318 self._check_data()
313
319
314 def _check_data(self):
320 def _check_data(self):
315 """Override in subclasses if there's something to check."""
321 """Override in subclasses if there's something to check."""
316 pass
322 pass
317
323
318 def reload(self):
324 def reload(self):
319 """Reload the raw data from file or URL."""
325 """Reload the raw data from file or URL."""
320 if self.filename is not None:
326 if self.filename is not None:
321 with open(self.filename, self._read_flags) as f:
327 with open(self.filename, self._read_flags) as f:
322 self.data = f.read()
328 self.data = f.read()
323 elif self.url is not None:
329 elif self.url is not None:
324 try:
330 try:
325 try:
331 try:
326 from urllib.request import urlopen # Py3
332 from urllib.request import urlopen # Py3
327 except ImportError:
333 except ImportError:
328 from urllib2 import urlopen
334 from urllib2 import urlopen
329 response = urlopen(self.url)
335 response = urlopen(self.url)
330 self.data = response.read()
336 self.data = response.read()
331 # extract encoding from header, if there is one:
337 # extract encoding from header, if there is one:
332 encoding = None
338 encoding = None
333 for sub in response.headers['content-type'].split(';'):
339 for sub in response.headers['content-type'].split(';'):
334 sub = sub.strip()
340 sub = sub.strip()
335 if sub.startswith('charset'):
341 if sub.startswith('charset'):
336 encoding = sub.split('=')[-1].strip()
342 encoding = sub.split('=')[-1].strip()
337 break
343 break
338 # decode data, if an encoding was specified
344 # decode data, if an encoding was specified
339 if encoding:
345 if encoding:
340 self.data = self.data.decode(encoding, 'replace')
346 self.data = self.data.decode(encoding, 'replace')
341 except:
347 except:
342 self.data = None
348 self.data = None
343
349
344 class TextDisplayObject(DisplayObject):
350 class TextDisplayObject(DisplayObject):
345 """Validate that display data is text"""
351 """Validate that display data is text"""
346 def _check_data(self):
352 def _check_data(self):
347 if self.data is not None and not isinstance(self.data, string_types):
353 if self.data is not None and not isinstance(self.data, string_types):
348 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
354 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
349
355
350 class Pretty(TextDisplayObject):
356 class Pretty(TextDisplayObject):
351
357
352 def _repr_pretty_(self):
358 def _repr_pretty_(self):
353 return self.data
359 return self.data
354
360
355
361
356 class HTML(TextDisplayObject):
362 class HTML(TextDisplayObject):
357
363
358 def _repr_html_(self):
364 def _repr_html_(self):
359 return self.data
365 return self.data
360
366
361 def __html__(self):
367 def __html__(self):
362 """
368 """
363 This method exists to inform other HTML-using modules (e.g. Markupsafe,
369 This method exists to inform other HTML-using modules (e.g. Markupsafe,
364 htmltag, etc) that this object is HTML and does not need things like
370 htmltag, etc) that this object is HTML and does not need things like
365 special characters (<>&) escaped.
371 special characters (<>&) escaped.
366 """
372 """
367 return self._repr_html_()
373 return self._repr_html_()
368
374
369
375
370 class Math(TextDisplayObject):
376 class Math(TextDisplayObject):
371
377
372 def _repr_latex_(self):
378 def _repr_latex_(self):
373 s = self.data.strip('$')
379 s = self.data.strip('$')
374 return "$$%s$$" % s
380 return "$$%s$$" % s
375
381
376
382
377 class Latex(TextDisplayObject):
383 class Latex(TextDisplayObject):
378
384
379 def _repr_latex_(self):
385 def _repr_latex_(self):
380 return self.data
386 return self.data
381
387
382
388
383 class SVG(DisplayObject):
389 class SVG(DisplayObject):
384
390
385 # wrap data in a property, which extracts the <svg> tag, discarding
391 # wrap data in a property, which extracts the <svg> tag, discarding
386 # document headers
392 # document headers
387 _data = None
393 _data = None
388
394
389 @property
395 @property
390 def data(self):
396 def data(self):
391 return self._data
397 return self._data
392
398
393 @data.setter
399 @data.setter
394 def data(self, svg):
400 def data(self, svg):
395 if svg is None:
401 if svg is None:
396 self._data = None
402 self._data = None
397 return
403 return
398 # parse into dom object
404 # parse into dom object
399 from xml.dom import minidom
405 from xml.dom import minidom
400 svg = cast_bytes_py2(svg)
406 svg = cast_bytes_py2(svg)
401 x = minidom.parseString(svg)
407 x = minidom.parseString(svg)
402 # get svg tag (should be 1)
408 # get svg tag (should be 1)
403 found_svg = x.getElementsByTagName('svg')
409 found_svg = x.getElementsByTagName('svg')
404 if found_svg:
410 if found_svg:
405 svg = found_svg[0].toxml()
411 svg = found_svg[0].toxml()
406 else:
412 else:
407 # fallback on the input, trust the user
413 # fallback on the input, trust the user
408 # but this is probably an error.
414 # but this is probably an error.
409 pass
415 pass
410 svg = cast_unicode(svg)
416 svg = cast_unicode(svg)
411 self._data = svg
417 self._data = svg
412
418
413 def _repr_svg_(self):
419 def _repr_svg_(self):
414 return self.data
420 return self.data
415
421
416
422
417 class JSON(TextDisplayObject):
423 class JSON(TextDisplayObject):
418
424
419 def _repr_json_(self):
425 def _repr_json_(self):
420 return self.data
426 return self.data
421
427
422 css_t = """$("head").append($("<link/>").attr({
428 css_t = """$("head").append($("<link/>").attr({
423 rel: "stylesheet",
429 rel: "stylesheet",
424 type: "text/css",
430 type: "text/css",
425 href: "%s"
431 href: "%s"
426 }));
432 }));
427 """
433 """
428
434
429 lib_t1 = """$.getScript("%s", function () {
435 lib_t1 = """$.getScript("%s", function () {
430 """
436 """
431 lib_t2 = """});
437 lib_t2 = """});
432 """
438 """
433
439
434 class Javascript(TextDisplayObject):
440 class Javascript(TextDisplayObject):
435
441
436 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
442 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
437 """Create a Javascript display object given raw data.
443 """Create a Javascript display object given raw data.
438
444
439 When this object is returned by an expression or passed to the
445 When this object is returned by an expression or passed to the
440 display function, it will result in the data being displayed
446 display function, it will result in the data being displayed
441 in the frontend. If the data is a URL, the data will first be
447 in the frontend. If the data is a URL, the data will first be
442 downloaded and then displayed.
448 downloaded and then displayed.
443
449
444 In the Notebook, the containing element will be available as `element`,
450 In the Notebook, the containing element will be available as `element`,
445 and jQuery will be available. The output area starts hidden, so if
451 and jQuery will be available. The output area starts hidden, so if
446 the js appends content to `element` that should be visible, then
452 the js appends content to `element` that should be visible, then
447 it must call `container.show()` to unhide the area.
453 it must call `container.show()` to unhide the area.
448
454
449 Parameters
455 Parameters
450 ----------
456 ----------
451 data : unicode, str or bytes
457 data : unicode, str or bytes
452 The Javascript source code or a URL to download it from.
458 The Javascript source code or a URL to download it from.
453 url : unicode
459 url : unicode
454 A URL to download the data from.
460 A URL to download the data from.
455 filename : unicode
461 filename : unicode
456 Path to a local file to load the data from.
462 Path to a local file to load the data from.
457 lib : list or str
463 lib : list or str
458 A sequence of Javascript library URLs to load asynchronously before
464 A sequence of Javascript library URLs to load asynchronously before
459 running the source code. The full URLs of the libraries should
465 running the source code. The full URLs of the libraries should
460 be given. A single Javascript library URL can also be given as a
466 be given. A single Javascript library URL can also be given as a
461 string.
467 string.
462 css: : list or str
468 css: : list or str
463 A sequence of css files to load before running the source code.
469 A sequence of css files to load before running the source code.
464 The full URLs of the css files should be given. A single css URL
470 The full URLs of the css files should be given. A single css URL
465 can also be given as a string.
471 can also be given as a string.
466 """
472 """
467 if isinstance(lib, string_types):
473 if isinstance(lib, string_types):
468 lib = [lib]
474 lib = [lib]
469 elif lib is None:
475 elif lib is None:
470 lib = []
476 lib = []
471 if isinstance(css, string_types):
477 if isinstance(css, string_types):
472 css = [css]
478 css = [css]
473 elif css is None:
479 elif css is None:
474 css = []
480 css = []
475 if not isinstance(lib, (list,tuple)):
481 if not isinstance(lib, (list,tuple)):
476 raise TypeError('expected sequence, got: %r' % lib)
482 raise TypeError('expected sequence, got: %r' % lib)
477 if not isinstance(css, (list,tuple)):
483 if not isinstance(css, (list,tuple)):
478 raise TypeError('expected sequence, got: %r' % css)
484 raise TypeError('expected sequence, got: %r' % css)
479 self.lib = lib
485 self.lib = lib
480 self.css = css
486 self.css = css
481 super(Javascript, self).__init__(data=data, url=url, filename=filename)
487 super(Javascript, self).__init__(data=data, url=url, filename=filename)
482
488
483 def _repr_javascript_(self):
489 def _repr_javascript_(self):
484 r = ''
490 r = ''
485 for c in self.css:
491 for c in self.css:
486 r += css_t % c
492 r += css_t % c
487 for l in self.lib:
493 for l in self.lib:
488 r += lib_t1 % l
494 r += lib_t1 % l
489 r += self.data
495 r += self.data
490 r += lib_t2*len(self.lib)
496 r += lib_t2*len(self.lib)
491 return r
497 return r
492
498
493 # constants for identifying png/jpeg data
499 # constants for identifying png/jpeg data
494 _PNG = b'\x89PNG\r\n\x1a\n'
500 _PNG = b'\x89PNG\r\n\x1a\n'
495 _JPEG = b'\xff\xd8'
501 _JPEG = b'\xff\xd8'
496
502
497 def _pngxy(data):
503 def _pngxy(data):
498 """read the (width, height) from a PNG header"""
504 """read the (width, height) from a PNG header"""
499 ihdr = data.index(b'IHDR')
505 ihdr = data.index(b'IHDR')
500 # next 8 bytes are width/height
506 # next 8 bytes are width/height
501 w4h4 = data[ihdr+4:ihdr+12]
507 w4h4 = data[ihdr+4:ihdr+12]
502 return struct.unpack('>ii', w4h4)
508 return struct.unpack('>ii', w4h4)
503
509
504 def _jpegxy(data):
510 def _jpegxy(data):
505 """read the (width, height) from a JPEG header"""
511 """read the (width, height) from a JPEG header"""
506 # adapted from http://www.64lines.com/jpeg-width-height
512 # adapted from http://www.64lines.com/jpeg-width-height
507
513
508 idx = 4
514 idx = 4
509 while True:
515 while True:
510 block_size = struct.unpack('>H', data[idx:idx+2])[0]
516 block_size = struct.unpack('>H', data[idx:idx+2])[0]
511 idx = idx + block_size
517 idx = idx + block_size
512 if data[idx:idx+2] == b'\xFF\xC0':
518 if data[idx:idx+2] == b'\xFF\xC0':
513 # found Start of Frame
519 # found Start of Frame
514 iSOF = idx
520 iSOF = idx
515 break
521 break
516 else:
522 else:
517 # read another block
523 # read another block
518 idx += 2
524 idx += 2
519
525
520 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
526 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
521 return w, h
527 return w, h
522
528
523 class Image(DisplayObject):
529 class Image(DisplayObject):
524
530
525 _read_flags = 'rb'
531 _read_flags = 'rb'
526 _FMT_JPEG = u'jpeg'
532 _FMT_JPEG = u'jpeg'
527 _FMT_PNG = u'png'
533 _FMT_PNG = u'png'
528 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
534 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
529
535
530 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=None, width=None, height=None, retina=False):
536 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=None, width=None, height=None, retina=False):
531 """Create a PNG/JPEG image object given raw data.
537 """Create a PNG/JPEG image object given raw data.
532
538
533 When this object is returned by an input cell or passed to the
539 When this object is returned by an input cell or passed to the
534 display function, it will result in the image being displayed
540 display function, it will result in the image being displayed
535 in the frontend.
541 in the frontend.
536
542
537 Parameters
543 Parameters
538 ----------
544 ----------
539 data : unicode, str or bytes
545 data : unicode, str or bytes
540 The raw image data or a URL or filename to load the data from.
546 The raw image data or a URL or filename to load the data from.
541 This always results in embedded image data.
547 This always results in embedded image data.
542 url : unicode
548 url : unicode
543 A URL to download the data from. If you specify `url=`,
549 A URL to download the data from. If you specify `url=`,
544 the image data will not be embedded unless you also specify `embed=True`.
550 the image data will not be embedded unless you also specify `embed=True`.
545 filename : unicode
551 filename : unicode
546 Path to a local file to load the data from.
552 Path to a local file to load the data from.
547 Images from a file are always embedded.
553 Images from a file are always embedded.
548 format : unicode
554 format : unicode
549 The format of the image data (png/jpeg/jpg). If a filename or URL is given
555 The format of the image data (png/jpeg/jpg). If a filename or URL is given
550 for format will be inferred from the filename extension.
556 for format will be inferred from the filename extension.
551 embed : bool
557 embed : bool
552 Should the image data be embedded using a data URI (True) or be
558 Should the image data be embedded using a data URI (True) or be
553 loaded using an <img> tag. Set this to True if you want the image
559 loaded using an <img> tag. Set this to True if you want the image
554 to be viewable later with no internet connection in the notebook.
560 to be viewable later with no internet connection in the notebook.
555
561
556 Default is `True`, unless the keyword argument `url` is set, then
562 Default is `True`, unless the keyword argument `url` is set, then
557 default value is `False`.
563 default value is `False`.
558
564
559 Note that QtConsole is not able to display images if `embed` is set to `False`
565 Note that QtConsole is not able to display images if `embed` is set to `False`
560 width : int
566 width : int
561 Width to which to constrain the image in html
567 Width to which to constrain the image in html
562 height : int
568 height : int
563 Height to which to constrain the image in html
569 Height to which to constrain the image in html
564 retina : bool
570 retina : bool
565 Automatically set the width and height to half of the measured
571 Automatically set the width and height to half of the measured
566 width and height.
572 width and height.
567 This only works for embedded images because it reads the width/height
573 This only works for embedded images because it reads the width/height
568 from image data.
574 from image data.
569 For non-embedded images, you can just set the desired display width
575 For non-embedded images, you can just set the desired display width
570 and height directly.
576 and height directly.
571
577
572 Examples
578 Examples
573 --------
579 --------
574 # embedded image data, works in qtconsole and notebook
580 # embedded image data, works in qtconsole and notebook
575 # when passed positionally, the first arg can be any of raw image data,
581 # when passed positionally, the first arg can be any of raw image data,
576 # a URL, or a filename from which to load image data.
582 # a URL, or a filename from which to load image data.
577 # The result is always embedding image data for inline images.
583 # The result is always embedding image data for inline images.
578 Image('http://www.google.fr/images/srpr/logo3w.png')
584 Image('http://www.google.fr/images/srpr/logo3w.png')
579 Image('/path/to/image.jpg')
585 Image('/path/to/image.jpg')
580 Image(b'RAW_PNG_DATA...')
586 Image(b'RAW_PNG_DATA...')
581
587
582 # Specifying Image(url=...) does not embed the image data,
588 # Specifying Image(url=...) does not embed the image data,
583 # it only generates `<img>` tag with a link to the source.
589 # it only generates `<img>` tag with a link to the source.
584 # This will not work in the qtconsole or offline.
590 # This will not work in the qtconsole or offline.
585 Image(url='http://www.google.fr/images/srpr/logo3w.png')
591 Image(url='http://www.google.fr/images/srpr/logo3w.png')
586
592
587 """
593 """
588 if filename is not None:
594 if filename is not None:
589 ext = self._find_ext(filename)
595 ext = self._find_ext(filename)
590 elif url is not None:
596 elif url is not None:
591 ext = self._find_ext(url)
597 ext = self._find_ext(url)
592 elif data is None:
598 elif data is None:
593 raise ValueError("No image data found. Expecting filename, url, or data.")
599 raise ValueError("No image data found. Expecting filename, url, or data.")
594 elif isinstance(data, string_types) and (
600 elif isinstance(data, string_types) and (
595 data.startswith('http') or _safe_exists(data)
601 data.startswith('http') or _safe_exists(data)
596 ):
602 ):
597 ext = self._find_ext(data)
603 ext = self._find_ext(data)
598 else:
604 else:
599 ext = None
605 ext = None
600
606
601 if ext is not None:
607 if ext is not None:
602 format = ext.lower()
608 format = ext.lower()
603 if ext == u'jpg' or ext == u'jpeg':
609 if ext == u'jpg' or ext == u'jpeg':
604 format = self._FMT_JPEG
610 format = self._FMT_JPEG
605 if ext == u'png':
611 if ext == u'png':
606 format = self._FMT_PNG
612 format = self._FMT_PNG
607 elif isinstance(data, bytes) and format == 'png':
613 elif isinstance(data, bytes) and format == 'png':
608 # infer image type from image data header,
614 # infer image type from image data header,
609 # only if format might not have been specified.
615 # only if format might not have been specified.
610 if data[:2] == _JPEG:
616 if data[:2] == _JPEG:
611 format = 'jpeg'
617 format = 'jpeg'
612
618
613 self.format = unicode_type(format).lower()
619 self.format = unicode_type(format).lower()
614 self.embed = embed if embed is not None else (url is None)
620 self.embed = embed if embed is not None else (url is None)
615
621
616 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
622 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
617 raise ValueError("Cannot embed the '%s' image format" % (self.format))
623 raise ValueError("Cannot embed the '%s' image format" % (self.format))
618 self.width = width
624 self.width = width
619 self.height = height
625 self.height = height
620 self.retina = retina
626 self.retina = retina
621 super(Image, self).__init__(data=data, url=url, filename=filename)
627 super(Image, self).__init__(data=data, url=url, filename=filename)
622
628
623 if retina:
629 if retina:
624 self._retina_shape()
630 self._retina_shape()
625
631
626 def _retina_shape(self):
632 def _retina_shape(self):
627 """load pixel-doubled width and height from image data"""
633 """load pixel-doubled width and height from image data"""
628 if not self.embed:
634 if not self.embed:
629 return
635 return
630 if self.format == 'png':
636 if self.format == 'png':
631 w, h = _pngxy(self.data)
637 w, h = _pngxy(self.data)
632 elif self.format == 'jpeg':
638 elif self.format == 'jpeg':
633 w, h = _jpegxy(self.data)
639 w, h = _jpegxy(self.data)
634 else:
640 else:
635 # retina only supports png
641 # retina only supports png
636 return
642 return
637 self.width = w // 2
643 self.width = w // 2
638 self.height = h // 2
644 self.height = h // 2
639
645
640 def reload(self):
646 def reload(self):
641 """Reload the raw data from file or URL."""
647 """Reload the raw data from file or URL."""
642 if self.embed:
648 if self.embed:
643 super(Image,self).reload()
649 super(Image,self).reload()
644 if self.retina:
650 if self.retina:
645 self._retina_shape()
651 self._retina_shape()
646
652
647 def _repr_html_(self):
653 def _repr_html_(self):
648 if not self.embed:
654 if not self.embed:
649 width = height = ''
655 width = height = ''
650 if self.width:
656 if self.width:
651 width = ' width="%d"' % self.width
657 width = ' width="%d"' % self.width
652 if self.height:
658 if self.height:
653 height = ' height="%d"' % self.height
659 height = ' height="%d"' % self.height
654 return u'<img src="%s"%s%s/>' % (self.url, width, height)
660 return u'<img src="%s"%s%s/>' % (self.url, width, height)
655
661
656 def _data_and_metadata(self):
662 def _data_and_metadata(self):
657 """shortcut for returning metadata with shape information, if defined"""
663 """shortcut for returning metadata with shape information, if defined"""
658 md = {}
664 md = {}
659 if self.width:
665 if self.width:
660 md['width'] = self.width
666 md['width'] = self.width
661 if self.height:
667 if self.height:
662 md['height'] = self.height
668 md['height'] = self.height
663 if md:
669 if md:
664 return self.data, md
670 return self.data, md
665 else:
671 else:
666 return self.data
672 return self.data
667
673
668 def _repr_png_(self):
674 def _repr_png_(self):
669 if self.embed and self.format == u'png':
675 if self.embed and self.format == u'png':
670 return self._data_and_metadata()
676 return self._data_and_metadata()
671
677
672 def _repr_jpeg_(self):
678 def _repr_jpeg_(self):
673 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
679 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
674 return self._data_and_metadata()
680 return self._data_and_metadata()
675
681
676 def _find_ext(self, s):
682 def _find_ext(self, s):
677 return unicode_type(s.split('.')[-1].lower())
683 return unicode_type(s.split('.')[-1].lower())
678
684
679
685
680 def clear_output(wait=False):
686 def clear_output(wait=False):
681 """Clear the output of the current cell receiving output.
687 """Clear the output of the current cell receiving output.
682
688
683 Parameters
689 Parameters
684 ----------
690 ----------
685 wait : bool [default: false]
691 wait : bool [default: false]
686 Wait to clear the output until new output is available to replace it."""
692 Wait to clear the output until new output is available to replace it."""
687 from IPython.core.interactiveshell import InteractiveShell
693 from IPython.core.interactiveshell import InteractiveShell
688 if InteractiveShell.initialized():
694 if InteractiveShell.initialized():
689 InteractiveShell.instance().display_pub.clear_output(wait)
695 InteractiveShell.instance().display_pub.clear_output(wait)
690 else:
696 else:
691 from IPython.utils import io
697 from IPython.utils import io
692 print('\033[2K\r', file=io.stdout, end='')
698 print('\033[2K\r', file=io.stdout, end='')
693 io.stdout.flush()
699 io.stdout.flush()
694 print('\033[2K\r', file=io.stderr, end='')
700 print('\033[2K\r', file=io.stderr, end='')
695 io.stderr.flush()
701 io.stderr.flush()
@@ -1,282 +1,287 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Displayhook for IPython.
2 """Displayhook for IPython.
3
3
4 This defines a callable class that IPython uses for `sys.displayhook`.
4 This defines a callable class that IPython uses for `sys.displayhook`.
5
5
6 Authors:
6 Authors:
7
7
8 * Fernando Perez
8 * Fernando Perez
9 * Brian Granger
9 * Brian Granger
10 * Robert Kern
10 * Robert Kern
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Copyright (C) 2008-2011 The IPython Development Team
14 # Copyright (C) 2008-2011 The IPython Development Team
15 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
15 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 from __future__ import print_function
24 from __future__ import print_function
25
25
26 import sys
26 import sys
27
27
28
28
29 from IPython.config.configurable import Configurable
29 from IPython.config.configurable import Configurable
30 from IPython.utils import io
30 from IPython.utils import io
31 from IPython.utils.py3compat import builtin_mod
31 from IPython.utils.py3compat import builtin_mod
32 from IPython.utils.traitlets import Instance
32 from IPython.utils.traitlets import Instance
33 from IPython.utils.warn import warn
33 from IPython.utils.warn import warn
34
34
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36 # Main displayhook class
36 # Main displayhook class
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38
38
39 # TODO: Move the various attributes (cache_size, [others now moved]). Some
39 # TODO: Move the various attributes (cache_size, [others now moved]). Some
40 # of these are also attributes of InteractiveShell. They should be on ONE object
40 # of these are also attributes of InteractiveShell. They should be on ONE object
41 # only and the other objects should ask that one object for their values.
41 # only and the other objects should ask that one object for their values.
42
42
43 class DisplayHook(Configurable):
43 class DisplayHook(Configurable):
44 """The custom IPython displayhook to replace sys.displayhook.
44 """The custom IPython displayhook to replace sys.displayhook.
45
45
46 This class does many things, but the basic idea is that it is a callable
46 This class does many things, but the basic idea is that it is a callable
47 that gets called anytime user code returns a value.
47 that gets called anytime user code returns a value.
48 """
48 """
49
49
50 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
50 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
51
51
52 def __init__(self, shell=None, cache_size=1000, **kwargs):
52 def __init__(self, shell=None, cache_size=1000, **kwargs):
53 super(DisplayHook, self).__init__(shell=shell, **kwargs)
53 super(DisplayHook, self).__init__(shell=shell, **kwargs)
54
54
55 cache_size_min = 3
55 cache_size_min = 3
56 if cache_size <= 0:
56 if cache_size <= 0:
57 self.do_full_cache = 0
57 self.do_full_cache = 0
58 cache_size = 0
58 cache_size = 0
59 elif cache_size < cache_size_min:
59 elif cache_size < cache_size_min:
60 self.do_full_cache = 0
60 self.do_full_cache = 0
61 cache_size = 0
61 cache_size = 0
62 warn('caching was disabled (min value for cache size is %s).' %
62 warn('caching was disabled (min value for cache size is %s).' %
63 cache_size_min,level=3)
63 cache_size_min,level=3)
64 else:
64 else:
65 self.do_full_cache = 1
65 self.do_full_cache = 1
66
66
67 self.cache_size = cache_size
67 self.cache_size = cache_size
68
68
69 # we need a reference to the user-level namespace
69 # we need a reference to the user-level namespace
70 self.shell = shell
70 self.shell = shell
71
71
72 self._,self.__,self.___ = '','',''
72 self._,self.__,self.___ = '','',''
73
73
74 # these are deliberately global:
74 # these are deliberately global:
75 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
75 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
76 self.shell.user_ns.update(to_user_ns)
76 self.shell.user_ns.update(to_user_ns)
77
77
78 @property
78 @property
79 def prompt_count(self):
79 def prompt_count(self):
80 return self.shell.execution_count
80 return self.shell.execution_count
81
81
82 #-------------------------------------------------------------------------
82 #-------------------------------------------------------------------------
83 # Methods used in __call__. Override these methods to modify the behavior
83 # Methods used in __call__. Override these methods to modify the behavior
84 # of the displayhook.
84 # of the displayhook.
85 #-------------------------------------------------------------------------
85 #-------------------------------------------------------------------------
86
86
87 def check_for_underscore(self):
87 def check_for_underscore(self):
88 """Check if the user has set the '_' variable by hand."""
88 """Check if the user has set the '_' variable by hand."""
89 # If something injected a '_' variable in __builtin__, delete
89 # If something injected a '_' variable in __builtin__, delete
90 # ipython's automatic one so we don't clobber that. gettext() in
90 # ipython's automatic one so we don't clobber that. gettext() in
91 # particular uses _, so we need to stay away from it.
91 # particular uses _, so we need to stay away from it.
92 if '_' in builtin_mod.__dict__:
92 if '_' in builtin_mod.__dict__:
93 try:
93 try:
94 del self.shell.user_ns['_']
94 del self.shell.user_ns['_']
95 except KeyError:
95 except KeyError:
96 pass
96 pass
97
97
98 def quiet(self):
98 def quiet(self):
99 """Should we silence the display hook because of ';'?"""
99 """Should we silence the display hook because of ';'?"""
100 # do not print output if input ends in ';'
100 # do not print output if input ends in ';'
101 try:
101 try:
102 cell = self.shell.history_manager.input_hist_parsed[self.prompt_count]
102 cell = self.shell.history_manager.input_hist_parsed[self.prompt_count]
103 if cell.rstrip().endswith(';'):
103 if cell.rstrip().endswith(';'):
104 return True
104 return True
105 except IndexError:
105 except IndexError:
106 # some uses of ipshellembed may fail here
106 # some uses of ipshellembed may fail here
107 pass
107 pass
108 return False
108 return False
109
109
110 def start_displayhook(self):
110 def start_displayhook(self):
111 """Start the displayhook, initializing resources."""
111 """Start the displayhook, initializing resources."""
112 pass
112 pass
113
113
114 def write_output_prompt(self):
114 def write_output_prompt(self):
115 """Write the output prompt.
115 """Write the output prompt.
116
116
117 The default implementation simply writes the prompt to
117 The default implementation simply writes the prompt to
118 ``io.stdout``.
118 ``io.stdout``.
119 """
119 """
120 # Use write, not print which adds an extra space.
120 # Use write, not print which adds an extra space.
121 io.stdout.write(self.shell.separate_out)
121 io.stdout.write(self.shell.separate_out)
122 outprompt = self.shell.prompt_manager.render('out')
122 outprompt = self.shell.prompt_manager.render('out')
123 if self.do_full_cache:
123 if self.do_full_cache:
124 io.stdout.write(outprompt)
124 io.stdout.write(outprompt)
125
125
126 def compute_format_data(self, result):
126 def compute_format_data(self, result):
127 """Compute format data of the object to be displayed.
127 """Compute format data of the object to be displayed.
128
128
129 The format data is a generalization of the :func:`repr` of an object.
129 The format data is a generalization of the :func:`repr` of an object.
130 In the default implementation the format data is a :class:`dict` of
130 In the default implementation the format data is a :class:`dict` of
131 key value pair where the keys are valid MIME types and the values
131 key value pair where the keys are valid MIME types and the values
132 are JSON'able data structure containing the raw data for that MIME
132 are JSON'able data structure containing the raw data for that MIME
133 type. It is up to frontends to determine pick a MIME to to use and
133 type. It is up to frontends to determine pick a MIME to to use and
134 display that data in an appropriate manner.
134 display that data in an appropriate manner.
135
135
136 This method only computes the format data for the object and should
136 This method only computes the format data for the object and should
137 NOT actually print or write that to a stream.
137 NOT actually print or write that to a stream.
138
138
139 Parameters
139 Parameters
140 ----------
140 ----------
141 result : object
141 result : object
142 The Python object passed to the display hook, whose format will be
142 The Python object passed to the display hook, whose format will be
143 computed.
143 computed.
144
144
145 Returns
145 Returns
146 -------
146 -------
147 (format_dict, md_dict) : dict
147 (format_dict, md_dict) : dict
148 format_dict is a :class:`dict` whose keys are valid MIME types and values are
148 format_dict is a :class:`dict` whose keys are valid MIME types and values are
149 JSON'able raw data for that MIME type. It is recommended that
149 JSON'able raw data for that MIME type. It is recommended that
150 all return values of this should always include the "text/plain"
150 all return values of this should always include the "text/plain"
151 MIME type representation of the object.
151 MIME type representation of the object.
152 md_dict is a :class:`dict` with the same MIME type keys
152 md_dict is a :class:`dict` with the same MIME type keys
153 of metadata associated with each output.
153 of metadata associated with each output.
154
154
155 """
155 """
156 return self.shell.display_formatter.format(result)
156 return self.shell.display_formatter.format(result)
157
157
158 def write_format_data(self, format_dict, md_dict=None):
158 def write_format_data(self, format_dict, md_dict=None):
159 """Write the format data dict to the frontend.
159 """Write the format data dict to the frontend.
160
160
161 This default version of this method simply writes the plain text
161 This default version of this method simply writes the plain text
162 representation of the object to ``io.stdout``. Subclasses should
162 representation of the object to ``io.stdout``. Subclasses should
163 override this method to send the entire `format_dict` to the
163 override this method to send the entire `format_dict` to the
164 frontends.
164 frontends.
165
165
166 Parameters
166 Parameters
167 ----------
167 ----------
168 format_dict : dict
168 format_dict : dict
169 The format dict for the object passed to `sys.displayhook`.
169 The format dict for the object passed to `sys.displayhook`.
170 md_dict : dict (optional)
170 md_dict : dict (optional)
171 The metadata dict to be associated with the display data.
171 The metadata dict to be associated with the display data.
172 """
172 """
173 # We want to print because we want to always make sure we have a
173 # We want to print because we want to always make sure we have a
174 # newline, even if all the prompt separators are ''. This is the
174 # newline, even if all the prompt separators are ''. This is the
175 # standard IPython behavior.
175 # standard IPython behavior.
176 result_repr = format_dict['text/plain']
176 result_repr = format_dict['text/plain']
177 if '\n' in result_repr:
177 if '\n' in result_repr:
178 # So that multi-line strings line up with the left column of
178 # So that multi-line strings line up with the left column of
179 # the screen, instead of having the output prompt mess up
179 # the screen, instead of having the output prompt mess up
180 # their first line.
180 # their first line.
181 # We use the prompt template instead of the expanded prompt
181 # We use the prompt template instead of the expanded prompt
182 # because the expansion may add ANSI escapes that will interfere
182 # because the expansion may add ANSI escapes that will interfere
183 # with our ability to determine whether or not we should add
183 # with our ability to determine whether or not we should add
184 # a newline.
184 # a newline.
185 prompt_template = self.shell.prompt_manager.out_template
185 prompt_template = self.shell.prompt_manager.out_template
186 if prompt_template and not prompt_template.endswith('\n'):
186 if prompt_template and not prompt_template.endswith('\n'):
187 # But avoid extraneous empty lines.
187 # But avoid extraneous empty lines.
188 result_repr = '\n' + result_repr
188 result_repr = '\n' + result_repr
189
189
190 print(result_repr, file=io.stdout)
190 print(result_repr, file=io.stdout)
191
191
192 def update_user_ns(self, result):
192 def update_user_ns(self, result):
193 """Update user_ns with various things like _, __, _1, etc."""
193 """Update user_ns with various things like _, __, _1, etc."""
194
194
195 # Avoid recursive reference when displaying _oh/Out
195 # Avoid recursive reference when displaying _oh/Out
196 if result is not self.shell.user_ns['_oh']:
196 if result is not self.shell.user_ns['_oh']:
197 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
197 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
198 warn('Output cache limit (currently '+
198 warn('Output cache limit (currently '+
199 repr(self.cache_size)+' entries) hit.\n'
199 repr(self.cache_size)+' entries) hit.\n'
200 'Flushing cache and resetting history counter...\n'
200 'Flushing cache and resetting history counter...\n'
201 'The only history variables available will be _,__,___ and _1\n'
201 'The only history variables available will be _,__,___ and _1\n'
202 'with the current result.')
202 'with the current result.')
203
203
204 self.flush()
204 self.flush()
205 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
205 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
206 # we cause buggy behavior for things like gettext).
206 # we cause buggy behavior for things like gettext).
207
207
208 if '_' not in builtin_mod.__dict__:
208 if '_' not in builtin_mod.__dict__:
209 self.___ = self.__
209 self.___ = self.__
210 self.__ = self._
210 self.__ = self._
211 self._ = result
211 self._ = result
212 self.shell.push({'_':self._,
212 self.shell.push({'_':self._,
213 '__':self.__,
213 '__':self.__,
214 '___':self.___}, interactive=False)
214 '___':self.___}, interactive=False)
215
215
216 # hackish access to top-level namespace to create _1,_2... dynamically
216 # hackish access to top-level namespace to create _1,_2... dynamically
217 to_main = {}
217 to_main = {}
218 if self.do_full_cache:
218 if self.do_full_cache:
219 new_result = '_'+repr(self.prompt_count)
219 new_result = '_'+repr(self.prompt_count)
220 to_main[new_result] = result
220 to_main[new_result] = result
221 self.shell.push(to_main, interactive=False)
221 self.shell.push(to_main, interactive=False)
222 self.shell.user_ns['_oh'][self.prompt_count] = result
222 self.shell.user_ns['_oh'][self.prompt_count] = result
223
223
224 def log_output(self, format_dict):
224 def log_output(self, format_dict):
225 """Log the output."""
225 """Log the output."""
226 if self.shell.logger.log_output:
226 if self.shell.logger.log_output:
227 self.shell.logger.log_write(format_dict['text/plain'], 'output')
227 self.shell.logger.log_write(format_dict['text/plain'], 'output')
228 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
228 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
229 format_dict['text/plain']
229 format_dict['text/plain']
230
230
231 def finish_displayhook(self):
231 def finish_displayhook(self):
232 """Finish up all displayhook activities."""
232 """Finish up all displayhook activities."""
233 io.stdout.write(self.shell.separate_out2)
233 io.stdout.write(self.shell.separate_out2)
234 io.stdout.flush()
234 io.stdout.flush()
235
235
236 def __call__(self, result=None):
236 def __call__(self, result=None):
237 """Printing with history cache management.
237 """Printing with history cache management.
238
238
239 This is invoked everytime the interpreter needs to print, and is
239 This is invoked everytime the interpreter needs to print, and is
240 activated by setting the variable sys.displayhook to it.
240 activated by setting the variable sys.displayhook to it.
241 """
241 """
242 self.check_for_underscore()
242 self.check_for_underscore()
243 if result is not None and not self.quiet():
243 if result is not None and not self.quiet():
244 # If _ipython_display_ is defined, use that to display this object. If
244 # If _ipython_display_ is defined, use that to display this object.
245 # it returns NotImplemented, use the _repr_ logic (default).
245 display_method = getattr(result, '_ipython_display_', None)
246 if not hasattr(result, '_ipython_display_') or result._ipython_display_() is NotImplemented:
246 if display_method is not None:
247 self.start_displayhook()
247 try:
248 self.write_output_prompt()
248 return display_method()
249 format_dict, md_dict = self.compute_format_data(result)
249 except NotImplementedError:
250 self.write_format_data(format_dict, md_dict)
250 pass
251 self.update_user_ns(result)
251
252 self.log_output(format_dict)
252 self.start_displayhook()
253 self.finish_displayhook()
253 self.write_output_prompt()
254 format_dict, md_dict = self.compute_format_data(result)
255 self.write_format_data(format_dict, md_dict)
256 self.update_user_ns(result)
257 self.log_output(format_dict)
258 self.finish_displayhook()
254
259
255 def flush(self):
260 def flush(self):
256 if not self.do_full_cache:
261 if not self.do_full_cache:
257 raise ValueError("You shouldn't have reached the cache flush "
262 raise ValueError("You shouldn't have reached the cache flush "
258 "if full caching is not enabled!")
263 "if full caching is not enabled!")
259 # delete auto-generated vars from global namespace
264 # delete auto-generated vars from global namespace
260
265
261 for n in range(1,self.prompt_count + 1):
266 for n in range(1,self.prompt_count + 1):
262 key = '_'+repr(n)
267 key = '_'+repr(n)
263 try:
268 try:
264 del self.shell.user_ns[key]
269 del self.shell.user_ns[key]
265 except: pass
270 except: pass
266 # In some embedded circumstances, the user_ns doesn't have the
271 # In some embedded circumstances, the user_ns doesn't have the
267 # '_oh' key set up.
272 # '_oh' key set up.
268 oh = self.shell.user_ns.get('_oh', None)
273 oh = self.shell.user_ns.get('_oh', None)
269 if oh is not None:
274 if oh is not None:
270 oh.clear()
275 oh.clear()
271
276
272 # Release our own references to objects:
277 # Release our own references to objects:
273 self._, self.__, self.___ = '', '', ''
278 self._, self.__, self.___ = '', '', ''
274
279
275 if '_' not in builtin_mod.__dict__:
280 if '_' not in builtin_mod.__dict__:
276 self.shell.user_ns.update({'_':None,'__':None, '___':None})
281 self.shell.user_ns.update({'_':None,'__':None, '___':None})
277 import gc
282 import gc
278 # TODO: Is this really needed?
283 # TODO: Is this really needed?
279 # IronPython blocks here forever
284 # IronPython blocks here forever
280 if sys.platform != "cli":
285 if sys.platform != "cli":
281 gc.collect()
286 gc.collect()
282
287
General Comments 0
You need to be logged in to leave comments. Login now