Show More
@@ -21,21 +21,18 b' import bdb' | |||||
21 | import signal |
|
21 | import signal | |
22 | import sys |
|
22 | import sys | |
23 | import time |
|
23 | import time | |
|
24 | import tempfile | |||
|
25 | import subprocess | |||
24 | from io import BytesIO |
|
26 | from io import BytesIO | |
25 | import base64 |
|
27 | import base64 | |
26 |
|
28 | |||
27 | from Queue import Empty |
|
29 | from Queue import Empty | |
28 |
|
30 | |||
29 | try: |
|
|||
30 | import PIL |
|
|||
31 | except ImportError: |
|
|||
32 | PIL = None |
|
|||
33 |
|
||||
34 | from IPython.core.alias import AliasManager, AliasError |
|
31 | from IPython.core.alias import AliasManager, AliasError | |
35 | from IPython.core import page |
|
32 | from IPython.core import page | |
36 | from IPython.utils.warn import warn, error, fatal |
|
33 | from IPython.utils.warn import warn, error, fatal | |
37 | from IPython.utils import io |
|
34 | from IPython.utils import io | |
38 | from IPython.utils.traitlets import List |
|
35 | from IPython.utils.traitlets import List, Enum, Any | |
39 |
|
36 | |||
40 | from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell |
|
37 | from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell | |
41 | from IPython.frontend.terminal.console.completer import ZMQCompleter |
|
38 | from IPython.frontend.terminal.console.completer import ZMQCompleter | |
@@ -45,14 +42,50 b' class ZMQTerminalInteractiveShell(TerminalInteractiveShell):' | |||||
45 | """A subclass of TerminalInteractiveShell that uses the 0MQ kernel""" |
|
42 | """A subclass of TerminalInteractiveShell that uses the 0MQ kernel""" | |
46 | _executing = False |
|
43 | _executing = False | |
47 |
|
44 | |||
48 | image_handler = List([], allow_none=False, config=True, help= |
|
45 | image_handler = Enum(('PIL', 'stream', 'tempfile', 'callable'), | |
|
46 | config=True, help= | |||
49 | """ |
|
47 | """ | |
50 |
Handler |
|
48 | Handler for image type output. This is useful, for example, | |
51 | when connecting to the kernel in which pylab inline backend is |
|
49 | when connecting to the kernel in which pylab inline backend is | |
52 | activated. Handlers in the list is tried one-by-one and first |
|
50 | activated. There are four handlers defined. 'PIL': Use | |
53 | available handler is used. Currently IPython only supports |
|
51 | Python Imaging Library to popup image; 'stream': Use an | |
54 | handler `PIL`. IPython shell pops up window to show image |
|
52 | external program to show the image. Image will be fed into | |
55 | when the kernel sends image (e.g., when you plot a graph). |
|
53 | the STDIN of the program. You will need to configure | |
|
54 | `stream_image_handler`; 'tempfile': Use an external program to | |||
|
55 | show the image. Image will be saved in a temporally file and | |||
|
56 | the program is called with the temporally file. You will need | |||
|
57 | to configure `tempfile_image_handler`; 'callable': You can set | |||
|
58 | any Python callable which is called with the image data. You | |||
|
59 | will need to configure `callable_image_handler`. | |||
|
60 | """ | |||
|
61 | ) | |||
|
62 | ||||
|
63 | stream_image_handler = List(config=True, help= | |||
|
64 | """ | |||
|
65 | Command to invoke an image viewer program when you are using | |||
|
66 | 'stream' image handler. This option is a list of string where | |||
|
67 | the first element is the command itself and reminders are the | |||
|
68 | options for the command. Raw image data is given as STDIN to | |||
|
69 | the program. | |||
|
70 | """ | |||
|
71 | ) | |||
|
72 | ||||
|
73 | tempfile_image_handler = List(config=True, help= | |||
|
74 | """ | |||
|
75 | Command to invoke an image viewer program when you are using | |||
|
76 | 'tempfile' image handler. This option is a list of string | |||
|
77 | where the first element is the command itself and reminders | |||
|
78 | are the options for the command. You can use {file} in the | |||
|
79 | string to represent the location of the generated image file. | |||
|
80 | """ | |||
|
81 | ) | |||
|
82 | ||||
|
83 | callable_image_handler = Any(config=True, help= | |||
|
84 | """ | |||
|
85 | Callable object called via 'callable' image handler with one | |||
|
86 | argument, `data`, which is `msg["content"]["data"]` where | |||
|
87 | `msg` is the message from iopub channel. For exmaple, you can | |||
|
88 | find base64 encoded PNG data as `data['image/png']`. | |||
56 | """ |
|
89 | """ | |
57 | ) |
|
90 | ) | |
58 |
|
91 | |||
@@ -195,16 +228,44 b' class ZMQTerminalInteractiveShell(TerminalInteractiveShell):' | |||||
195 | self.handle_rich_data(sub_msg["content"]["data"]) |
|
228 | self.handle_rich_data(sub_msg["content"]["data"]) | |
196 |
|
229 | |||
197 | def handle_rich_data(self, data): |
|
230 | def handle_rich_data(self, data): | |
198 | if 'image/png' in data: |
|
231 | for mime in ['image/png', 'image/jpeg', 'image/svg+xml']: | |
199 | self.handle_image(data['image/png']) |
|
232 | if mime in data: | |
200 | elif 'image/jpeg' in data: |
|
233 | self.handle_image(data, mime) | |
201 | self.handle_image(data['image/jpeg']) |
|
234 | ||
202 |
|
235 | def handle_image(self, data, mime): | ||
203 | def handle_image(self, string): |
|
236 | handler = getattr( | |
204 | if 'PIL' in self.image_handler and PIL: |
|
237 | self, 'handle_image_{0}'.format(self.image_handler), None) | |
205 | data = base64.decodestring(string) |
|
238 | if handler: | |
206 | img = PIL.Image.open(BytesIO(data)) |
|
239 | handler(data, mime) | |
207 | img.show() |
|
240 | ||
|
241 | def handle_image_PIL(self, data, mime): | |||
|
242 | if mime not in ('image/png', 'image/jpeg'): | |||
|
243 | return | |||
|
244 | import PIL | |||
|
245 | raw = base64.decodestring(data[mime]) | |||
|
246 | img = PIL.Image.open(BytesIO(raw)) | |||
|
247 | img.show() | |||
|
248 | ||||
|
249 | def handle_image_stream(self, data, mime): | |||
|
250 | raw = base64.decodestring(data[mime]) | |||
|
251 | proc = subprocess.Popen( | |||
|
252 | self.stream_image_handler, stdin=subprocess.PIPE, | |||
|
253 | stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |||
|
254 | proc.communicate(raw) | |||
|
255 | ||||
|
256 | def handle_image_tempfile(self, data, mime): | |||
|
257 | raw = base64.decodestring(data[mime]) | |||
|
258 | with tempfile.NamedTemporaryFile() as f: | |||
|
259 | f.write(raw) | |||
|
260 | f.flush() | |||
|
261 | fmt = dict(file=f.name) | |||
|
262 | args = [s.format(**fmt) for s in self.tempfile_image_handler] | |||
|
263 | subprocess.Popen( | |||
|
264 | args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, | |||
|
265 | ).communicate() | |||
|
266 | ||||
|
267 | def handle_image_callable(self, data, mime): | |||
|
268 | self.callable_image_handler(data) | |||
208 |
|
269 | |||
209 | def handle_stdin_request(self, timeout=0.1): |
|
270 | def handle_stdin_request(self, timeout=0.1): | |
210 | """ Method to capture raw_input |
|
271 | """ Method to capture raw_input |
General Comments 0
You need to be logged in to leave comments.
Login now