Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(411)

Side by Side Diff: ports/ipython-ppapi/kernel.py

Issue 165473002: Adds an IPython kernel running in NaCl, and a wrapper as a Chrome extension. Base URL: https://naclports.googlecode.com/svn/trunk/src
Patch Set: rebase to master Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ports/ipython-ppapi/kernel.cc ('k') | ports/ipython-ppapi/pkg_info » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright (c) 2014 Google Inc. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """A simple shell that uses the IPython messaging system."""
6
7 import json
8 import logging
9 import sys
10
11 import IPython
12 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
13 from IPython.utils.traitlets import Type, Dict, Instance
14 from IPython.core.displayhook import DisplayHook
15 from IPython.utils.jsonutil import json_clean, encode_images
16 from IPython.core.displaypub import DisplayPublisher
17 from IPython.config.configurable import Configurable
18
19 # module defined in shell.cc for communicating via pepper API
20 import ppmessage
21
22 def sendMessage(socket_name, msg_type, parent_header=None, content=None):
23 if parent_header is None:
24 parent_header = {}
25 if content is None:
26 content = {}
27 msg = {
28 'header': {'msg_type': msg_type},
29 'parent_header': parent_header,
30 'content': content
31 }
32 ppmessage._PostJSONMessage(socket_name, json.dumps(msg))
33
34 class MsgOutStream(object):
35 """Class to overrides stderr and stdout."""
36
37 def __init__(self, stream_name):
38 self._stream_name = stream_name
39 self._parent_header = {}
40
41 def SetParentHeader(self, parent_header):
42 self._parent_header = parent_header
43
44 def close(self):
45 pass
46
47 def flush(self):
48 pass
49
50 def write(self, string):
51 sendMessage('iopub', 'stream', parent_header=self._parent_header,
52 content={'name': self._stream_name, 'data': string})
53
54 def writelines(self, sequence):
55 for string in sequence:
56 self.write(string)
57
58 # override sys.stdout and sys.stderr to broadcast on iopub
59 stdout_stream = MsgOutStream('stdout')
60 stderr_stream = MsgOutStream('stderr')
61 sys_stdout = sys.stdout
62 sys_stderr = sys.stderr
63 sys.stdout = stdout_stream
64 sys.stderr = stderr_stream
65
66
67
68 class PepperShellDisplayHook(DisplayHook):
69 parent_header = Dict({})
70
71 def set_parent_header(self, parent_header):
72 """Set the parent for outbound messages."""
73 self.parent_header = parent_header
74
75 def start_displayhook(self):
76 self.content = {}
77
78 def write_output_prompt(self):
79 self.content['execution_count'] = self.prompt_count
80
81 def write_format_data(self, format_dict, md_dict=None):
82 self.content['data'] = encode_images(format_dict)
83 self.content['metadata'] = md_dict
84
85 def finish_displayhook(self):
86 sys.stdout.flush()
87 sys.stderr.flush()
88 sendMessage('iopub', 'pyout', parent_header=self.parent_header,
89 content=self.content)
90 self.content = None
91
92
93 class PepperDisplayPublisher(DisplayPublisher):
94 parent_header = Dict({})
95
96 def set_parent_header(self, parent_header):
97 self.parent_header = parent_header
98
99 def _flush_streams(self):
100 """flush IO Streams prior to display"""
101 sys.stdout.flush()
102 sys.stderr.flush()
103
104 def publish(self, source, data, metadata=None):
105 self._flush_streams()
106 if metadata is None:
107 metadata = {}
108 self._validate_data(source, data, metadata)
109 content = {}
110 content['source'] = source
111 content['data'] = encode_images(data)
112 content['metadata'] = metadata
113 sendMessage('iopub', 'display_data', content=json_clean(content),
114 parent_header=self.parent_header)
115
116 def clear_output(self, stdout=True, stderr=True, other=True):
117 content = dict(stdout=stdout, stderr=stderr, other=other)
118
119 if stdout:
120 sys.stdout.write('\r')
121 if stderr:
122 sys.stderr.write('\r')
123
124 self._flush_streams()
125 sendMessage('iopub', 'clear_output', content=content,
126 parent_header=self.parent_header)
127
128
129 class PepperInteractiveShell(InteractiveShell):
130 """A subclass of InteractiveShell for the Pepper Messagin API."""
131 displayhook_class = Type(PepperShellDisplayHook)
132 display_pub_class = Type(PepperDisplayPublisher)
133 @staticmethod
134 def enable_gui(gui):
135 pass
136
137
138 InteractiveShellABC.register(PepperInteractiveShell)
139
140 class PepperKernel(Configurable):
141 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
142 shell_class = Type(PepperInteractiveShell)
143
144 def __init__(self):
145 self.shell = self.shell_class.instance(parent=self)
146 self.shell.run_cell("""
147 import os
148 matplotlib_config_dir = '/mplconfigdir'
149 os.environ['XDG_CONFIG_HOME'] = matplotlib_config_dir
150 os.environ['TMP'] = ''
151 import matplotlib
152 import matplotlib.cbook
153 """)
154
155 execution_count = 1
156
157 shell = PepperKernel().shell
158
159 # Special message to indicate the NaCl kernel is ready.
160 sendMessage('iopub', 'status', content={'execution_state': 'nacl_ready'})
161
162 while 1:
163 sendMessage('iopub', 'status', content={'execution_state': 'idle'})
164 msg = json.loads(ppmessage._AcquireJSONMessageWait())
165 sendMessage('iopub', 'status', content={'execution_state': 'busy'})
166
167 if not 'header' in msg:
168 continue
169 request_header = msg['header']
170 if not 'msg_type' in request_header:
171 continue
172 msg_type = request_header['msg_type']
173 if msg_type == 'execute_request':
174 try:
175 content = msg[u'content']
176 code = content[u'code']
177 silent = content[u'silent']
178 store_history = content.get(u'store_history', not silent)
179 except:
180 self.log.error("Got bad msg: ")
181 self.log.error("%s", msg)
182 continue
183
184 # Let output streams know which message the output is for
185 stdout_stream.SetParentHeader(request_header)
186 stderr_stream.SetParentHeader(request_header)
187 shell.displayhook.set_parent_header(request_header)
188 shell.display_pub.set_parent_header(request_header)
189
190 status = 'ok'
191 content = {}
192 try:
193 shell.run_cell(msg['content']['code'],
194 store_history=store_history,
195 silent=silent)
196 except Exception, ex:
197 status = 'error'
198 logging.exception('Exception occured while running cell')
199
200 content = {'status': status,
201 'execution_count': execution_count}
202
203 if status == 'ok':
204 content['payload'] = []
205 content['user_variables'] = {}
206 content['user_expressions'] = {}
207 elif status == 'error':
208 content['ename'] = type(ex).__name__
209 content['evalue'] = str(ex)
210 content['traceback'] = []
211
212 execution_count += 1
213 if status == 'error':
214 sendMessage('iopub', 'pyerr', parent_header=request_header,
215 content={
216 'execution_count': execution_count,
217 'ename': type(ex).__name__,
218 'evalue': str(ex),
219 'traceback': []
220 }
221 )
222 sendMessage('shell', 'execute_reply', parent_header=request_header,
223 content=content)
224 elif msg_type == 'complete_request':
225 c = msg['content']
226 try:
227 cpos = int(c['cursor_pos'])
228 except:
229 cpos = len(c['text'])
230 if cpos == 0:
231 cpos = len(c['line'])
232 txt, matches = shell.complete(c['text'], c['line'], cpos)
233 sendMessage('shell', 'complete_reply',
234 parent_header = request_header,
235 content = {
236 'matches': matches,
237 'matched_text': txt,
238 'status': 'ok'
239 })
240 elif msg_type == 'restart':
241 # break out of this loop, ending this program.
242 # The main event loop in shell.cc will then
243 # run this program again.
244 break
245 elif msg_type == 'kill':
246 # Raise an exception so that the function
247 # running this script will return -1, resulting
248 # in no restart of this script.
249 raise RuntimeError
OLDNEW
« no previous file with comments | « ports/ipython-ppapi/kernel.cc ('k') | ports/ipython-ppapi/pkg_info » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698