Show More
@@ -13,7 +13,7 b' from tornado import websocket' | |||||
13 |
|
13 | |||
14 |
|
14 | |||
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 |
# |
|
16 | # Top-level handlers | |
17 | #----------------------------------------------------------------------------- |
|
17 | #----------------------------------------------------------------------------- | |
18 |
|
18 | |||
19 |
|
19 | |||
@@ -38,25 +38,45 b' class NamedNotebookHandler(web.RequestHandler):' | |||||
38 | self.render('notebook.html', notebook_id=notebook_id) |
|
38 | self.render('notebook.html', notebook_id=notebook_id) | |
39 |
|
39 | |||
40 |
|
40 | |||
41 | class KernelHandler(web.RequestHandler): |
|
41 | #----------------------------------------------------------------------------- | |
|
42 | # Kernel handlers | |||
|
43 | #----------------------------------------------------------------------------- | |||
|
44 | ||||
|
45 | ||||
|
46 | class MainKernelHandler(web.RequestHandler): | |||
42 |
|
47 | |||
43 | def get(self): |
|
48 | def get(self): | |
44 | self.finish(json.dumps(self.application.kernel_ids)) |
|
49 | rkm = self.application.routing_kernel_manager | |
|
50 | self.finish(json.dumps(rkm.kernel_ids)) | |||
45 |
|
51 | |||
46 | def post(self): |
|
52 | def post(self): | |
47 |
|
|
53 | rkm = self.application.routing_kernel_manager | |
|
54 | notebook_id = self.get_argument('notebook', default=None) | |||
|
55 | kernel_id = rkm.start_kernel(notebook_id) | |||
48 | self.set_header('Location', '/'+kernel_id) |
|
56 | self.set_header('Location', '/'+kernel_id) | |
49 | self.finish(json.dumps(kernel_id)) |
|
57 | self.finish(json.dumps(kernel_id)) | |
50 |
|
58 | |||
51 |
|
59 | |||
|
60 | class KernelHandler(web.RequestHandler): | |||
|
61 | ||||
|
62 | SUPPORTED_METHODS = ('DELETE') | |||
|
63 | ||||
|
64 | def delete(self, kernel_id): | |||
|
65 | rkm = self.application.routing_kernel_manager | |||
|
66 | self.kill_kernel(kernel_id) | |||
|
67 | self.set_status(204) | |||
|
68 | self.finish() | |||
|
69 | ||||
|
70 | ||||
52 | class KernelActionHandler(web.RequestHandler): |
|
71 | class KernelActionHandler(web.RequestHandler): | |
53 |
|
72 | |||
54 | def post(self, kernel_id, action): |
|
73 | def post(self, kernel_id, action): | |
55 | # TODO: figure out a better way of handling RPC style calls. |
|
74 | rkm = self.application.routing_kernel_manager | |
56 | if action == 'interrupt': |
|
75 | if action == 'interrupt': | |
57 |
|
|
76 | rkm.interrupt_kernel(kernel_id) | |
|
77 | self.set_status(204) | |||
58 | if action == 'restart': |
|
78 | if action == 'restart': | |
59 |
new_kernel_id = |
|
79 | new_kernel_id = rkm.restart_kernel(kernel_id) | |
60 | self.write(json.dumps(new_kernel_id)) |
|
80 | self.write(json.dumps(new_kernel_id)) | |
61 | self.finish() |
|
81 | self.finish() | |
62 |
|
82 | |||
@@ -67,7 +87,8 b' class ZMQStreamHandler(websocket.WebSocketHandler):' | |||||
67 | self.stream_name = stream_name |
|
87 | self.stream_name = stream_name | |
68 |
|
88 | |||
69 | def open(self, kernel_id): |
|
89 | def open(self, kernel_id): | |
70 |
|
|
90 | rkm = self.application.routing_kernel_manager | |
|
91 | self.router = rkm.get_router(kernel_id, self.stream_name) | |||
71 | self.client_id = self.router.register_client(self) |
|
92 | self.client_id = self.router.register_client(self) | |
72 | logging.info("Connection open: %s, %s" % (kernel_id, self.client_id)) |
|
93 | logging.info("Connection open: %s, %s" % (kernel_id, self.client_id)) | |
73 |
|
94 | |||
@@ -79,6 +100,10 b' class ZMQStreamHandler(websocket.WebSocketHandler):' | |||||
79 | logging.info("Connection closed: %s" % self.client_id) |
|
100 | logging.info("Connection closed: %s" % self.client_id) | |
80 |
|
101 | |||
81 |
|
102 | |||
|
103 | #----------------------------------------------------------------------------- | |||
|
104 | # Notebook web service handlers | |||
|
105 | #----------------------------------------------------------------------------- | |||
|
106 | ||||
82 | class NotebookRootHandler(web.RequestHandler): |
|
107 | class NotebookRootHandler(web.RequestHandler): | |
83 |
|
108 | |||
84 | def get(self): |
|
109 | def get(self): |
@@ -17,9 +17,13 b' import uuid' | |||||
17 |
|
17 | |||
18 | import zmq |
|
18 | import zmq | |
19 |
|
19 | |||
|
20 | from tornado import web | |||
|
21 | ||||
|
22 | from .routers import IOPubStreamRouter, ShellStreamRouter | |||
|
23 | ||||
20 | from IPython.config.configurable import LoggingConfigurable |
|
24 | from IPython.config.configurable import LoggingConfigurable | |
21 | from IPython.zmq.ipkernel import launch_kernel |
|
25 | from IPython.zmq.ipkernel import launch_kernel | |
22 | from IPython.utils.traitlets import Instance, Dict |
|
26 | from IPython.utils.traitlets import Instance, Dict, List, Unicode | |
23 |
|
27 | |||
24 | #----------------------------------------------------------------------------- |
|
28 | #----------------------------------------------------------------------------- | |
25 | # Classes |
|
29 | # Classes | |
@@ -55,7 +59,7 b' class KernelManager(LoggingConfigurable):' | |||||
55 |
|
59 | |||
56 | def start_kernel(self, **kwargs): |
|
60 | def start_kernel(self, **kwargs): | |
57 | """Start a new kernel.""" |
|
61 | """Start a new kernel.""" | |
58 |
kernel_id = |
|
62 | kernel_id = unicode(uuid.uuid4()) | |
59 | (process, shell_port, iopub_port, stdin_port, hb_port) = launch_kernel(**kwargs) |
|
63 | (process, shell_port, iopub_port, stdin_port, hb_port) = launch_kernel(**kwargs) | |
60 | # Store the information for contacting the kernel. This assumes the kernel is |
|
64 | # Store the information for contacting the kernel. This assumes the kernel is | |
61 | # running on localhost. |
|
65 | # running on localhost. | |
@@ -186,3 +190,117 b' class KernelManager(LoggingConfigurable):' | |||||
186 | config=self.config, context=self.context, log=self.log |
|
190 | config=self.config, context=self.context, log=self.log | |
187 | ) |
|
191 | ) | |
188 |
|
192 | |||
|
193 | ||||
|
194 | class RoutingKernelManager(LoggingConfigurable): | |||
|
195 | """A KernelManager that handles WebSocket routing and HTTP error handling""" | |||
|
196 | ||||
|
197 | kernel_argv = List(Unicode) | |||
|
198 | kernel_manager = Instance(KernelManager) | |||
|
199 | ||||
|
200 | _routers = Dict() | |||
|
201 | _session_dict = Dict() | |||
|
202 | _notebook_mapping = Dict() | |||
|
203 | ||||
|
204 | #------------------------------------------------------------------------- | |||
|
205 | # Methods for managing kernels and sessions | |||
|
206 | #------------------------------------------------------------------------- | |||
|
207 | ||||
|
208 | @property | |||
|
209 | def kernel_ids(self): | |||
|
210 | return self.kernel_manager.kernel_ids | |||
|
211 | ||||
|
212 | def notebook_for_kernel(self, kernel_id): | |||
|
213 | notebook_ids = [k for k, v in self._notebook_mapping.iteritems() if v == kernel_id] | |||
|
214 | if len(notebook_ids) == 1: | |||
|
215 | return notebook_ids[0] | |||
|
216 | else: | |||
|
217 | return None | |||
|
218 | ||||
|
219 | def delete_mapping_for_kernel(self, kernel_id): | |||
|
220 | notebook_id = self.notebook_for_kernel(kernel_id) | |||
|
221 | if notebook_id is not None: | |||
|
222 | del self._notebook_mapping[notebook_id] | |||
|
223 | ||||
|
224 | def start_kernel(self, notebook_id=None): | |||
|
225 | self.log.info | |||
|
226 | kernel_id = self._notebook_mapping.get(notebook_id) | |||
|
227 | if kernel_id is None: | |||
|
228 | kwargs = dict() | |||
|
229 | kwargs['extra_arguments'] = self.kernel_argv | |||
|
230 | kernel_id = self.kernel_manager.start_kernel(**kwargs) | |||
|
231 | if notebook_id is not None: | |||
|
232 | self._notebook_mapping[notebook_id] = kernel_id | |||
|
233 | self.log.info("Kernel started for notebook %s: %s" % (notebook_id,kernel_id)) | |||
|
234 | self.log.debug("Kernel args: %r" % kwargs) | |||
|
235 | self.start_session_manager(kernel_id) | |||
|
236 | else: | |||
|
237 | self.log.info("Using existing kernel: %s" % kernel_id) | |||
|
238 | return kernel_id | |||
|
239 | ||||
|
240 | def start_session_manager(self, kernel_id): | |||
|
241 | sm = self.kernel_manager.create_session_manager(kernel_id) | |||
|
242 | self._session_dict[kernel_id] = sm | |||
|
243 | iopub_stream = sm.get_iopub_stream() | |||
|
244 | shell_stream = sm.get_shell_stream() | |||
|
245 | iopub_router = IOPubStreamRouter( | |||
|
246 | zmq_stream=iopub_stream, session=sm.session, config=self.config | |||
|
247 | ) | |||
|
248 | shell_router = ShellStreamRouter( | |||
|
249 | zmq_stream=shell_stream, session=sm.session, config=self.config | |||
|
250 | ) | |||
|
251 | self._routers[(kernel_id, 'iopub')] = iopub_router | |||
|
252 | self._routers[(kernel_id, 'shell')] = shell_router | |||
|
253 | ||||
|
254 | def kill_kernel(self, kernel_id): | |||
|
255 | if kernel_id not in self.kernel_manager: | |||
|
256 | raise web.HTTPError(404) | |||
|
257 | try: | |||
|
258 | sm = self._session_dict.pop(kernel_id) | |||
|
259 | except KeyError: | |||
|
260 | raise web.HTTPError(404) | |||
|
261 | sm.stop() | |||
|
262 | self.kernel_manager.kill_kernel(kernel_id) | |||
|
263 | self.delete_mapping_for_kernel(kernel_id) | |||
|
264 | self.log.info("Kernel killed: %s" % kernel_id) | |||
|
265 | ||||
|
266 | def interrupt_kernel(self, kernel_id): | |||
|
267 | if kernel_id not in self.kernel_manager: | |||
|
268 | raise web.HTTPError(404) | |||
|
269 | self.kernel_manager.interrupt_kernel(kernel_id) | |||
|
270 | self.log.debug("Kernel interrupted: %s" % kernel_id) | |||
|
271 | ||||
|
272 | def restart_kernel(self, kernel_id): | |||
|
273 | if kernel_id not in self.kernel_manager: | |||
|
274 | raise web.HTTPError(404) | |||
|
275 | ||||
|
276 | # Get the notebook_id to preserve the kernel/notebook association | |||
|
277 | notebook_id = self.notebook_for_kernel(kernel_id) | |||
|
278 | # Create the new kernel first so we can move the clients over. | |||
|
279 | new_kernel_id = self.start_kernel() | |||
|
280 | ||||
|
281 | # Copy the clients over to the new routers. | |||
|
282 | old_iopub_router = self.get_router(kernel_id, 'iopub') | |||
|
283 | old_shell_router = self.get_router(kernel_id, 'shell') | |||
|
284 | new_iopub_router = self.get_router(new_kernel_id, 'iopub') | |||
|
285 | new_shell_router = self.get_router(new_kernel_id, 'shell') | |||
|
286 | new_iopub_router.copy_clients(old_iopub_router) | |||
|
287 | new_shell_router.copy_clients(old_shell_router) | |||
|
288 | ||||
|
289 | # Now shutdown the old session and the kernel. | |||
|
290 | # TODO: This causes a hard crash in ZMQStream.close, which sets | |||
|
291 | # self.socket to None to hastily. We will need to fix this in PyZMQ | |||
|
292 | # itself. For now, we just leave the old kernel running :( | |||
|
293 | # Maybe this is fixed now, but nothing was changed really. | |||
|
294 | self.kill_kernel(kernel_id) | |||
|
295 | ||||
|
296 | # Now save the new kernel/notebook association. We have to save it | |||
|
297 | # after the old kernel is killed as that will delete the mapping. | |||
|
298 | self._notebook_mapping[notebook_id] = kernel_id | |||
|
299 | ||||
|
300 | self.log.debug("Kernel restarted: %s -> %s" % (kernel_id, new_kernel_id)) | |||
|
301 | return new_kernel_id | |||
|
302 | ||||
|
303 | def get_router(self, kernel_id, stream_name): | |||
|
304 | router = self._routers[(kernel_id, stream_name)] | |||
|
305 | return router | |||
|
306 |
@@ -27,14 +27,13 b' tornado.ioloop = ioloop' | |||||
27 | from tornado import httpserver |
|
27 | from tornado import httpserver | |
28 | from tornado import web |
|
28 | from tornado import web | |
29 |
|
29 | |||
30 | from .kernelmanager import KernelManager |
|
30 | from .kernelmanager import KernelManager, RoutingKernelManager | |
31 | from .sessionmanager import SessionManager |
|
31 | from .sessionmanager import SessionManager | |
32 | from .handlers import ( |
|
32 | from .handlers import ( | |
33 | NBBrowserHandler, NewHandler, NamedNotebookHandler, |
|
33 | NBBrowserHandler, NewHandler, NamedNotebookHandler, | |
34 | KernelHandler, KernelActionHandler, ZMQStreamHandler, |
|
34 | MainKernelHandler, KernelHandler, KernelActionHandler, ZMQStreamHandler, | |
35 | NotebookRootHandler, NotebookHandler |
|
35 | NotebookRootHandler, NotebookHandler | |
36 | ) |
|
36 | ) | |
37 | from .routers import IOPubStreamRouter, ShellStreamRouter |
|
|||
38 | from .notebookmanager import NotebookManager |
|
37 | from .notebookmanager import NotebookManager | |
39 |
|
38 | |||
40 | from IPython.core.application import BaseIPythonApplication |
|
39 | from IPython.core.application import BaseIPythonApplication | |
@@ -65,12 +64,13 b" LOCALHOST = '127.0.0.1'" | |||||
65 |
|
64 | |||
66 | class NotebookWebApplication(web.Application): |
|
65 | class NotebookWebApplication(web.Application): | |
67 |
|
66 | |||
68 |
def __init__(self, kernel_manager, log |
|
67 | def __init__(self, routing_kernel_manager, notebook_manager, log): | |
69 | handlers = [ |
|
68 | handlers = [ | |
70 | (r"/", NBBrowserHandler), |
|
69 | (r"/", NBBrowserHandler), | |
71 | (r"/new", NewHandler), |
|
70 | (r"/new", NewHandler), | |
72 | (r"/%s" % _notebook_id_regex, NamedNotebookHandler), |
|
71 | (r"/%s" % _notebook_id_regex, NamedNotebookHandler), | |
73 | (r"/kernels", KernelHandler), |
|
72 | (r"/kernels", MainKernelHandler), | |
|
73 | (r"/kernels/%s" % _kernel_id_regex, KernelHandler), | |||
74 | (r"/kernels/%s/%s" % (_kernel_id_regex, _kernel_action_regex), KernelActionHandler), |
|
74 | (r"/kernels/%s/%s" % (_kernel_id_regex, _kernel_action_regex), KernelActionHandler), | |
75 | (r"/kernels/%s/iopub" % _kernel_id_regex, ZMQStreamHandler, dict(stream_name='iopub')), |
|
75 | (r"/kernels/%s/iopub" % _kernel_id_regex, ZMQStreamHandler, dict(stream_name='iopub')), | |
76 | (r"/kernels/%s/shell" % _kernel_id_regex, ZMQStreamHandler, dict(stream_name='shell')), |
|
76 | (r"/kernels/%s/shell" % _kernel_id_regex, ZMQStreamHandler, dict(stream_name='shell')), | |
@@ -83,81 +83,9 b' class NotebookWebApplication(web.Application):' | |||||
83 | ) |
|
83 | ) | |
84 | web.Application.__init__(self, handlers, **settings) |
|
84 | web.Application.__init__(self, handlers, **settings) | |
85 |
|
85 | |||
86 | self.kernel_manager = kernel_manager |
|
86 | self.routing_kernel_manager = routing_kernel_manager | |
87 | self.log = log |
|
87 | self.log = log | |
88 | self.kernel_argv = kernel_argv |
|
88 | self.notebook_manager = notebook_manager | |
89 | self.config = config |
|
|||
90 | self._routers = {} |
|
|||
91 | self._session_dict = {} |
|
|||
92 | self.notebook_manager = NotebookManager(config=self.config) |
|
|||
93 |
|
||||
94 | #------------------------------------------------------------------------- |
|
|||
95 | # Methods for managing kernels and sessions |
|
|||
96 | #------------------------------------------------------------------------- |
|
|||
97 |
|
||||
98 | @property |
|
|||
99 | def kernel_ids(self): |
|
|||
100 | return self.kernel_manager.kernel_ids |
|
|||
101 |
|
||||
102 | def start_kernel(self): |
|
|||
103 | kwargs = dict() |
|
|||
104 | kwargs['extra_arguments'] = self.kernel_argv |
|
|||
105 | kernel_id = self.kernel_manager.start_kernel(**kwargs) |
|
|||
106 | self.log.info("Kernel started: %s" % kernel_id) |
|
|||
107 | self.log.debug("Kernel args: %r" % kwargs) |
|
|||
108 | self.start_session_manager(kernel_id) |
|
|||
109 | return kernel_id |
|
|||
110 |
|
||||
111 | def start_session_manager(self, kernel_id): |
|
|||
112 | sm = self.kernel_manager.create_session_manager(kernel_id) |
|
|||
113 | self._session_dict[kernel_id] = sm |
|
|||
114 | iopub_stream = sm.get_iopub_stream() |
|
|||
115 | shell_stream = sm.get_shell_stream() |
|
|||
116 | iopub_router = IOPubStreamRouter( |
|
|||
117 | zmq_stream=iopub_stream, session=sm.session, config=self.config |
|
|||
118 | ) |
|
|||
119 | shell_router = ShellStreamRouter( |
|
|||
120 | zmq_stream=shell_stream, session=sm.session, config=self.config |
|
|||
121 | ) |
|
|||
122 | self._routers[(kernel_id, 'iopub')] = iopub_router |
|
|||
123 | self._routers[(kernel_id, 'shell')] = shell_router |
|
|||
124 |
|
||||
125 | def kill_kernel(self, kernel_id): |
|
|||
126 | sm = self._session_dict.pop(kernel_id) |
|
|||
127 | sm.stop() |
|
|||
128 | self.kernel_manager.kill_kernel(kernel_id) |
|
|||
129 | self.log.info("Kernel killed: %s" % kernel_id) |
|
|||
130 |
|
||||
131 | def interrupt_kernel(self, kernel_id): |
|
|||
132 | self.kernel_manager.interrupt_kernel(kernel_id) |
|
|||
133 | self.log.debug("Kernel interrupted: %s" % kernel_id) |
|
|||
134 |
|
||||
135 | def restart_kernel(self, kernel_id): |
|
|||
136 | # Create the new kernel first so we can move the clients over. |
|
|||
137 | new_kernel_id = self.start_kernel() |
|
|||
138 |
|
||||
139 | # Copy the clients over to the new routers. |
|
|||
140 | old_iopub_router = self.get_router(kernel_id, 'iopub') |
|
|||
141 | old_shell_router = self.get_router(kernel_id, 'shell') |
|
|||
142 | new_iopub_router = self.get_router(new_kernel_id, 'iopub') |
|
|||
143 | new_shell_router = self.get_router(new_kernel_id, 'shell') |
|
|||
144 | new_iopub_router.copy_clients(old_iopub_router) |
|
|||
145 | new_shell_router.copy_clients(old_shell_router) |
|
|||
146 |
|
||||
147 | # Now shutdown the old session and the kernel. |
|
|||
148 | # TODO: This causes a hard crash in ZMQStream.close, which sets |
|
|||
149 | # self.socket to None to hastily. We will need to fix this in PyZMQ |
|
|||
150 | # itself. For now, we just leave the old kernel running :( |
|
|||
151 | # Maybe this is fixed now, but nothing was changed really. |
|
|||
152 | self.kill_kernel(kernel_id) |
|
|||
153 |
|
||||
154 | self.log.debug("Kernel restarted: %s -> %s" % (kernel_id, new_kernel_id)) |
|
|||
155 | return new_kernel_id |
|
|||
156 |
|
||||
157 | def get_router(self, kernel_id, stream_name): |
|
|||
158 | router = self._routers[(kernel_id, stream_name)] |
|
|||
159 | return router |
|
|||
160 |
|
||||
161 |
|
89 | |||
162 |
|
90 | |||
163 | #----------------------------------------------------------------------------- |
|
91 | #----------------------------------------------------------------------------- | |
@@ -196,6 +124,7 b' class IPythonNotebookApp(BaseIPythonApplication):' | |||||
196 | """ |
|
124 | """ | |
197 |
|
125 | |||
198 | classes = [IPKernelApp, ZMQInteractiveShell, ProfileDir, Session, |
|
126 | classes = [IPKernelApp, ZMQInteractiveShell, ProfileDir, Session, | |
|
127 | RoutingKernelManager, NotebookManager, | |||
199 | KernelManager, SessionManager, RichIPythonWidget] |
|
128 | KernelManager, SessionManager, RichIPythonWidget] | |
200 | flags = Dict(flags) |
|
129 | flags = Dict(flags) | |
201 | aliases = Dict(aliases) |
|
130 | aliases = Dict(aliases) | |
@@ -232,12 +161,16 b' class IPythonNotebookApp(BaseIPythonApplication):' | |||||
232 | if a.startswith('-') and a.lstrip('-') in notebook_flags: |
|
161 | if a.startswith('-') and a.lstrip('-') in notebook_flags: | |
233 | self.kernel_argv.remove(a) |
|
162 | self.kernel_argv.remove(a) | |
234 |
|
163 | |||
235 |
def init_ |
|
164 | def init_configurables(self): | |
236 | # Don't let Qt or ZMQ swallow KeyboardInterupts. |
|
165 | # Don't let Qt or ZMQ swallow KeyboardInterupts. | |
237 | signal.signal(signal.SIGINT, signal.SIG_DFL) |
|
166 | signal.signal(signal.SIGINT, signal.SIG_DFL) | |
238 |
|
167 | |||
239 | # Create a KernelManager and start a kernel. |
|
168 | # Create a KernelManager and start a kernel. | |
240 | self.kernel_manager = KernelManager(config=self.config, log=self.log) |
|
169 | self.kernel_manager = KernelManager(config=self.config, log=self.log) | |
|
170 | self.routing_kernel_manager = RoutingKernelManager(config=self.config, log=self.log, | |||
|
171 | kernel_manager=self.kernel_manager, kernel_argv=self.kernel_argv | |||
|
172 | ) | |||
|
173 | self.notebook_manager = NotebookManager(config=self.config, log=self.log) | |||
241 |
|
174 | |||
242 | def init_logging(self): |
|
175 | def init_logging(self): | |
243 | super(IPythonNotebookApp, self).init_logging() |
|
176 | super(IPythonNotebookApp, self).init_logging() | |
@@ -248,9 +181,9 b' class IPythonNotebookApp(BaseIPythonApplication):' | |||||
248 |
|
181 | |||
249 | def initialize(self, argv=None): |
|
182 | def initialize(self, argv=None): | |
250 | super(IPythonNotebookApp, self).initialize(argv) |
|
183 | super(IPythonNotebookApp, self).initialize(argv) | |
251 |
self.init_ |
|
184 | self.init_configurables() | |
252 | self.web_app = NotebookWebApplication( |
|
185 | self.web_app = NotebookWebApplication( | |
253 |
self.kernel_manager, self.log |
|
186 | self.routing_kernel_manager, self.notebook_manager, self.log | |
254 | ) |
|
187 | ) | |
255 | self.http_server = httpserver.HTTPServer(self.web_app) |
|
188 | self.http_server = httpserver.HTTPServer(self.web_app) | |
256 | self.http_server.listen(self.port) |
|
189 | self.http_server.listen(self.port) |
@@ -15,7 +15,7 b' import uuid' | |||||
15 |
|
15 | |||
16 | from tornado import web |
|
16 | from tornado import web | |
17 |
|
17 | |||
18 | from IPython.config.configurable import Configurable |
|
18 | from IPython.config.configurable import LoggingConfigurable | |
19 | from IPython.nbformat import current |
|
19 | from IPython.nbformat import current | |
20 | from IPython.utils.traitlets import Unicode, List, Dict |
|
20 | from IPython.utils.traitlets import Unicode, List, Dict | |
21 |
|
21 | |||
@@ -25,7 +25,7 b' from IPython.utils.traitlets import Unicode, List, Dict' | |||||
25 | #----------------------------------------------------------------------------- |
|
25 | #----------------------------------------------------------------------------- | |
26 |
|
26 | |||
27 |
|
27 | |||
28 | class NotebookManager(Configurable): |
|
28 | class NotebookManager(LoggingConfigurable): | |
29 |
|
29 | |||
30 | notebook_dir = Unicode(os.getcwd()) |
|
30 | notebook_dir = Unicode(os.getcwd()) | |
31 | filename_ext = Unicode(u'.ipynb') |
|
31 | filename_ext = Unicode(u'.ipynb') |
@@ -28,9 +28,10 b' var IPython = (function (IPython) {' | |||||
28 | return msg; |
|
28 | return msg; | |
29 | } |
|
29 | } | |
30 |
|
30 | |||
31 | Kernel.prototype.start_kernel = function (callback) { |
|
31 | Kernel.prototype.start_kernel = function (notebook_id, callback) { | |
32 | var that = this; |
|
32 | var that = this; | |
33 | $.post(this.base_url, |
|
33 | var qs = $.param({notebook:notebook_id}); | |
|
34 | $.post(this.base_url + '?' + qs, | |||
34 | function (kernel_id) { |
|
35 | function (kernel_id) { | |
35 | that._handle_start_kernel(kernel_id, callback); |
|
36 | that._handle_start_kernel(kernel_id, callback); | |
36 | }, |
|
37 | }, |
@@ -391,7 +391,8 b' var IPython = (function (IPython) {' | |||||
391 |
|
391 | |||
392 | Notebook.prototype.start_kernel = function () { |
|
392 | Notebook.prototype.start_kernel = function () { | |
393 | this.kernel = new IPython.Kernel(); |
|
393 | this.kernel = new IPython.Kernel(); | |
394 | this.kernel.start_kernel($.proxy(this.kernel_started, this)); |
|
394 | var notebook_id = IPython.save_widget.get_notebook_id(); | |
|
395 | this.kernel.start_kernel(notebook_id, $.proxy(this.kernel_started, this)); | |||
395 | }; |
|
396 | }; | |
396 |
|
397 | |||
397 |
|
398 |
General Comments 0
You need to be logged in to leave comments.
Login now