##// END OF EJS Templates
Basic server for htmlnotebook working.
Brian Granger -
Show More
@@ -1,98 +1,102 b''
1 1 import signal
2 2 import sys
3 import uuid
4 3
5 4 from IPython.zmq.ipkernel import launch_kernel
6 5 from session import SessionManager
7 6
8 7
8 class DuplicateKernelError(Exception):
9 pass
10
11
9 12 class KernelManager(object):
10 13
11 14 ip = '127.0.0.1'
12 15
13 16 def __init__(self, context):
14 17 self.context = context
15 18 self._kernels = {}
16 19
17 20 @property
18 21 def kernel_ids(self):
19 22 return self._kernels.keys()
20 23
21 24 def __len__(self):
22 25 return len(self.kernel_ids)
23 26
24 27 def __contains__(self, kernel_id):
25 28 if kernel_id in self.kernel_ids:
26 29 return True
27 30 else:
28 31 return False
29 32
30 def start_kernel(self):
31 kid = str(uuid.uuid4())
33 def start_kernel(self, kernel_id):
34 if kernel_id in self._kernels:
35 raise DuplicateKernelError("Kernel already exists: %s" % kernel_id)
32 36 (process, shell_port, iopub_port, stdin_port, hb_port) = launch_kernel()
33 37 d = dict(
34 38 process = process,
35 39 stdin_port = stdin_port,
36 40 iopub_port = iopub_port,
37 41 shell_port = shell_port,
38 42 hb_port = hb_port,
39 session_manager = SessionManager(self, kid, self.context)
43 session_manager = SessionManager(self, kernel_id, self.context)
40 44 )
41 self._kernels[kid] = d
42 return kid
45 self._kernels[kernel_id] = d
46 return kernel_id
43 47
44 48 def kill_kernel(self, kernel_id):
45 49 kernel_process = self.get_kernel_process(kernel_id)
46 50 if kernel_process is not None:
47 51 # Attempt to kill the kernel.
48 52 try:
49 53 kernel_process.kill()
50 54 except OSError, e:
51 55 # In Windows, we will get an Access Denied error if the process
52 56 # has already terminated. Ignore it.
53 57 if not (sys.platform == 'win32' and e.winerror == 5):
54 58 raise
55 59 del self._kernels[kernel_id]
56 60
57 61 def interrupt_kernel(self, kernel_id):
58 62 kernel_process = self.get_kernel_process(kernel_id)
59 63 if kernel_process is not None:
60 64 if sys.platform == 'win32':
61 65 from parentpoller import ParentPollerWindows as Poller
62 66 Poller.send_interrupt(kernel_process.win32_interrupt_event)
63 67 else:
64 68 kernel_process.send_signal(signal.SIGINT)
65 69
66 70 def signal_kernel(self, kernel_id, signum):
67 71 """ Sends a signal to the kernel. Note that since only SIGTERM is
68 72 supported on Windows, this function is only useful on Unix systems.
69 73 """
70 74 kernel_process = self.get_kernel_process(kernel_id)
71 75 if kernel_process is not None:
72 76 kernel_process.send_signal(signum)
73 77
74 78 def get_kernel_process(self, kernel_id):
75 79 d = self._kernels.get(kernel_id)
76 80 if d is not None:
77 81 return d['process']
78 82 else:
79 83 raise KeyError("Kernel with id not found: %s" % kernel_id)
80 84
81 85 def get_kernel_ports(self, kernel_id):
82 86 d = self._kernels.get(kernel_id)
83 87 if d is not None:
84 88 dcopy = d.copy()
85 89 dcopy.pop('process')
86 90 return dcopy
87 91 else:
88 92 raise KeyError("Kernel with id not found: %s" % kernel_id)
89 93
90 94 def get_session_manager(self, kernel_id):
91 95 d = self._kernels.get(kernel_id)
92 96 if d is not None:
93 97 return d['session_manager']
94 98 else:
95 99 raise KeyError("Kernel with id not found: %s" % kernel_id)
96 100
97 101
98 102
@@ -1,124 +1,133 b''
1 1 import json
2 2 import logging
3 3 import os
4 import uuid
5 4
6 5 import zmq
7 6
8 7 # Install the pyzmq ioloop. This has to be done before anything else from
9 8 # tornado is imported.
10 from zmq.eventloop.zmqstream import ZMQStream
11 9 from zmq.eventloop import ioloop
12 10 import tornado.ioloop
13 11 tornado.ioloop = ioloop
14 12
15 13 from tornado import httpserver
16 14 from tornado import options
17 15 from tornado import web
18 16 from tornado import websocket
19 17
20 18 from kernelmanager import KernelManager
21 19
22 20 options.define("port", default=8888, help="run on the given port", type=int)
23 21
24 _kernel_id_regex = r"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)"
25 _session_id_regex = r"(?P<session_id>\w+)"
22 _session_id_regex = r"(?P<session_id>\w+-\w+-\w+-\w+-\w+)"
23 _kernel_id_regex = r"(?P<kernel_id>\w+)"
26 24
27 25
28 26 class MainHandler(web.RequestHandler):
29 27 def get(self):
30 28 self.render('notebook.html')
31 29
32 30
33 class KernelHandler(web.RequestHandler):
31 class BaseKernelHandler(object):
32
33 def get_kernel(self):
34 return self.application.kernel_manager
35
36 def get_session(self, kernel_id):
37 km = self.get_kernel()
38 sm = km.get_session_manager(kernel_id)
39 return sm
40
41
42 class KernelHandler(web.RequestHandler, BaseKernelHandler):
34 43
35 44 def get(self):
36 self.write(json.dumps(self.application.kernel_manager.kernel_ids))
45 self.write(json.dumps(self.get_kernel().kernel_ids))
46
47 def post(self, *args, **kwargs):
48 kernel_id = kwargs['kernel_id']
49 self.get_kernel().start_kernel(kernel_id)
50 logging.info("Starting kernel: %s" % kernel_id)
51 self.write(json.dumps(kernel_id))
37 52
38 def post(self):
39 kid = self.application.kernel_manager.start_kernel()
40 logging.info("Starting kernel: %s" % kid)
41 self.write(json.dumps(kid))
42 53
54 class SessionHandler(web.RequestHandler, BaseKernelHandler):
43 55
44 class SessionHandler(web.RequestHandler):
56 def get(self, *args, **kwargs):
57 kernel_id = kwargs['kernel_id']
58 self.write(json.dumps(self.get_session(kernel_id).session_ids))
45 59
46 60 def post(self, *args, **kwargs):
47 61 kernel_id = kwargs['kernel_id']
48 session_id = kwargs['session_id']
62 sm = self.get_session(kernel_id)
63 session_id = sm.start_session()
49 64 logging.info("Starting session: %s, %s" % (kernel_id,session_id))
50 km = self.application.kernel_manager
51 sm = km.get_session_manager(kernel_id)
52 sm.start_session(session_id)
53 self.finish()
65 self.write(json.dumps(session_id))
54 66
55 67
56 class ZMQStreamHandler(websocket.WebSocketHandler):
68 class ZMQStreamHandler(websocket.WebSocketHandler, BaseKernelHandler):
57 69
58 70 stream_name = ''
59 71
60 72 def open(self, *args, **kwargs):
61 73 kernel_id = kwargs['kernel_id']
62 74 session_id = kwargs['session_id']
63 75 logging.info("Connection open: %s, %s" % (kernel_id,session_id))
64 sm = self.application.kernel_manager.get_session_manager(kernel_id)
76 sm = self.get_session(kernel_id)
65 77 method_name = "get_%s_stream" % self.stream_name
66 78 method = getattr(sm, method_name)
67 79 self.zmq_stream = method(session_id)
68 80 self.zmq_stream.on_recv(self._on_zmq_reply)
69 self.session_manager = sm
70 self.session_id = session_id
71 81
72 82 def on_message(self, msg):
73 83 logging.info("Message received: %r" % msg)
74 self.zmq_stream.send(msg)
84 self.zmq_stream.send_unicode(msg)
75 85
76 86 def on_close(self):
77 logging.info("Connection closed: %s, %s" % (kernel_id,session_id))
78 87 self.zmq_stream.close()
79 88
80 89 def _on_zmq_reply(self, msg):
81 90 logging.info("Message reply: %r" % msg)
82 91 self.write_message(msg)
83 92
84 93
85 94 class IOPubStreamHandler(ZMQStreamHandler):
86 95
87 96 stream_name = 'iopub'
88 97
89 98
90 99 class ShellStreamHandler(ZMQStreamHandler):
91 100
92 101 stream_name = 'shell'
93 102
94 103
95 104 class NotebookApplication(web.Application):
96 105
97 106 def __init__(self):
98 107 handlers = [
99 108 (r"/", MainHandler),
100 (r"/kernels", KernelHandler),
101 (r"/kernels/%s/sessions/%s" % (_kernel_id_regex,_session_id_regex), SessionHandler),
109 (r"/kernels/%s" % (_kernel_id_regex,), KernelHandler),
110 (r"/kernels/%s/sessions" % (_kernel_id_regex,), SessionHandler),
102 111 (r"/kernels/%s/sessions/%s/iopub" % (_kernel_id_regex,_session_id_regex), IOPubStreamHandler),
103 112 (r"/kernels/%s/sessions/%s/shell" % (_kernel_id_regex,_session_id_regex), ShellStreamHandler),
104 113 ]
105 114 settings = dict(
106 115 template_path=os.path.join(os.path.dirname(__file__), "templates"),
107 116 static_path=os.path.join(os.path.dirname(__file__), "static"),
108 117 )
109 118 web.Application.__init__(self, handlers, **settings)
110 119 self.context = zmq.Context()
111 120 self.kernel_manager = KernelManager(self.context)
112 121
113 122
114 123 def main():
115 124 options.parse_command_line()
116 125 application = NotebookApplication()
117 126 http_server = httpserver.HTTPServer(application)
118 127 http_server.listen(options.options.port)
119 128 ioloop.IOLoop.instance().start()
120 129
121 130
122 131 if __name__ == "__main__":
123 132 main()
124 133
@@ -1,56 +1,72 b''
1 1 import logging
2 import uuid
2 3
3 4 import zmq
4 5 from zmq.eventloop.zmqstream import ZMQStream
5 6
6 7
7 8 class SessionManager(object):
8 9
9 10 def __init__(self, kernel_manager, kernel_id, context):
10 11 self.context = context
11 12 self.kernel_manager = kernel_manager
12 13 self.kernel_id = kernel_id
13 14 self._sessions = {}
14 15
15 16 def __del__(self):
16 17 self.stop_all()
17 18
18 def start_session(self, session_id):
19 @property
20 def session_ids(self):
21 return self._session.keys()
22
23 def __len__(self):
24 return len(self.session_ids)
25
26 def __contains__(self, session_id):
27 if session_id in self.session_ids:
28 return True
29 else:
30 return False
31
32 def start_session(self):
33 session_id = str(uuid.uuid4())
19 34 ports = self.kernel_manager.get_kernel_ports(self.kernel_id)
20 35 iopub_stream = self.create_connected_stream(ports['iopub_port'], zmq.SUB)
21 36 shell_stream = self.create_connected_stream(ports['shell_port'], zmq.XREQ)
22 37 self._sessions[session_id] = dict(
23 38 iopub_stream = iopub_stream,
24 39 shell_stream = shell_stream
25 40 )
41 return session_id
26 42
27 43 def stop_session(self, session_id):
28 44 session_dict = self._sessions.get(session_id)
29 45 if session_dict is not None:
30 46 for name, stream in session_dict.items():
31 47 stream.close()
32 48 del self._sessions[session_id]
33 49
34 50 def stop_all(self):
35 51 for session_id in self._sessions.keys():
36 52 self.stop_session(session_id)
37 53
38 54 def create_connected_stream(self, port, socket_type):
39 55 sock = self.context.socket(socket_type)
40 56 addr = "tcp://%s:%i" % (self.kernel_manager.ip, port)
41 57 logging.info("Connecting to: %s" % addr)
42 58 sock.connect(addr)
43 59 return ZMQStream(sock)
44 60
45 61 def get_stream(self, session_id, stream_name):
46 62 session_dict = self._sessions.get(session_id)
47 63 if session_dict is not None:
48 64 return session_dict[stream_name]
49 65 else:
50 66 raise KeyError("Session with id not found: %s" % session_id)
51 67
52 68 def get_iopub_stream(self, session_id):
53 69 return self.get_stream(session_id, 'iopub_stream')
54 70
55 71 def get_shell_stream(self, session_id):
56 72 return self.get_stream(session_id, 'shell_stream')
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now