##// END OF EJS Templates
respect encoding of display data from urls
MinRK -
Show More
@@ -1,373 +1,383 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) 2008-2010 The IPython Development Team
10 # Copyright (C) 2008-2010 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 .displaypub import (
20 from .displaypub import (
21 publish_pretty, publish_html,
21 publish_pretty, publish_html,
22 publish_latex, publish_svg,
22 publish_latex, publish_svg,
23 publish_png, publish_json,
23 publish_png, publish_json,
24 publish_javascript, publish_jpeg
24 publish_javascript, publish_jpeg
25 )
25 )
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Main functions
28 # Main functions
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31 def display(*objs, **kwargs):
31 def display(*objs, **kwargs):
32 """Display a Python object in all frontends.
32 """Display a Python object in all frontends.
33
33
34 By default all representations will be computed and sent to the frontends.
34 By default all representations will be computed and sent to the frontends.
35 Frontends can decide which representation is used and how.
35 Frontends can decide which representation is used and how.
36
36
37 Parameters
37 Parameters
38 ----------
38 ----------
39 objs : tuple of objects
39 objs : tuple of objects
40 The Python objects to display.
40 The Python objects to display.
41 include : list or tuple, optional
41 include : list or tuple, optional
42 A list of format type strings (MIME types) to include in the
42 A list of format type strings (MIME types) to include in the
43 format data dict. If this is set *only* the format types included
43 format data dict. If this is set *only* the format types included
44 in this list will be computed.
44 in this list will be computed.
45 exclude : list or tuple, optional
45 exclude : list or tuple, optional
46 A list of format type string (MIME types) to exclue in the format
46 A list of format type string (MIME types) to exclue in the format
47 data dict. If this is set all format types will be computed,
47 data dict. If this is set all format types will be computed,
48 except for those included in this argument.
48 except for those included in this argument.
49 """
49 """
50 include = kwargs.get('include')
50 include = kwargs.get('include')
51 exclude = kwargs.get('exclude')
51 exclude = kwargs.get('exclude')
52
52
53 from IPython.core.interactiveshell import InteractiveShell
53 from IPython.core.interactiveshell import InteractiveShell
54 inst = InteractiveShell.instance()
54 inst = InteractiveShell.instance()
55 format = inst.display_formatter.format
55 format = inst.display_formatter.format
56 publish = inst.display_pub.publish
56 publish = inst.display_pub.publish
57
57
58 for obj in objs:
58 for obj in objs:
59 format_dict = format(obj, include=include, exclude=exclude)
59 format_dict = format(obj, include=include, exclude=exclude)
60 publish('IPython.core.display.display', format_dict)
60 publish('IPython.core.display.display', format_dict)
61
61
62
62
63 def display_pretty(*objs, **kwargs):
63 def display_pretty(*objs, **kwargs):
64 """Display the pretty (default) representation of an object.
64 """Display the pretty (default) representation of an object.
65
65
66 Parameters
66 Parameters
67 ----------
67 ----------
68 objs : tuple of objects
68 objs : tuple of objects
69 The Python objects to display, or if raw=True raw text data to
69 The Python objects to display, or if raw=True raw text data to
70 display.
70 display.
71 raw : bool
71 raw : bool
72 Are the data objects raw data or Python objects that need to be
72 Are the data objects raw data or Python objects that need to be
73 formatted before display? [default: False]
73 formatted before display? [default: False]
74 """
74 """
75 raw = kwargs.pop('raw',False)
75 raw = kwargs.pop('raw',False)
76 if raw:
76 if raw:
77 for obj in objs:
77 for obj in objs:
78 publish_pretty(obj)
78 publish_pretty(obj)
79 else:
79 else:
80 display(*objs, include=['text/plain'])
80 display(*objs, include=['text/plain'])
81
81
82
82
83 def display_html(*objs, **kwargs):
83 def display_html(*objs, **kwargs):
84 """Display the HTML representation of an object.
84 """Display the HTML representation of an object.
85
85
86 Parameters
86 Parameters
87 ----------
87 ----------
88 objs : tuple of objects
88 objs : tuple of objects
89 The Python objects to display, or if raw=True raw HTML data to
89 The Python objects to display, or if raw=True raw HTML data to
90 display.
90 display.
91 raw : bool
91 raw : bool
92 Are the data objects raw data or Python objects that need to be
92 Are the data objects raw data or Python objects that need to be
93 formatted before display? [default: False]
93 formatted before display? [default: False]
94 """
94 """
95 raw = kwargs.pop('raw',False)
95 raw = kwargs.pop('raw',False)
96 if raw:
96 if raw:
97 for obj in objs:
97 for obj in objs:
98 publish_html(obj)
98 publish_html(obj)
99 else:
99 else:
100 display(*objs, include=['text/plain','text/html'])
100 display(*objs, include=['text/plain','text/html'])
101
101
102
102
103 def display_svg(*objs, **kwargs):
103 def display_svg(*objs, **kwargs):
104 """Display the SVG representation of an object.
104 """Display the SVG representation of an object.
105
105
106 Parameters
106 Parameters
107 ----------
107 ----------
108 objs : tuple of objects
108 objs : tuple of objects
109 The Python objects to display, or if raw=True raw svg data to
109 The Python objects to display, or if raw=True raw svg data to
110 display.
110 display.
111 raw : bool
111 raw : bool
112 Are the data objects raw data or Python objects that need to be
112 Are the data objects raw data or Python objects that need to be
113 formatted before display? [default: False]
113 formatted before display? [default: False]
114 """
114 """
115 raw = kwargs.pop('raw',False)
115 raw = kwargs.pop('raw',False)
116 if raw:
116 if raw:
117 for obj in objs:
117 for obj in objs:
118 publish_svg(obj)
118 publish_svg(obj)
119 else:
119 else:
120 display(*objs, include=['text/plain','image/svg+xml'])
120 display(*objs, include=['text/plain','image/svg+xml'])
121
121
122
122
123 def display_png(*objs, **kwargs):
123 def display_png(*objs, **kwargs):
124 """Display the PNG representation of an object.
124 """Display the PNG representation of an object.
125
125
126 Parameters
126 Parameters
127 ----------
127 ----------
128 objs : tuple of objects
128 objs : tuple of objects
129 The Python objects to display, or if raw=True raw png data to
129 The Python objects to display, or if raw=True raw png data to
130 display.
130 display.
131 raw : bool
131 raw : bool
132 Are the data objects raw data or Python objects that need to be
132 Are the data objects raw data or Python objects that need to be
133 formatted before display? [default: False]
133 formatted before display? [default: False]
134 """
134 """
135 raw = kwargs.pop('raw',False)
135 raw = kwargs.pop('raw',False)
136 if raw:
136 if raw:
137 for obj in objs:
137 for obj in objs:
138 publish_png(obj)
138 publish_png(obj)
139 else:
139 else:
140 display(*objs, include=['text/plain','image/png'])
140 display(*objs, include=['text/plain','image/png'])
141
141
142
142
143 def display_jpeg(*objs, **kwargs):
143 def display_jpeg(*objs, **kwargs):
144 """Display the JPEG representation of an object.
144 """Display the JPEG representation of an object.
145
145
146 Parameters
146 Parameters
147 ----------
147 ----------
148 objs : tuple of objects
148 objs : tuple of objects
149 The Python objects to display, or if raw=True raw JPEG data to
149 The Python objects to display, or if raw=True raw JPEG data to
150 display.
150 display.
151 raw : bool
151 raw : bool
152 Are the data objects raw data or Python objects that need to be
152 Are the data objects raw data or Python objects that need to be
153 formatted before display? [default: False]
153 formatted before display? [default: False]
154 """
154 """
155 raw = kwargs.pop('raw',False)
155 raw = kwargs.pop('raw',False)
156 if raw:
156 if raw:
157 for obj in objs:
157 for obj in objs:
158 publish_jpeg(obj)
158 publish_jpeg(obj)
159 else:
159 else:
160 display(*objs, include=['text/plain','image/jpeg'])
160 display(*objs, include=['text/plain','image/jpeg'])
161
161
162
162
163 def display_latex(*objs, **kwargs):
163 def display_latex(*objs, **kwargs):
164 """Display the LaTeX representation of an object.
164 """Display the LaTeX representation of an object.
165
165
166 Parameters
166 Parameters
167 ----------
167 ----------
168 objs : tuple of objects
168 objs : tuple of objects
169 The Python objects to display, or if raw=True raw latex data to
169 The Python objects to display, or if raw=True raw latex data to
170 display.
170 display.
171 raw : bool
171 raw : bool
172 Are the data objects raw data or Python objects that need to be
172 Are the data objects raw data or Python objects that need to be
173 formatted before display? [default: False]
173 formatted before display? [default: False]
174 """
174 """
175 raw = kwargs.pop('raw',False)
175 raw = kwargs.pop('raw',False)
176 if raw:
176 if raw:
177 for obj in objs:
177 for obj in objs:
178 publish_latex(obj)
178 publish_latex(obj)
179 else:
179 else:
180 display(*objs, include=['text/plain','text/latex'])
180 display(*objs, include=['text/plain','text/latex'])
181
181
182
182
183 def display_json(*objs, **kwargs):
183 def display_json(*objs, **kwargs):
184 """Display the JSON representation of an object.
184 """Display the JSON representation of an object.
185
185
186 Parameters
186 Parameters
187 ----------
187 ----------
188 objs : tuple of objects
188 objs : tuple of objects
189 The Python objects to display, or if raw=True raw json data to
189 The Python objects to display, or if raw=True raw json data to
190 display.
190 display.
191 raw : bool
191 raw : bool
192 Are the data objects raw data or Python objects that need to be
192 Are the data objects raw data or Python objects that need to be
193 formatted before display? [default: False]
193 formatted before display? [default: False]
194 """
194 """
195 raw = kwargs.pop('raw',False)
195 raw = kwargs.pop('raw',False)
196 if raw:
196 if raw:
197 for obj in objs:
197 for obj in objs:
198 publish_json(obj)
198 publish_json(obj)
199 else:
199 else:
200 display(*objs, include=['text/plain','application/json'])
200 display(*objs, include=['text/plain','application/json'])
201
201
202
202
203 def display_javascript(*objs, **kwargs):
203 def display_javascript(*objs, **kwargs):
204 """Display the Javascript representation of an object.
204 """Display the Javascript representation of an object.
205
205
206 Parameters
206 Parameters
207 ----------
207 ----------
208 objs : tuple of objects
208 objs : tuple of objects
209 The Python objects to display, or if raw=True raw javascript data to
209 The Python objects to display, or if raw=True raw javascript data to
210 display.
210 display.
211 raw : bool
211 raw : bool
212 Are the data objects raw data or Python objects that need to be
212 Are the data objects raw data or Python objects that need to be
213 formatted before display? [default: False]
213 formatted before display? [default: False]
214 """
214 """
215 raw = kwargs.pop('raw',False)
215 raw = kwargs.pop('raw',False)
216 if raw:
216 if raw:
217 for obj in objs:
217 for obj in objs:
218 publish_javascript(obj)
218 publish_javascript(obj)
219 else:
219 else:
220 display(*objs, include=['text/plain','application/javascript'])
220 display(*objs, include=['text/plain','application/javascript'])
221
221
222 #-----------------------------------------------------------------------------
222 #-----------------------------------------------------------------------------
223 # Smart classes
223 # Smart classes
224 #-----------------------------------------------------------------------------
224 #-----------------------------------------------------------------------------
225
225
226
226
227 class DisplayObject(object):
227 class DisplayObject(object):
228 """An object that wraps data to be displayed."""
228 """An object that wraps data to be displayed."""
229
229
230 _read_flags = 'r'
230 _read_flags = 'r'
231
231
232 def __init__(self, data=None, url=None, filename=None):
232 def __init__(self, data=None, url=None, filename=None):
233 """Create a display object given raw data.
233 """Create a display object given raw data.
234
234
235 When this object is returned by an expression or passed to the
235 When this object is returned by an expression or passed to the
236 display function, it will result in the data being displayed
236 display function, it will result in the data being displayed
237 in the frontend. The MIME type of the data should match the
237 in the frontend. The MIME type of the data should match the
238 subclasses used, so the Png subclass should be used for 'image/png'
238 subclasses used, so the Png subclass should be used for 'image/png'
239 data. If the data is a URL, the data will first be downloaded
239 data. If the data is a URL, the data will first be downloaded
240 and then displayed. If
240 and then displayed. If
241
241
242 Parameters
242 Parameters
243 ----------
243 ----------
244 data : unicode, str or bytes
244 data : unicode, str or bytes
245 The raw data or a URL to download the data from.
245 The raw data or a URL to download the data from.
246 url : unicode
246 url : unicode
247 A URL to download the data from.
247 A URL to download the data from.
248 filename : unicode
248 filename : unicode
249 Path to a local file to load the data from.
249 Path to a local file to load the data from.
250 """
250 """
251 if data is not None and data.startswith('http'):
251 if data is not None and data.startswith('http'):
252 self.url = data
252 self.url = data
253 self.filename = None
253 self.filename = None
254 self.data = None
254 self.data = None
255 else:
255 else:
256 self.data = data
256 self.data = data
257 self.url = url
257 self.url = url
258 self.filename = None if filename is None else unicode(filename)
258 self.filename = None if filename is None else unicode(filename)
259 self.reload()
259 self.reload()
260
260
261 def reload(self):
261 def reload(self):
262 """Reload the raw data from file or URL."""
262 """Reload the raw data from file or URL."""
263 if self.filename is not None:
263 if self.filename is not None:
264 with open(self.filename, self._read_flags) as f:
264 with open(self.filename, self._read_flags) as f:
265 self.data = f.read()
265 self.data = f.read()
266 elif self.url is not None:
266 elif self.url is not None:
267 try:
267 try:
268 import urllib2
268 import urllib2
269 response = urllib2.urlopen(self.url)
269 response = urllib2.urlopen(self.url)
270 self.data = response.read()
270 self.data = response.read()
271 # extract encoding from header, if there is one:
272 encoding = None
273 for sub in response.headers['content-type'].split(';'):
274 sub = sub.strip()
275 if sub.startswith('charset'):
276 encoding = sub.split('=')[-1].strip()
277 break
278 # decode data, if an encoding was specified
279 if encoding:
280 self.data = self.data.decode(encoding, 'replace')
271 except:
281 except:
272 self.data = None
282 self.data = None
273
283
274 class Pretty(DisplayObject):
284 class Pretty(DisplayObject):
275
285
276 def _repr_pretty_(self):
286 def _repr_pretty_(self):
277 return self.data
287 return self.data
278
288
279
289
280 class HTML(DisplayObject):
290 class HTML(DisplayObject):
281
291
282 def _repr_html_(self):
292 def _repr_html_(self):
283 return self.data
293 return self.data
284
294
285
295
286 class Math(DisplayObject):
296 class Math(DisplayObject):
287
297
288 def _repr_latex_(self):
298 def _repr_latex_(self):
289 return self.data
299 return self.data
290
300
291
301
292 class SVG(DisplayObject):
302 class SVG(DisplayObject):
293
303
294 def _repr_svg_(self):
304 def _repr_svg_(self):
295 return self.data
305 return self.data
296
306
297
307
298 class JSON(DisplayObject):
308 class JSON(DisplayObject):
299
309
300 def _repr_json_(self):
310 def _repr_json_(self):
301 return self.data
311 return self.data
302
312
303
313
304 class Javascript(DisplayObject):
314 class Javascript(DisplayObject):
305
315
306 def _repr_javascript_(self):
316 def _repr_javascript_(self):
307 return self.data
317 return self.data
308
318
309
319
310 class Image(DisplayObject):
320 class Image(DisplayObject):
311
321
312 _read_flags = 'rb'
322 _read_flags = 'rb'
313
323
314 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=False):
324 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=False):
315 """Create a display an PNG/JPEG image given raw data.
325 """Create a display an PNG/JPEG image given raw data.
316
326
317 When this object is returned by an expression or passed to the
327 When this object is returned by an expression or passed to the
318 display function, it will result in the image being displayed
328 display function, it will result in the image being displayed
319 in the frontend.
329 in the frontend.
320
330
321 Parameters
331 Parameters
322 ----------
332 ----------
323 data : unicode, str or bytes
333 data : unicode, str or bytes
324 The raw data or a URL to download the data from.
334 The raw data or a URL to download the data from.
325 url : unicode
335 url : unicode
326 A URL to download the data from.
336 A URL to download the data from.
327 filename : unicode
337 filename : unicode
328 Path to a local file to load the data from.
338 Path to a local file to load the data from.
329 format : unicode
339 format : unicode
330 The format of the image data (png/jpeg/jpg). If a filename or URL is given
340 The format of the image data (png/jpeg/jpg). If a filename or URL is given
331 for format will be inferred from the filename extension.
341 for format will be inferred from the filename extension.
332 embed : bool
342 embed : bool
333 Should the image data be embedded in the notebook using a data URI (True)
343 Should the image data be embedded in the notebook using a data URI (True)
334 or be loaded using an <img> tag. Set this to True if you want the image
344 or be loaded using an <img> tag. Set this to True if you want the image
335 to be viewable later with no internet connection. If a filename is given
345 to be viewable later with no internet connection. If a filename is given
336 embed is always set to True.
346 embed is always set to True.
337 """
347 """
338 if filename is not None:
348 if filename is not None:
339 ext = self._find_ext(filename)
349 ext = self._find_ext(filename)
340 elif url is not None:
350 elif url is not None:
341 ext = self._find_ext(url)
351 ext = self._find_ext(url)
342 elif data.startswith('http'):
352 elif data.startswith('http'):
343 ext = self._find_ext(data)
353 ext = self._find_ext(data)
344 else:
354 else:
345 ext = None
355 ext = None
346 if ext is not None:
356 if ext is not None:
347 if ext == u'jpg' or ext == u'jpeg':
357 if ext == u'jpg' or ext == u'jpeg':
348 format = u'jpeg'
358 format = u'jpeg'
349 if ext == u'png':
359 if ext == u'png':
350 format = u'png'
360 format = u'png'
351 self.format = unicode(format).lower()
361 self.format = unicode(format).lower()
352 self.embed = True if filename is not None else embed
362 self.embed = True if filename is not None else embed
353 super(Image, self).__init__(data=data, url=url, filename=filename)
363 super(Image, self).__init__(data=data, url=url, filename=filename)
354
364
355 def reload(self):
365 def reload(self):
356 """Reload the raw data from file or URL."""
366 """Reload the raw data from file or URL."""
357 if self.embed:
367 if self.embed:
358 super(Image,self).reload()
368 super(Image,self).reload()
359
369
360 def _repr_html_(self):
370 def _repr_html_(self):
361 if not self.embed:
371 if not self.embed:
362 return u'<img src="%s" />' % self.url
372 return u'<img src="%s" />' % self.url
363
373
364 def _repr_png_(self):
374 def _repr_png_(self):
365 if self.embed and self.format == u'png':
375 if self.embed and self.format == u'png':
366 return self.data
376 return self.data
367
377
368 def _repr_jpeg_(self):
378 def _repr_jpeg_(self):
369 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
379 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
370 return self.data
380 return self.data
371
381
372 def _find_ext(self, s):
382 def _find_ext(self, s):
373 return unicode(s.split('.')[-1].lower())
383 return unicode(s.split('.')[-1].lower())
General Comments 0
You need to be logged in to leave comments. Login now