##// END OF EJS Templates
Fixing import statments in handlers and notebookapp.
Brian E. Granger -
Show More
@@ -1,275 +1,166 b''
1 1 import datetime
2 2 import json
3 3 import logging
4 4 import os
5 5 import urllib
6 6 import uuid
7 7 from Queue import Queue
8 8
9 import zmq
10
11 # Install the pyzmq ioloop. This has to be done before anything else from
12 # tornado is imported.
13 from zmq.eventloop import ioloop
14 import tornado.ioloop
15 tornado.ioloop = ioloop
16
17 from tornado import httpserver
18 9 from tornado import options
19 10 from tornado import web
20 11 from tornado import websocket
21 12
22 from kernelmanager import KernelManager
23 13
24 14 options.define("port", default=8888, help="run on the given port", type=int)
25 15
26 16 _kernel_id_regex = r"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)"
27 17 _kernel_action_regex = r"(?P<action>restart|interrupt)"
28 18
29 19 class MainHandler(web.RequestHandler):
30 20 def get(self):
31 21 self.render('notebook.html')
32 22
33 23
34 24 class KernelHandler(web.RequestHandler):
35 25
36 26 def get(self):
37 27 self.write(json.dumps(self.application.kernel_ids))
38 28
39 29 def post(self):
40 30 kernel_id = self.application.start_kernel()
41 31 self.write(json.dumps(kernel_id))
42 32
43 33
44 34 class KernelActionHandler(web.RequestHandler):
45 35
46 36 def post(self, kernel_id, action):
47 37 # TODO: figure out a better way of handling RPC style calls.
48 38 if action == 'interrupt':
49 39 self.application.interrupt_kernel(kernel_id)
50 40 if action == 'restart':
51 41 new_kernel_id = self.application.restart_kernel(kernel_id)
52 42 self.write(json.dumps(new_kernel_id))
53 43
54 44
55 45 class ZMQStreamRouter(object):
56 46
57 47 def __init__(self, zmq_stream):
58 48 self.zmq_stream = zmq_stream
59 49 self._clients = {}
60 50 self.zmq_stream.on_recv(self._on_zmq_reply)
61 51
62 52 def register_client(self, client):
63 53 client_id = uuid.uuid4()
64 54 self._clients[client_id] = client
65 55 return client_id
66 56
67 57 def unregister_client(self, client_id):
68 58 del self._clients[client_id]
69 59
70 60 def copy_clients(self, router):
71 61 # Copy the clients of another router.
72 62 for client_id, client in router._clients.items():
73 63 client.router = self
74 64 self._clients[client_id] = client
75 65
76 66
77 67 class IOPubStreamRouter(ZMQStreamRouter):
78 68
79 69 def _on_zmq_reply(self, msg_list):
80 70 for client_id, client in self._clients.items():
81 71 for msg in msg_list:
82 72 client.write_message(msg)
83 73
84 74 def forward_unicode(self, client_id, msg):
85 75 # This is a SUB stream that we should never write to.
86 76 pass
87 77
88 78
89 79 class ShellStreamRouter(ZMQStreamRouter):
90 80
91 81 def __init__(self, zmq_stream):
92 82 ZMQStreamRouter.__init__(self, zmq_stream)
93 83 self._request_queue = Queue()
94 84
95 85 def _on_zmq_reply(self, msg_list):
96 86 client_id = self._request_queue.get(block=False)
97 87 client = self._clients.get(client_id)
98 88 if client is not None:
99 89 for msg in msg_list:
100 90 client.write_message(msg)
101 91
102 92 def forward_unicode(self, client_id, msg):
103 93 self._request_queue.put(client_id)
104 94 self.zmq_stream.send_unicode(msg)
105 95
106 96
107 97 class ZMQStreamHandler(websocket.WebSocketHandler):
108 98
109 99 def initialize(self, stream_name):
110 100 self.stream_name = stream_name
111 101
112 102 def open(self, kernel_id):
113 103 self.router = self.application.get_router(kernel_id, self.stream_name)
114 104 self.client_id = self.router.register_client(self)
115 105 logging.info("Connection open: %s, %s" % (kernel_id, self.client_id))
116 106
117 107 def on_message(self, msg):
118 108 self.router.forward_unicode(self.client_id, msg)
119 109
120 110 def on_close(self):
121 111 self.router.unregister_client(self.client_id)
122 112 logging.info("Connection closed: %s" % self.client_id)
123 113
124 114
125 115 class NotebookRootHandler(web.RequestHandler):
126 116
127 117 def get(self):
128 118 files = os.listdir(os.getcwd())
129 119 files = [file for file in files if file.endswith(".ipynb")]
130 120 self.write(json.dumps(files))
131 121
132 122
133 123 class NotebookHandler(web.RequestHandler):
134 124
135 125 SUPPORTED_METHODS = ("GET", "DELETE", "PUT")
136 126
137 127 def find_path(self, filename):
138 128 filename = urllib.unquote(filename)
139 129 if not filename.endswith('.ipynb'):
140 130 raise web.HTTPError(400)
141 131 path = os.path.join(os.getcwd(), filename)
142 132 return path
143 133
144 134 def get(self, filename):
145 135 path = self.find_path(filename)
146 136 if not os.path.isfile(path):
147 137 raise web.HTTPError(404)
148 138 info = os.stat(path)
149 139 self.set_header("Content-Type", "application/unknown")
150 140 self.set_header("Last-Modified", datetime.datetime.utcfromtimestamp(
151 141 info.st_mtime))
152 142 f = open(path, "r")
153 143 try:
154 144 self.finish(f.read())
155 145 finally:
156 146 f.close()
157 147
158 148 def put(self, filename):
159 149 path = self.find_path(filename)
160 150 f = open(path, "w")
161 151 f.write(self.request.body)
162 152 f.close()
163 153 self.finish()
164 154
165 155 def delete(self, filename):
166 156 path = self.find_path(filename)
167 157 if not os.path.isfile(path):
168 158 raise web.HTTPError(404)
169 159 os.unlink(path)
170 160 self.set_status(204)
171 161 self.finish()
172 162
173 163
174 class NotebookApplication(web.Application):
175
176 def __init__(self):
177 handlers = [
178 (r"/", MainHandler),
179 (r"/kernels", KernelHandler),
180 (r"/kernels/%s/%s" % (_kernel_id_regex, _kernel_action_regex), KernelActionHandler),
181 (r"/kernels/%s/iopub" % _kernel_id_regex, ZMQStreamHandler, dict(stream_name='iopub')),
182 (r"/kernels/%s/shell" % _kernel_id_regex, ZMQStreamHandler, dict(stream_name='shell')),
183 (r"/notebooks", NotebookRootHandler),
184 (r"/notebooks/([^/]+)", NotebookHandler)
185 ]
186 settings = dict(
187 template_path=os.path.join(os.path.dirname(__file__), "templates"),
188 static_path=os.path.join(os.path.dirname(__file__), "static"),
189 )
190 web.Application.__init__(self, handlers, **settings)
191
192 self.context = zmq.Context()
193 self.kernel_manager = KernelManager(self.context)
194 self._session_dict = {}
195 self._routers = {}
196
197 #-------------------------------------------------------------------------
198 # Methods for managing kernels and sessions
199 #-------------------------------------------------------------------------
200
201 @property
202 def kernel_ids(self):
203 return self.kernel_manager.kernel_ids
204
205 def start_kernel(self):
206 kernel_id = self.kernel_manager.start_kernel()
207 logging.info("Kernel started: %s" % kernel_id)
208 self.start_session(kernel_id)
209 return kernel_id
210
211 def interrupt_kernel(self, kernel_id):
212 self.kernel_manager.interrupt_kernel(kernel_id)
213 logging.info("Kernel interrupted: %s" % kernel_id)
214
215 def restart_kernel(self, kernel_id):
216 # Create the new kernel first so we can move the clients over.
217 new_kernel_id = self.start_kernel()
218
219 # Copy the clients over to the new routers.
220 old_iopub_router = self.get_router(kernel_id, 'iopub')
221 old_shell_router = self.get_router(kernel_id, 'shell')
222 new_iopub_router = self.get_router(new_kernel_id, 'iopub')
223 new_shell_router = self.get_router(new_kernel_id, 'shell')
224 new_iopub_router.copy_clients(old_iopub_router)
225 new_shell_router.copy_clients(old_shell_router)
226
227 # Now shutdown the old session and the kernel.
228 # TODO: This causes a hard crash in ZMQStream.close, which sets
229 # self.socket to None to hastily. We will need to fix this in PyZMQ
230 # itself. For now, we just leave the old kernel running :(
231 # sm = self.kernel_manager.get_session_manager(kernel_id)
232 # session_id = self._session_dict[kernel_id]
233 # sm.stop_session(session_id)
234 # self.kernel_manager.kill_kernel(kernel_id)
235
236 logging.info("Kernel restarted")
237 return new_kernel_id
238
239 def start_session(self, kernel_id):
240 sm = self.kernel_manager.get_session_manager(kernel_id)
241 session_id = sm.start_session()
242 self._session_dict[kernel_id] = session_id
243 iopub_stream = sm.get_iopub_stream(session_id)
244 shell_stream = sm.get_shell_stream(session_id)
245 iopub_router = IOPubStreamRouter(iopub_stream)
246 shell_router = ShellStreamRouter(shell_stream)
247 self._routers[(kernel_id, session_id, 'iopub')] = iopub_router
248 self._routers[(kernel_id, session_id, 'shell')] = shell_router
249 logging.info("Session started: %s, %s" % (kernel_id, session_id))
250
251 def stop_session(self, kernel_id):
252 # TODO: finish this!
253 sm = self.kernel_manager.get_session_manager(kernel_id)
254 session_id = self._session_dict[kernel_id]
255
256 def get_router(self, kernel_id, stream_name):
257 session_id = self._session_dict[kernel_id]
258 router = self._routers[(kernel_id, session_id, stream_name)]
259 return router
260
261
262 def main():
263 options.parse_command_line()
264 application = NotebookApplication()
265 http_server = httpserver.HTTPServer(application)
266 http_server.listen(options.options.port)
267 print "IPython Notebook running at: http://127.0.0.1:8888"
268 print "The github master of tornado is required to run this server:"
269 print " https://github.com/facebook/tornado/tree/master/tornado"
270 ioloop.IOLoop.instance().start()
271
272
273 if __name__ == "__main__":
274 main()
164
165
275 166
@@ -1,275 +1,131 b''
1 import datetime
2 import json
3 1 import logging
4 2 import os
5 import urllib
6 import uuid
7 from Queue import Queue
8 3
9 4 import zmq
10 5
11 6 # Install the pyzmq ioloop. This has to be done before anything else from
12 7 # tornado is imported.
13 8 from zmq.eventloop import ioloop
14 9 import tornado.ioloop
15 10 tornado.ioloop = ioloop
16 11
17 12 from tornado import httpserver
18 13 from tornado import options
19 14 from tornado import web
20 from tornado import websocket
21 15
22 16 from kernelmanager import KernelManager
17 from handlers import (
18 MainHandler, KernelHandler, KernelActionHandler, ZMQStreamHandler,
19 NotebookRootHandler, NotebookHandler
20 )
21 from routers import IOPubStreamRouter, ShellStreamRouter
23 22
24 23 options.define("port", default=8888, help="run on the given port", type=int)
25 24
26 25 _kernel_id_regex = r"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)"
27 26 _kernel_action_regex = r"(?P<action>restart|interrupt)"
28 27
29 class MainHandler(web.RequestHandler):
30 def get(self):
31 self.render('notebook.html')
32
33
34 class KernelHandler(web.RequestHandler):
35
36 def get(self):
37 self.write(json.dumps(self.application.kernel_ids))
38
39 def post(self):
40 kernel_id = self.application.start_kernel()
41 self.write(json.dumps(kernel_id))
42
43
44 class KernelActionHandler(web.RequestHandler):
45
46 def post(self, kernel_id, action):
47 # TODO: figure out a better way of handling RPC style calls.
48 if action == 'interrupt':
49 self.application.interrupt_kernel(kernel_id)
50 if action == 'restart':
51 new_kernel_id = self.application.restart_kernel(kernel_id)
52 self.write(json.dumps(new_kernel_id))
53
54
55 class ZMQStreamRouter(object):
56
57 def __init__(self, zmq_stream):
58 self.zmq_stream = zmq_stream
59 self._clients = {}
60 self.zmq_stream.on_recv(self._on_zmq_reply)
61
62 def register_client(self, client):
63 client_id = uuid.uuid4()
64 self._clients[client_id] = client
65 return client_id
66
67 def unregister_client(self, client_id):
68 del self._clients[client_id]
69
70 def copy_clients(self, router):
71 # Copy the clients of another router.
72 for client_id, client in router._clients.items():
73 client.router = self
74 self._clients[client_id] = client
75
76
77 class IOPubStreamRouter(ZMQStreamRouter):
78
79 def _on_zmq_reply(self, msg_list):
80 for client_id, client in self._clients.items():
81 for msg in msg_list:
82 client.write_message(msg)
83
84 def forward_unicode(self, client_id, msg):
85 # This is a SUB stream that we should never write to.
86 pass
87
88
89 class ShellStreamRouter(ZMQStreamRouter):
90
91 def __init__(self, zmq_stream):
92 ZMQStreamRouter.__init__(self, zmq_stream)
93 self._request_queue = Queue()
94
95 def _on_zmq_reply(self, msg_list):
96 client_id = self._request_queue.get(block=False)
97 client = self._clients.get(client_id)
98 if client is not None:
99 for msg in msg_list:
100 client.write_message(msg)
101
102 def forward_unicode(self, client_id, msg):
103 self._request_queue.put(client_id)
104 self.zmq_stream.send_unicode(msg)
105
106
107 class ZMQStreamHandler(websocket.WebSocketHandler):
108
109 def initialize(self, stream_name):
110 self.stream_name = stream_name
111
112 def open(self, kernel_id):
113 self.router = self.application.get_router(kernel_id, self.stream_name)
114 self.client_id = self.router.register_client(self)
115 logging.info("Connection open: %s, %s" % (kernel_id, self.client_id))
116
117 def on_message(self, msg):
118 self.router.forward_unicode(self.client_id, msg)
119
120 def on_close(self):
121 self.router.unregister_client(self.client_id)
122 logging.info("Connection closed: %s" % self.client_id)
123
124
125 class NotebookRootHandler(web.RequestHandler):
126
127 def get(self):
128 files = os.listdir(os.getcwd())
129 files = [file for file in files if file.endswith(".ipynb")]
130 self.write(json.dumps(files))
131
132
133 class NotebookHandler(web.RequestHandler):
134
135 SUPPORTED_METHODS = ("GET", "DELETE", "PUT")
136
137 def find_path(self, filename):
138 filename = urllib.unquote(filename)
139 if not filename.endswith('.ipynb'):
140 raise web.HTTPError(400)
141 path = os.path.join(os.getcwd(), filename)
142 return path
143
144 def get(self, filename):
145 path = self.find_path(filename)
146 if not os.path.isfile(path):
147 raise web.HTTPError(404)
148 info = os.stat(path)
149 self.set_header("Content-Type", "application/unknown")
150 self.set_header("Last-Modified", datetime.datetime.utcfromtimestamp(
151 info.st_mtime))
152 f = open(path, "r")
153 try:
154 self.finish(f.read())
155 finally:
156 f.close()
157
158 def put(self, filename):
159 path = self.find_path(filename)
160 f = open(path, "w")
161 f.write(self.request.body)
162 f.close()
163 self.finish()
164
165 def delete(self, filename):
166 path = self.find_path(filename)
167 if not os.path.isfile(path):
168 raise web.HTTPError(404)
169 os.unlink(path)
170 self.set_status(204)
171 self.finish()
172 28
173 29
174 30 class NotebookApplication(web.Application):
175 31
176 32 def __init__(self):
177 33 handlers = [
178 34 (r"/", MainHandler),
179 35 (r"/kernels", KernelHandler),
180 36 (r"/kernels/%s/%s" % (_kernel_id_regex, _kernel_action_regex), KernelActionHandler),
181 37 (r"/kernels/%s/iopub" % _kernel_id_regex, ZMQStreamHandler, dict(stream_name='iopub')),
182 38 (r"/kernels/%s/shell" % _kernel_id_regex, ZMQStreamHandler, dict(stream_name='shell')),
183 39 (r"/notebooks", NotebookRootHandler),
184 40 (r"/notebooks/([^/]+)", NotebookHandler)
185 41 ]
186 42 settings = dict(
187 43 template_path=os.path.join(os.path.dirname(__file__), "templates"),
188 44 static_path=os.path.join(os.path.dirname(__file__), "static"),
189 45 )
190 46 web.Application.__init__(self, handlers, **settings)
191 47
192 48 self.context = zmq.Context()
193 49 self.kernel_manager = KernelManager(self.context)
194 50 self._session_dict = {}
195 51 self._routers = {}
196 52
197 53 #-------------------------------------------------------------------------
198 54 # Methods for managing kernels and sessions
199 55 #-------------------------------------------------------------------------
200 56
201 57 @property
202 58 def kernel_ids(self):
203 59 return self.kernel_manager.kernel_ids
204 60
205 61 def start_kernel(self):
206 62 kernel_id = self.kernel_manager.start_kernel()
207 63 logging.info("Kernel started: %s" % kernel_id)
208 64 self.start_session(kernel_id)
209 65 return kernel_id
210 66
211 67 def interrupt_kernel(self, kernel_id):
212 68 self.kernel_manager.interrupt_kernel(kernel_id)
213 69 logging.info("Kernel interrupted: %s" % kernel_id)
214 70
215 71 def restart_kernel(self, kernel_id):
216 72 # Create the new kernel first so we can move the clients over.
217 73 new_kernel_id = self.start_kernel()
218 74
219 75 # Copy the clients over to the new routers.
220 76 old_iopub_router = self.get_router(kernel_id, 'iopub')
221 77 old_shell_router = self.get_router(kernel_id, 'shell')
222 78 new_iopub_router = self.get_router(new_kernel_id, 'iopub')
223 79 new_shell_router = self.get_router(new_kernel_id, 'shell')
224 80 new_iopub_router.copy_clients(old_iopub_router)
225 81 new_shell_router.copy_clients(old_shell_router)
226 82
227 83 # Now shutdown the old session and the kernel.
228 84 # TODO: This causes a hard crash in ZMQStream.close, which sets
229 85 # self.socket to None to hastily. We will need to fix this in PyZMQ
230 86 # itself. For now, we just leave the old kernel running :(
231 87 # sm = self.kernel_manager.get_session_manager(kernel_id)
232 88 # session_id = self._session_dict[kernel_id]
233 89 # sm.stop_session(session_id)
234 90 # self.kernel_manager.kill_kernel(kernel_id)
235 91
236 92 logging.info("Kernel restarted")
237 93 return new_kernel_id
238 94
239 95 def start_session(self, kernel_id):
240 96 sm = self.kernel_manager.get_session_manager(kernel_id)
241 97 session_id = sm.start_session()
242 98 self._session_dict[kernel_id] = session_id
243 99 iopub_stream = sm.get_iopub_stream(session_id)
244 100 shell_stream = sm.get_shell_stream(session_id)
245 101 iopub_router = IOPubStreamRouter(iopub_stream)
246 102 shell_router = ShellStreamRouter(shell_stream)
247 103 self._routers[(kernel_id, session_id, 'iopub')] = iopub_router
248 104 self._routers[(kernel_id, session_id, 'shell')] = shell_router
249 105 logging.info("Session started: %s, %s" % (kernel_id, session_id))
250 106
251 107 def stop_session(self, kernel_id):
252 108 # TODO: finish this!
253 109 sm = self.kernel_manager.get_session_manager(kernel_id)
254 110 session_id = self._session_dict[kernel_id]
255 111
256 112 def get_router(self, kernel_id, stream_name):
257 113 session_id = self._session_dict[kernel_id]
258 114 router = self._routers[(kernel_id, session_id, stream_name)]
259 115 return router
260 116
261 117
262 118 def main():
263 119 options.parse_command_line()
264 120 application = NotebookApplication()
265 121 http_server = httpserver.HTTPServer(application)
266 122 http_server.listen(options.options.port)
267 123 print "IPython Notebook running at: http://127.0.0.1:8888"
268 124 print "The github master of tornado is required to run this server:"
269 125 print " https://github.com/facebook/tornado/tree/master/tornado"
270 126 ioloop.IOLoop.instance().start()
271 127
272 128
273 129 if __name__ == "__main__":
274 130 main()
275 131
General Comments 0
You need to be logged in to leave comments. Login now