##// END OF EJS Templates
fix: changed keyword input field to type password
Satrajit Ghosh -
Show More
@@ -1,357 +1,357 b''
1 1 """Tornado handlers for the notebook.
2 2
3 3 Authors:
4 4
5 5 * Brian Granger
6 6 """
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2008-2011 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 from tornado import web
20 20 from tornado import websocket
21 21
22 22 from zmq.eventloop import ioloop
23 23 from zmq.utils import jsonapi
24 24
25 25 from IPython.zmq.session import Session
26 26
27 27 try:
28 28 from docutils.core import publish_string
29 29 except ImportError:
30 30 publish_string = None
31 31
32 32
33 33
34 34 #-----------------------------------------------------------------------------
35 35 # Top-level handlers
36 36 #-----------------------------------------------------------------------------
37 37
38 38 class BaseHandler(web.RequestHandler):
39 39 def get_current_user(self):
40 40 user_id = self.get_secure_cookie("user")
41 41 keyword = self.get_secure_cookie("keyword")
42 42 if self.application.keyword and self.application.keyword != keyword:
43 43 return None
44 44 if not user_id:
45 45 user_id = 'anonymous'
46 46 return user_id
47 47
48 48 class NBBrowserHandler(BaseHandler):
49 49 @web.authenticated
50 50 def get(self):
51 51 nbm = self.application.notebook_manager
52 52 project = nbm.notebook_dir
53 53 self.render('nbbrowser.html', project=project)
54 54
55 55 class LoginHandler(BaseHandler):
56 56 def get(self):
57 57 user_id = self.get_secure_cookie("user")
58 58 self.write('<html><body><form action="/login" method="post">'
59 59 'Name: <input type="text" name="name" value=%s>'
60 'Keyword: <input type="text" name="keyword">'
60 'Keyword: <input type="password" name="keyword">'
61 61 '<input type="submit" value="Sign in">'
62 62 '</form></body></html>'%user_id)
63 63
64 64 def post(self):
65 65 self.set_secure_cookie("user", self.get_argument("name", default=u''))
66 66 self.set_secure_cookie("keyword", self.get_argument("keyword", default=u''))
67 67 self.redirect("/")
68 68
69 69 class NewHandler(web.RequestHandler):
70 70 def get(self):
71 71 notebook_id = self.application.notebook_manager.new_notebook()
72 72 self.render('notebook.html', notebook_id=notebook_id)
73 73
74 74
75 75 class NamedNotebookHandler(web.RequestHandler):
76 76 def get(self, notebook_id):
77 77 nbm = self.application.notebook_manager
78 78 if not nbm.notebook_exists(notebook_id):
79 79 raise web.HTTPError(404, u'Notebook does not exist: %s' % notebook_id)
80 80 self.render('notebook.html', notebook_id=notebook_id)
81 81
82 82
83 83 #-----------------------------------------------------------------------------
84 84 # Kernel handlers
85 85 #-----------------------------------------------------------------------------
86 86
87 87
88 88 class MainKernelHandler(web.RequestHandler):
89 89
90 90 def get(self):
91 91 km = self.application.kernel_manager
92 92 self.finish(jsonapi.dumps(km.kernel_ids))
93 93
94 94 def post(self):
95 95 km = self.application.kernel_manager
96 96 notebook_id = self.get_argument('notebook', default=None)
97 97 kernel_id = km.start_kernel(notebook_id)
98 98 ws_url = self.application.ipython_app.get_ws_url()
99 99 data = {'ws_url':ws_url,'kernel_id':kernel_id}
100 100 self.set_header('Location', '/'+kernel_id)
101 101 self.finish(jsonapi.dumps(data))
102 102
103 103
104 104 class KernelHandler(web.RequestHandler):
105 105
106 106 SUPPORTED_METHODS = ('DELETE')
107 107
108 108 def delete(self, kernel_id):
109 109 km = self.application.kernel_manager
110 110 km.kill_kernel(kernel_id)
111 111 self.set_status(204)
112 112 self.finish()
113 113
114 114
115 115 class KernelActionHandler(web.RequestHandler):
116 116
117 117 def post(self, kernel_id, action):
118 118 km = self.application.kernel_manager
119 119 if action == 'interrupt':
120 120 km.interrupt_kernel(kernel_id)
121 121 self.set_status(204)
122 122 if action == 'restart':
123 123 new_kernel_id = km.restart_kernel(kernel_id)
124 124 ws_url = self.application.ipython_app.get_ws_url()
125 125 data = {'ws_url':ws_url,'kernel_id':new_kernel_id}
126 126 self.set_header('Location', '/'+new_kernel_id)
127 127 self.write(jsonapi.dumps(data))
128 128 self.finish()
129 129
130 130
131 131 class ZMQStreamHandler(websocket.WebSocketHandler):
132 132
133 133 def _reserialize_reply(self, msg_list):
134 134 """Reserialize a reply message using JSON.
135 135
136 136 This takes the msg list from the ZMQ socket, unserializes it using
137 137 self.session and then serializes the result using JSON. This method
138 138 should be used by self._on_zmq_reply to build messages that can
139 139 be sent back to the browser.
140 140 """
141 141 idents, msg_list = self.session.feed_identities(msg_list)
142 142 msg = self.session.unserialize(msg_list)
143 143 try:
144 144 msg['header'].pop('date')
145 145 except KeyError:
146 146 pass
147 147 try:
148 148 msg['parent_header'].pop('date')
149 149 except KeyError:
150 150 pass
151 151 msg.pop('buffers')
152 152 return jsonapi.dumps(msg)
153 153
154 154 def _on_zmq_reply(self, msg_list):
155 155 try:
156 156 msg = self._reserialize_reply(msg_list)
157 157 except:
158 158 self.application.kernel_manager.log.critical("Malformed message: %r" % msg_list)
159 159 else:
160 160 self.write_message(msg)
161 161
162 162
163 163 class IOPubHandler(ZMQStreamHandler):
164 164
165 165 def initialize(self, *args, **kwargs):
166 166 self._kernel_alive = True
167 167 self._beating = False
168 168 self.iopub_stream = None
169 169 self.hb_stream = None
170 170
171 171 def open(self, kernel_id):
172 172 km = self.application.kernel_manager
173 173 self.kernel_id = kernel_id
174 174 self.session = Session()
175 175 self.time_to_dead = km.time_to_dead
176 176 try:
177 177 self.iopub_stream = km.create_iopub_stream(kernel_id)
178 178 self.hb_stream = km.create_hb_stream(kernel_id)
179 179 except web.HTTPError:
180 180 # WebSockets don't response to traditional error codes so we
181 181 # close the connection.
182 182 if not self.stream.closed():
183 183 self.stream.close()
184 184 else:
185 185 self.iopub_stream.on_recv(self._on_zmq_reply)
186 186 self.start_hb(self.kernel_died)
187 187
188 188 def on_close(self):
189 189 # This method can be called twice, once by self.kernel_died and once
190 190 # from the WebSocket close event. If the WebSocket connection is
191 191 # closed before the ZMQ streams are setup, they could be None.
192 192 self.stop_hb()
193 193 if self.iopub_stream is not None and not self.iopub_stream.closed():
194 194 self.iopub_stream.on_recv(None)
195 195 self.iopub_stream.close()
196 196 if self.hb_stream is not None and not self.hb_stream.closed():
197 197 self.hb_stream.close()
198 198
199 199 def start_hb(self, callback):
200 200 """Start the heartbeating and call the callback if the kernel dies."""
201 201 if not self._beating:
202 202 self._kernel_alive = True
203 203
204 204 def ping_or_dead():
205 205 if self._kernel_alive:
206 206 self._kernel_alive = False
207 207 self.hb_stream.send(b'ping')
208 208 else:
209 209 try:
210 210 callback()
211 211 except:
212 212 pass
213 213 finally:
214 214 self._hb_periodic_callback.stop()
215 215
216 216 def beat_received(msg):
217 217 self._kernel_alive = True
218 218
219 219 self.hb_stream.on_recv(beat_received)
220 220 self._hb_periodic_callback = ioloop.PeriodicCallback(ping_or_dead, self.time_to_dead*1000)
221 221 self._hb_periodic_callback.start()
222 222 self._beating= True
223 223
224 224 def stop_hb(self):
225 225 """Stop the heartbeating and cancel all related callbacks."""
226 226 if self._beating:
227 227 self._hb_periodic_callback.stop()
228 228 if not self.hb_stream.closed():
229 229 self.hb_stream.on_recv(None)
230 230
231 231 def kernel_died(self):
232 232 self.application.kernel_manager.delete_mapping_for_kernel(self.kernel_id)
233 233 self.write_message(
234 234 {'header': {'msg_type': 'status'},
235 235 'parent_header': {},
236 236 'content': {'execution_state':'dead'}
237 237 }
238 238 )
239 239 self.on_close()
240 240
241 241
242 242 class ShellHandler(ZMQStreamHandler):
243 243
244 244 def initialize(self, *args, **kwargs):
245 245 self.shell_stream = None
246 246
247 247 def open(self, kernel_id):
248 248 km = self.application.kernel_manager
249 249 self.max_msg_size = km.max_msg_size
250 250 self.kernel_id = kernel_id
251 251 try:
252 252 self.shell_stream = km.create_shell_stream(kernel_id)
253 253 except web.HTTPError:
254 254 # WebSockets don't response to traditional error codes so we
255 255 # close the connection.
256 256 if not self.stream.closed():
257 257 self.stream.close()
258 258 else:
259 259 self.session = Session()
260 260 self.shell_stream.on_recv(self._on_zmq_reply)
261 261
262 262 def on_message(self, msg):
263 263 if len(msg) < self.max_msg_size:
264 264 msg = jsonapi.loads(msg)
265 265 self.session.send(self.shell_stream, msg)
266 266
267 267 def on_close(self):
268 268 # Make sure the stream exists and is not already closed.
269 269 if self.shell_stream is not None and not self.shell_stream.closed():
270 270 self.shell_stream.close()
271 271
272 272
273 273 #-----------------------------------------------------------------------------
274 274 # Notebook web service handlers
275 275 #-----------------------------------------------------------------------------
276 276
277 277 class NotebookRootHandler(web.RequestHandler):
278 278
279 279 def get(self):
280 280 nbm = self.application.notebook_manager
281 281 files = nbm.list_notebooks()
282 282 self.finish(jsonapi.dumps(files))
283 283
284 284 def post(self):
285 285 nbm = self.application.notebook_manager
286 286 body = self.request.body.strip()
287 287 format = self.get_argument('format', default='json')
288 288 name = self.get_argument('name', default=None)
289 289 if body:
290 290 notebook_id = nbm.save_new_notebook(body, name=name, format=format)
291 291 else:
292 292 notebook_id = nbm.new_notebook()
293 293 self.set_header('Location', '/'+notebook_id)
294 294 self.finish(jsonapi.dumps(notebook_id))
295 295
296 296
297 297 class NotebookHandler(web.RequestHandler):
298 298
299 299 SUPPORTED_METHODS = ('GET', 'PUT', 'DELETE')
300 300
301 301 def get(self, notebook_id):
302 302 nbm = self.application.notebook_manager
303 303 format = self.get_argument('format', default='json')
304 304 last_mod, name, data = nbm.get_notebook(notebook_id, format)
305 305 if format == u'json':
306 306 self.set_header('Content-Type', 'application/json')
307 307 self.set_header('Content-Disposition','attachment; filename="%s.ipynb"' % name)
308 308 elif format == u'py':
309 309 self.set_header('Content-Type', 'application/x-python')
310 310 self.set_header('Content-Disposition','attachment; filename="%s.py"' % name)
311 311 self.set_header('Last-Modified', last_mod)
312 312 self.finish(data)
313 313
314 314 def put(self, notebook_id):
315 315 nbm = self.application.notebook_manager
316 316 format = self.get_argument('format', default='json')
317 317 name = self.get_argument('name', default=None)
318 318 nbm.save_notebook(notebook_id, self.request.body, name=name, format=format)
319 319 self.set_status(204)
320 320 self.finish()
321 321
322 322 def delete(self, notebook_id):
323 323 nbm = self.application.notebook_manager
324 324 nbm.delete_notebook(notebook_id)
325 325 self.set_status(204)
326 326 self.finish()
327 327
328 328 #-----------------------------------------------------------------------------
329 329 # RST web service handlers
330 330 #-----------------------------------------------------------------------------
331 331
332 332
333 333 class RSTHandler(web.RequestHandler):
334 334
335 335 def post(self):
336 336 if publish_string is None:
337 337 raise web.HTTPError(503, u'docutils not available')
338 338 body = self.request.body.strip()
339 339 source = body
340 340 # template_path=os.path.join(os.path.dirname(__file__), u'templates', u'rst_template.html')
341 341 defaults = {'file_insertion_enabled': 0,
342 342 'raw_enabled': 0,
343 343 '_disable_config': 1,
344 344 'stylesheet_path': 0
345 345 # 'template': template_path
346 346 }
347 347 try:
348 348 html = publish_string(source, writer_name='html',
349 349 settings_overrides=defaults
350 350 )
351 351 except:
352 352 raise web.HTTPError(400, u'Invalid RST')
353 353 print html
354 354 self.set_header('Content-Type', 'text/html')
355 355 self.finish(html)
356 356
357 357
General Comments 0
You need to be logged in to leave comments. Login now