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