Show More
@@ -13,9 +13,7 b' except ImportError:' | |||
|
13 | 13 | from urlparse import urlparse # Py 2 |
|
14 | 14 | |
|
15 | 15 | import tornado |
|
16 | from tornado import ioloop | |
|
17 | from tornado import web | |
|
18 | from tornado import websocket | |
|
16 | from tornado import gen, ioloop, web, websocket | |
|
19 | 17 | |
|
20 | 18 | from IPython.kernel.zmq.session import Session |
|
21 | 19 | from IPython.utils.jsonutil import date_default, extract_dates |
@@ -197,7 +195,12 b' class AuthenticatedZMQStreamHandler(ZMQStreamHandler, IPythonHandler):' | |||
|
197 | 195 | """ |
|
198 | 196 | pass |
|
199 | 197 | |
|
200 |
def get(self |
|
|
198 | def pre_get(self): | |
|
199 | """Run before finishing the GET request | |
|
200 | ||
|
201 | Extend this method to add logic that should fire before | |
|
202 | the websocket finishes completing. | |
|
203 | """ | |
|
201 | 204 | # Check to see that origin matches host directly, including ports |
|
202 | 205 | # Tornado 4 already does CORS checking |
|
203 | 206 | if tornado.version_info[0] < 4: |
@@ -213,15 +216,22 b' class AuthenticatedZMQStreamHandler(ZMQStreamHandler, IPythonHandler):' | |||
|
213 | 216 | self.session.session = cast_unicode(self.get_argument('session_id')) |
|
214 | 217 | else: |
|
215 | 218 | self.log.warn("No session ID specified") |
|
219 | ||
|
220 | @gen.coroutine | |
|
221 | def get(self, *args, **kwargs): | |
|
222 | # pre_get can be a coroutine in subclasses | |
|
223 | yield gen.maybe_future(self.pre_get()) | |
|
216 | 224 | # FIXME: only do super get on tornado β₯ 4 |
|
217 | 225 | # tornado 3 has no get, will raise 405 |
|
218 | 226 | if tornado.version_info >= (4,): |
|
219 |
|
|
|
227 | super(AuthenticatedZMQStreamHandler, self).get(*args, **kwargs) | |
|
220 | 228 | |
|
221 | 229 | def initialize(self): |
|
230 | self.log.debug("Initializing websocket connection %s", self.request.path) | |
|
222 | 231 | self.session = Session(config=self.config) |
|
223 | 232 | |
|
224 | 233 | def open(self, *args, **kwargs): |
|
234 | self.log.debug("Opening websocket %s", self.request.path) | |
|
225 | 235 | if tornado.version_info < (4,): |
|
226 | 236 | try: |
|
227 | 237 | self.get(*self.open_args, **self.open_kwargs) |
@@ -7,6 +7,7 b' import json' | |||
|
7 | 7 | import logging |
|
8 | 8 | from tornado import gen, web |
|
9 | 9 | from tornado.concurrent import Future |
|
10 | from tornado.ioloop import IOLoop | |
|
10 | 11 | |
|
11 | 12 | from IPython.utils.jsonutil import date_default |
|
12 | 13 | from IPython.utils.py3compat import cast_unicode |
@@ -85,6 +86,10 b' class KernelActionHandler(IPythonHandler):' | |||
|
85 | 86 | |
|
86 | 87 | class ZMQChannelHandler(AuthenticatedZMQStreamHandler): |
|
87 | 88 | |
|
89 | @property | |
|
90 | def kernel_info_timeout(self): | |
|
91 | return self.settings.get('kernel_info_timeout', 10) | |
|
92 | ||
|
88 | 93 | def __repr__(self): |
|
89 | 94 | return "%s(%s)" % (self.__class__.__name__, getattr(self, 'kernel_id', 'uninitialized')) |
|
90 | 95 | |
@@ -150,6 +155,7 b' class ZMQChannelHandler(AuthenticatedZMQStreamHandler):' | |||
|
150 | 155 | if protocol_version != kernel_protocol_version: |
|
151 | 156 | self.session.adapt_version = int(protocol_version.split('.')[0]) |
|
152 | 157 | self.log.info("Kernel %s speaks protocol %s", self.kernel_id, protocol_version) |
|
158 | if not self._kernel_info_future.done(): | |
|
153 | 159 | self._kernel_info_future.set_result(info) |
|
154 | 160 | |
|
155 | 161 | def initialize(self): |
@@ -160,10 +166,29 b' class ZMQChannelHandler(AuthenticatedZMQStreamHandler):' | |||
|
160 | 166 | self._kernel_info_future = Future() |
|
161 | 167 | |
|
162 | 168 | @gen.coroutine |
|
169 | def pre_get(self): | |
|
170 | # authenticate first | |
|
171 | super(ZMQChannelHandler, self).pre_get() | |
|
172 | # then request kernel info, waiting up to a certain time before giving up. | |
|
173 | # We don't want to wait forever, because browsers don't take it well when | |
|
174 | # servers never respond to websocket connection requests. | |
|
175 | future = self.request_kernel_info() | |
|
176 | ||
|
177 | def give_up(): | |
|
178 | """Don't wait forever for the kernel to reply""" | |
|
179 | if future.done(): | |
|
180 | return | |
|
181 | self.log.warn("Timeout waiting for kernel_info reply from %s", self.kernel_id) | |
|
182 | future.set_result(None) | |
|
183 | loop = IOLoop.current() | |
|
184 | loop.add_timeout(loop.time() + self.kernel_info_timeout, give_up) | |
|
185 | # actually wait for it | |
|
186 | yield future | |
|
187 | ||
|
188 | @gen.coroutine | |
|
163 | 189 | def get(self, kernel_id): |
|
164 | 190 | self.kernel_id = cast_unicode(kernel_id, 'ascii') |
|
165 | yield self.request_kernel_info() | |
|
166 | super(ZMQChannelHandler, self).get(kernel_id) | |
|
191 | yield super(ZMQChannelHandler, self).get(kernel_id=kernel_id) | |
|
167 | 192 | |
|
168 | 193 | def open(self, kernel_id): |
|
169 | 194 | super(ZMQChannelHandler, self).open() |
General Comments 0
You need to be logged in to leave comments.
Login now