##// END OF EJS Templates
Finishing display system work....
Brian E. Granger -
Show More
@@ -21,7 +21,7 b' from .displaypub import ('
21 21 publish_pretty, publish_html,
22 22 publish_latex, publish_svg,
23 23 publish_png, publish_json,
24 publish_javascript
24 publish_javascript, publish_jpeg
25 25 )
26 26
27 27 #-----------------------------------------------------------------------------
@@ -86,7 +86,7 b' def display_html(*objs, **kwargs):'
86 86 Parameters
87 87 ----------
88 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 90 display.
91 91 raw : bool
92 92 Are the data objects raw data or Python objects that need to be
@@ -140,6 +140,26 b' def display_png(*objs, **kwargs):'
140 140 display(*objs, include=['text/plain','image/png'])
141 141
142 142
143 def display_jpeg(*objs, **kwargs):
144 """Display the JPEG representation of an object.
145
146 Parameters
147 ----------
148 objs : tuple of objects
149 The Python objects to display, or if raw=True raw JPEG data to
150 display.
151 raw : bool
152 Are the data objects raw data or Python objects that need to be
153 formatted before display? [default: False]
154 """
155 raw = kwargs.pop('raw',False)
156 if raw:
157 for obj in objs:
158 publish_png(obj)
159 else:
160 display(*objs, include=['text/plain','image/jpeg'])
161
162
143 163 def display_latex(*objs, **kwargs):
144 164 """Display the LaTeX representation of an object.
145 165
@@ -207,28 +227,49 b' def display_javascript(*objs, **kwargs):'
207 227 class DisplayObject(object):
208 228 """An object that wraps data to be displayed."""
209 229
210 def __init__(self, data):
211 """Create a display object given raw data of a MIME type or a URL.
230 _read_flags = 'r'
231
232 def __init__(self, data=None, url=None, filename=None):
233 """Create a display object given raw data.
212 234
213 235 When this object is returned by an expression or passed to the
214 236 display function, it will result in the data being displayed
215 237 in the frontend. The MIME type of the data should match the
216 238 subclasses used, so the Png subclass should be used for 'image/png'
217 239 data. If the data is a URL, the data will first be downloaded
218 and then displayed.
240 and then displayed. If
219 241
220 242 Parameters
221 243 ----------
222 244 data : unicode, str or bytes
223 245 The raw data or a URL to download the data from.
246 url : unicode
247 A URL to download the data from.
248 filename : unicode
249 Path to a local file to load the data from.
224 250 """
225 if data.startswith('http'):
226 import urllib2
227 response = urllib2.urlopen(data)
228 self.data = response.read()
251 if data is not None and data.startswith('http'):
252 self.url = data
253 self.filename = None
254 self.data = None
229 255 else:
230 256 self.data = data
231
257 self.url = url
258 self.filename = None if filename is None else unicode(filename)
259 self.reload()
260
261 def reload(self):
262 """Reload the raw data from file or URL."""
263 if self.filename is not None:
264 with open(self.filename, self._read_flags) as f:
265 self.data = f.read()
266 elif self.url is not None:
267 try:
268 import urllib2
269 response = urllib2.urlopen(self.url)
270 self.data = response.read()
271 except:
272 self.data = None
232 273
233 274 class Pretty(DisplayObject):
234 275
@@ -236,39 +277,97 b' class Pretty(DisplayObject):'
236 277 return self.data
237 278
238 279
239 class Html(DisplayObject):
280 class HTML(DisplayObject):
240 281
241 282 def _repr_html_(self):
242 283 return self.data
243 284
244 285
245 class Latex(DisplayObject):
286 class Math(DisplayObject):
246 287
247 288 def _repr_latex_(self):
248 289 return self.data
249 290
250 291
251 class Png(DisplayObject):
252
253 def _repr_png_(self):
254 return self.data
255
256
257 class Svg(DisplayObject):
292 class SVG(DisplayObject):
258 293
259 294 def _repr_svg_(self):
260 295 return self.data
261 296
262 297
263 class Json(DisplayObject):
298 class JSON(DisplayObject):
264 299
265 300 def _repr_json_(self):
266 301 return self.data
267 302
268 303
269 class Javscript(DisplayObject):
304 class Javascript(DisplayObject):
270 305
271 306 def _repr_javascript_(self):
272 307 return self.data
273 308
274 309
310 class Image(DisplayObject):
311
312 _read_flags = 'rb'
313
314 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.
316
317 When this object is returned by an expression or passed to the
318 display function, it will result in the image being displayed
319 in the frontend.
320
321 Parameters
322 ----------
323 data : unicode, str or bytes
324 The raw data or a URL to download the data from.
325 url : unicode
326 A URL to download the data from.
327 filename : unicode
328 Path to a local file to load the data from.
329 format : unicode
330 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.
332 embed : bool
333 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
335 to be viewable later with no internet connection. If a filename is given
336 embed is always set to True.
337 """
338 if filename is not None:
339 ext = self._find_ext(filename)
340 elif url is not None:
341 ext = self._find_ext(url)
342 elif data.startswith('http'):
343 ext = self._find_ext(data)
344 else:
345 ext = None
346 if ext is not None:
347 if ext == u'jpg' or ext == u'jpeg':
348 format = u'jpeg'
349 if ext == u'png':
350 format = u'png'
351 self.format = unicode(format).lower()
352 self.embed = True if filename is not None else embed
353 super(Image, self).__init__(data=data, url=url, filename=filename)
354
355 def reload(self):
356 """Reload the raw data from file or URL."""
357 if self.embed:
358 super(Image,self).reload()
359
360 def _repr_html_(self):
361 if not self.embed:
362 return u'<img src="%s" />' % self.url
363
364 def _repr_png_(self):
365 if self.embed and self.format == u'png':
366 return self.data
367
368 def _repr_jpeg_(self):
369 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
370 return self.data
371
372 def _find_ext(self, s):
373 return unicode(s.split('.')[-1].lower())
@@ -78,6 +78,7 b' class DisplayPublisher(Configurable):'
78 78 * application/json
79 79 * application/javascript
80 80 * image/png
81 * image/jpeg
81 82 * image/svg+xml
82 83
83 84 Parameters
@@ -118,6 +119,7 b' def publish_display_data(source, data, metadata=None):'
118 119 * application/json
119 120 * application/javascript
120 121 * image/png
122 * image/jpeg
121 123 * image/svg+xml
122 124
123 125 Parameters
@@ -166,12 +168,12 b' def publish_pretty(data, metadata=None):'
166 168
167 169
168 170 def publish_html(data, metadata=None):
169 """Publish raw html data to all frontends.
171 """Publish raw HTML data to all frontends.
170 172
171 173 Parameters
172 174 ----------
173 175 data : unicode
174 The raw html data to publish.
176 The raw HTML data to publish.
175 177 metadata : dict
176 178 A dictionary for metadata related to the data. This can contain
177 179 arbitrary key, value pairs that frontends can use to interpret
@@ -185,12 +187,12 b' def publish_html(data, metadata=None):'
185 187
186 188
187 189 def publish_latex(data, metadata=None):
188 """Publish raw latex data to all frontends.
190 """Publish raw LaTeX data to all frontends.
189 191
190 192 Parameters
191 193 ----------
192 194 data : unicode
193 The raw latex data to publish.
195 The raw LaTeX data to publish.
194 196 metadata : dict
195 197 A dictionary for metadata related to the data. This can contain
196 198 arbitrary key, value pairs that frontends can use to interpret
@@ -203,12 +205,12 b' def publish_latex(data, metadata=None):'
203 205 )
204 206
205 207 def publish_png(data, metadata=None):
206 """Publish raw binary png data to all frontends.
208 """Publish raw binary PNG data to all frontends.
207 209
208 210 Parameters
209 211 ----------
210 212 data : str/bytes
211 The raw binary png data to publish.
213 The raw binary PNG data to publish.
212 214 metadata : dict
213 215 A dictionary for metadata related to the data. This can contain
214 216 arbitrary key, value pairs that frontends can use to interpret
@@ -220,13 +222,33 b' def publish_png(data, metadata=None):'
220 222 metadata=metadata
221 223 )
222 224
225
226 def publish_jpeg(data, metadata=None):
227 """Publish raw binary JPEG data to all frontends.
228
229 Parameters
230 ----------
231 data : str/bytes
232 The raw binary JPEG data to publish.
233 metadata : dict
234 A dictionary for metadata related to the data. This can contain
235 arbitrary key, value pairs that frontends can use to interpret
236 the data.
237 """
238 publish_display_data(
239 u'IPython.core.displaypub.publish_jpeg',
240 {'image/jpeg':data},
241 metadata=metadata
242 )
243
244
223 245 def publish_svg(data, metadata=None):
224 """Publish raw svg data to all frontends.
246 """Publish raw SVG data to all frontends.
225 247
226 248 Parameters
227 249 ----------
228 250 data : unicode
229 The raw svg data to publish.
251 The raw SVG data to publish.
230 252 metadata : dict
231 253 A dictionary for metadata related to the data. This can contain
232 254 arbitrary key, value pairs that frontends can use to interpret
@@ -239,12 +261,12 b' def publish_svg(data, metadata=None):'
239 261 )
240 262
241 263 def publish_json(data, metadata=None):
242 """Publish raw json data to all frontends.
264 """Publish raw JSON data to all frontends.
243 265
244 266 Parameters
245 267 ----------
246 268 data : unicode
247 The raw json data to publish.
269 The raw JSON data to publish.
248 270 metadata : dict
249 271 A dictionary for metadata related to the data. This can contain
250 272 arbitrary key, value pairs that frontends can use to interpret
@@ -257,12 +279,12 b' def publish_json(data, metadata=None):'
257 279 )
258 280
259 281 def publish_javascript(data, metadata=None):
260 """Publish raw javascript data to all frontends.
282 """Publish raw Javascript data to all frontends.
261 283
262 284 Parameters
263 285 ----------
264 286 data : unicode
265 The raw javascript data to publish.
287 The raw Javascript data to publish.
266 288 metadata : dict
267 289 A dictionary for metadata related to the data. This can contain
268 290 arbitrary key, value pairs that frontends can use to interpret
@@ -51,6 +51,7 b' class DisplayFormatter(Configurable):'
51 51 HTMLFormatter,
52 52 SVGFormatter,
53 53 PNGFormatter,
54 JPEGFormatter,
54 55 LatexFormatter,
55 56 JSONFormatter,
56 57 JavascriptFormatter
@@ -74,6 +75,7 b' class DisplayFormatter(Configurable):'
74 75 * application/json
75 76 * application/javascript
76 77 * image/png
78 * image/jpeg
77 79 * image/svg+xml
78 80
79 81 Parameters
@@ -496,6 +498,22 b' class PNGFormatter(BaseFormatter):'
496 498 print_method = ObjectName('_repr_png_')
497 499
498 500
501 class JPEGFormatter(BaseFormatter):
502 """A JPEG formatter.
503
504 To define the callables that compute the JPEG representation of your
505 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
506 or :meth:`for_type_by_name` methods to register functions that handle
507 this.
508
509 The return value of this formatter should be raw JPEG data, *not*
510 base64 encoded.
511 """
512 format_type = Unicode('image/jpeg')
513
514 print_method = ObjectName('_repr_jpeg_')
515
516
499 517 class LatexFormatter(BaseFormatter):
500 518 """A LaTeX formatter.
501 519
@@ -547,6 +565,7 b' FormatterABC.register(PlainTextFormatter)'
547 565 FormatterABC.register(HTMLFormatter)
548 566 FormatterABC.register(SVGFormatter)
549 567 FormatterABC.register(PNGFormatter)
568 FormatterABC.register(JPEGFormatter)
550 569 FormatterABC.register(LatexFormatter)
551 570 FormatterABC.register(JSONFormatter)
552 571 FormatterABC.register(JavascriptFormatter)
@@ -565,6 +584,7 b' def format_display_data(obj, include=None, exclude=None):'
565 584 * application/json
566 585 * application/javascript
567 586 * image/png
587 * image/jpeg
568 588 * image/svg+xml
569 589
570 590 Parameters
@@ -596,3 +616,4 b' def format_display_data(obj, include=None, exclude=None):'
596 616 include,
597 617 exclude
598 618 )
619
@@ -2119,7 +2119,8 b' Currently the magic system has the following functions:\\n"""'
2119 2119 response = urllib2.urlopen(arg_s)
2120 2120 content = response.read()
2121 2121 else:
2122 content = open(arg_s).read()
2122 with open(arg_s) as f:
2123 content = f.read()
2123 2124 self.set_next_input(content)
2124 2125
2125 2126 def _find_edit_target(self, args, opts, last_call):
@@ -205,13 +205,15 b' var IPython = (function (IPython) {'
205 205
206 206 CodeCell.prototype.append_pyerr = function (json) {
207 207 var tb = json.traceback;
208 var s = '';
209 var len = tb.length;
210 for (var i=0; i<len; i++) {
211 s = s + tb[i] + '\n';
212 }
213 s = s + '\n';
214 this.append_text(s);
208 if (tb !== undefined) {
209 var s = '';
210 var len = tb.length;
211 for (var i=0; i<len; i++) {
212 s = s + tb[i] + '\n';
213 }
214 s = s + '\n';
215 this.append_text(s);
216 };
215 217 };
216 218
217 219
@@ -240,6 +242,8 b' var IPython = (function (IPython) {'
240 242 this.append_svg(json.svg, element);
241 243 } else if (json.png !== undefined) {
242 244 this.append_png(json.png, element);
245 } else if (json.jpeg !== undefined) {
246 this.append_jpeg(json.jpeg, element);
243 247 } else if (json.text !== undefined) {
244 248 this.append_text(json.text, element);
245 249 };
@@ -283,6 +287,15 b' var IPython = (function (IPython) {'
283 287 };
284 288
285 289
290 CodeCell.prototype.append_jpeg = function (jpeg, element) {
291 element = element || this.element.find("div.output");
292 var toinsert = $("<div/>").addClass("output_area output_jpeg");
293 toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
294 element.append(toinsert);
295 return element;
296 };
297
298
286 299 CodeCell.prototype.append_latex = function (latex, element) {
287 300 // This method cannot do the typesetting because the latex first has to
288 301 // be on the page.
@@ -544,6 +544,9 b' var IPython = (function (IPython) {'
544 544 if (data['image/png'] !== undefined) {
545 545 json.png = data['image/png'];
546 546 };
547 if (data['image/jpeg'] !== undefined) {
548 json.jpeg = data['image/jpeg'];
549 };
547 550 if (data['text/latex'] !== undefined) {
548 551 json.latex = data['text/latex'];
549 552 };
@@ -24,7 +24,7 b' def from_dict(d):'
24 24
25 25 def new_output(output_type=None, output_text=None, output_png=None,
26 26 output_html=None, output_svg=None, output_latex=None, output_json=None,
27 output_javascript=None, prompt_number=None):
27 output_javascript=None, output_jpeg=None, prompt_number=None):
28 28 """Create a new code cell with input and output"""
29 29 output = NotebookNode()
30 30 if output_type is not None:
@@ -33,6 +33,8 b' def new_output(output_type=None, output_text=None, output_png=None,'
33 33 output.text = unicode(output_text)
34 34 if output_png is not None:
35 35 output.png = bytes(output_png)
36 if output_jpeg is not None:
37 output.jpeg = bytes(output_jpeg)
36 38 if output_html is not None:
37 39 output.html = unicode(output_html)
38 40 if output_svg is not None:
@@ -91,16 +91,17 b' class XMLReader(NotebookReader):'
91 91 output_type = _get_text(output_e,'output_type')
92 92 output_text = _get_text(output_e,'text')
93 93 output_png = _get_binary(output_e,'png')
94 output_jpeg = _get_binary(output_e,'jpeg')
94 95 output_svg = _get_text(output_e,'svg')
95 96 output_html = _get_text(output_e,'html')
96 97 output_latex = _get_text(output_e,'latex')
97 98 output_json = _get_text(output_e,'json')
98 99 output_javascript = _get_text(output_e,'javascript')
99 100 output = new_output(output_type=output_type,output_png=output_png,
100 output_text=output_text,output_svg=output_svg,
101 output_html=output_html,output_latex=output_latex,
102 output_json=output_json,output_javascript=output_javascript,
103 prompt_number=out_prompt_number
101 output_text=output_text, output_svg=output_svg,
102 output_html=output_html, output_latex=output_latex,
103 output_json=output_json, output_javascript=output_javascript,
104 output_jpeg=output_jpeg, prompt_number=out_prompt_number
104 105 )
105 106 outputs.append(output)
106 107 cc = new_code_cell(input=input,prompt_number=prompt_number,
@@ -147,6 +148,7 b' class XMLWriter(NotebookWriter):'
147 148 _set_text(output,'output_type',output_e,'output_type')
148 149 _set_text(output,'text',output_e,'text')
149 150 _set_binary(output,'png',output_e,'png')
151 _set_binary(output,'jpeg',output_e,'jpeg')
150 152 _set_text(output,'html',output_e,'html')
151 153 _set_text(output,'svg',output_e,'svg')
152 154 _set_text(output,'latex',output_e,'latex')
@@ -8,6 +8,8 b' def base64_decode(nb):'
8 8 if cell.cell_type == 'code':
9 9 if 'png' in cell:
10 10 cell.png = bytes(decodestring(cell.png))
11 if 'jpeg' in cell:
12 cell.jpeg = bytes(decodestring(cell.jpeg))
11 13 return nb
12 14
13 15
@@ -18,6 +20,8 b' def base64_encode(nb):'
18 20 if cell.cell_type == 'code':
19 21 if 'png' in cell:
20 22 cell.png = unicode(encodestring(cell.png))
23 if 'jpeg' in cell:
24 cell.jpeg = unicode(encodestring(cell.jpeg))
21 25 return nb
22 26
23 27
@@ -39,6 +39,7 b' ws.cells.append(new_code_cell('
39 39 output_html=u'The HTML rep',
40 40 output_latex=u'$a$',
41 41 output_png=b'data',
42 output_jpeg=b'data',
42 43 output_svg=u'<svg>',
43 44 output_json=u'json data',
44 45 output_javascript=u'var i=0;',
@@ -49,6 +50,7 b' ws.cells.append(new_code_cell('
49 50 output_html=u'The HTML rep',
50 51 output_latex=u'$a$',
51 52 output_png=b'data',
53 output_jpeg=b'data',
52 54 output_svg=u'<svg>',
53 55 output_json=u'json data',
54 56 output_javascript=u'var i=0;',
@@ -27,10 +27,14 b' class ZMQDisplayHook(object):'
27 27 self.parent_header = extract_header(parent)
28 28
29 29
30 def _encode_png(data):
31 pngdata = data.get('image/png')
30 def _encode_binary(format_dict):
31 pngdata = format_dict.get('image/png')
32 32 if pngdata is not None:
33 data['image/png'] = encodestring(pngdata)
33 format_dict['image/png'] = encodestring(pngdata)
34 jpegdata = format_dict.get('image/jpeg')
35 if jpegdata is not None:
36 format_dict['image/jpeg'] = encodestring(jpegdata)
37
34 38
35 39 class ZMQShellDisplayHook(DisplayHook):
36 40 """A displayhook subclass that publishes data using ZeroMQ. This is intended
@@ -54,11 +58,11 b' class ZMQShellDisplayHook(DisplayHook):'
54 58 self.msg['content']['execution_count'] = self.prompt_count
55 59
56 60 def write_format_data(self, format_dict):
57 pngdata = format_dict.get('image/png')
58 _encode_png(format_dict)
61 _encode_binary(format_dict)
59 62 self.msg['content']['data'] = format_dict
60 63
61 64 def finish_displayhook(self):
62 65 """Finish up all displayhook activities."""
63 66 self.session.send(self.pub_socket, self.msg)
64 67 self.msg = None
68
@@ -33,7 +33,7 b' from IPython.utils import io'
33 33 from IPython.utils.path import get_py_filename
34 34 from IPython.utils.traitlets import Instance, Type, Dict, CBool
35 35 from IPython.utils.warn import warn
36 from IPython.zmq.displayhook import ZMQShellDisplayHook, _encode_png
36 from IPython.zmq.displayhook import ZMQShellDisplayHook, _encode_binary
37 37 from IPython.zmq.session import extract_header
38 38 from session import Session
39 39
@@ -65,7 +65,7 b' class ZMQDisplayPublisher(DisplayPublisher):'
65 65 self._validate_data(source, data, metadata)
66 66 content = {}
67 67 content['source'] = source
68 _encode_png(data)
68 _encode_binary(data)
69 69 content['data'] = data
70 70 content['metadata'] = metadata
71 71 self.session.send(
General Comments 0
You need to be logged in to leave comments. Login now