##// END OF EJS Templates
Allow notebook server to run in read-only mode...
MinRK -
Show More
@@ -26,6 +26,7 b' from tornado import websocket'
26 26 from zmq.eventloop import ioloop
27 27 from zmq.utils import jsonapi
28 28
29 from IPython.external.decorator import decorator
29 30 from IPython.zmq.session import Session
30 31
31 32 try:
@@ -34,6 +35,16 b' except ImportError:'
34 35 publish_string = None
35 36
36 37
38 #-----------------------------------------------------------------------------
39 # Decorator for disabling read-only handlers
40 #-----------------------------------------------------------------------------
41
42 @decorator
43 def not_if_readonly(f, self, *args, **kwargs):
44 if self.application.ipython_app.read_only:
45 raise web.HTTPError(403, "Notebook server is read-only")
46 else:
47 return f(self, *args, **kwargs)
37 48
38 49 #-----------------------------------------------------------------------------
39 50 # Top-level handlers
@@ -82,6 +93,7 b' class LoginHandler(AuthenticatedHandler):'
82 93
83 94 class NewHandler(AuthenticatedHandler):
84 95
96 @not_if_readonly
85 97 @web.authenticated
86 98 def get(self):
87 99 nbm = self.application.notebook_manager
@@ -118,11 +130,13 b' class NamedNotebookHandler(AuthenticatedHandler):'
118 130
119 131 class MainKernelHandler(AuthenticatedHandler):
120 132
133 @not_if_readonly
121 134 @web.authenticated
122 135 def get(self):
123 136 km = self.application.kernel_manager
124 137 self.finish(jsonapi.dumps(km.kernel_ids))
125 138
139 @not_if_readonly
126 140 @web.authenticated
127 141 def post(self):
128 142 km = self.application.kernel_manager
@@ -138,6 +152,7 b' class KernelHandler(AuthenticatedHandler):'
138 152
139 153 SUPPORTED_METHODS = ('DELETE')
140 154
155 @not_if_readonly
141 156 @web.authenticated
142 157 def delete(self, kernel_id):
143 158 km = self.application.kernel_manager
@@ -148,6 +163,7 b' class KernelHandler(AuthenticatedHandler):'
148 163
149 164 class KernelActionHandler(AuthenticatedHandler):
150 165
166 @not_if_readonly
151 167 @web.authenticated
152 168 def post(self, kernel_id, action):
153 169 km = self.application.kernel_manager
@@ -226,6 +242,7 b' class AuthenticatedZMQStreamHandler(ZMQStreamHandler):'
226 242 except:
227 243 logging.warn("couldn't parse cookie string: %s",msg, exc_info=True)
228 244
245 @not_if_readonly
229 246 def on_first_message(self, msg):
230 247 self._inject_cookie_message(msg)
231 248 if self.get_current_user() is None:
@@ -369,6 +386,7 b' class NotebookRootHandler(AuthenticatedHandler):'
369 386 files = nbm.list_notebooks()
370 387 self.finish(jsonapi.dumps(files))
371 388
389 @not_if_readonly
372 390 @web.authenticated
373 391 def post(self):
374 392 nbm = self.application.notebook_manager
@@ -401,6 +419,7 b' class NotebookHandler(AuthenticatedHandler):'
401 419 self.set_header('Last-Modified', last_mod)
402 420 self.finish(data)
403 421
422 @not_if_readonly
404 423 @web.authenticated
405 424 def put(self, notebook_id):
406 425 nbm = self.application.notebook_manager
@@ -410,6 +429,7 b' class NotebookHandler(AuthenticatedHandler):'
410 429 self.set_status(204)
411 430 self.finish()
412 431
432 @not_if_readonly
413 433 @web.authenticated
414 434 def delete(self, notebook_id):
415 435 nbm = self.application.notebook_manager
@@ -116,6 +116,10 b" flags['no-browser']=("
116 116 {'NotebookApp' : {'open_browser' : False}},
117 117 "Don't open the notebook in a browser after startup."
118 118 )
119 flags['read-only'] = (
120 {'NotebookApp' : {'read_only' : True}},
121 "Launch the Notebook server in read-only mode, not allowing execution or editing"
122 )
119 123
120 124 # the flags that are specific to the frontend
121 125 # these must be scrubbed before being passed to the kernel,
@@ -203,6 +207,10 b' class NotebookApp(BaseIPythonApplication):'
203 207
204 208 open_browser = Bool(True, config=True,
205 209 help="Whether to open in a browser after starting.")
210
211 read_only = Bool(False, config=True,
212 help="Whether to prevent editing/execution of notebooks."
213 )
206 214
207 215 def get_ws_url(self):
208 216 """Return the WebSocket URL for this server."""
@@ -282,7 +290,7 b' class NotebookApp(BaseIPythonApplication):'
282 290 # Try random ports centered around the default.
283 291 from random import randint
284 292 n = 50 # Max number of attempts, keep reasonably large.
285 for port in [self.port] + [self.port + randint(-2*n, 2*n) for i in range(n)]:
293 for port in range(self.port, self.port+5) + [self.port + randint(-2*n, 2*n) for i in range(n-5)]:
286 294 try:
287 295 self.http_server.listen(port, self.ip)
288 296 except socket.error, e:
General Comments 0
You need to be logged in to leave comments. Login now