##// END OF EJS Templates
fix inverted self.browser logic
MinRK -
Show More
@@ -1,468 +1,468 b''
1 # coding: utf-8
1 # coding: utf-8
2 """A tornado based IPython notebook server.
2 """A tornado based IPython notebook server.
3
3
4 Authors:
4 Authors:
5
5
6 * Brian Granger
6 * Brian Granger
7 """
7 """
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008-2011 The IPython Development Team
9 # Copyright (C) 2008-2011 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 # stdlib
19 # stdlib
20 import errno
20 import errno
21 import logging
21 import logging
22 import os
22 import os
23 import signal
23 import signal
24 import socket
24 import socket
25 import sys
25 import sys
26 import threading
26 import threading
27 import webbrowser
27 import webbrowser
28
28
29 # Third party
29 # Third party
30 import zmq
30 import zmq
31
31
32 # Install the pyzmq ioloop. This has to be done before anything else from
32 # Install the pyzmq ioloop. This has to be done before anything else from
33 # tornado is imported.
33 # tornado is imported.
34 from zmq.eventloop import ioloop
34 from zmq.eventloop import ioloop
35 # FIXME: ioloop.install is new in pyzmq-2.1.7, so remove this conditional
35 # FIXME: ioloop.install is new in pyzmq-2.1.7, so remove this conditional
36 # when pyzmq dependency is updated beyond that.
36 # when pyzmq dependency is updated beyond that.
37 if hasattr(ioloop, 'install'):
37 if hasattr(ioloop, 'install'):
38 ioloop.install()
38 ioloop.install()
39 else:
39 else:
40 import tornado.ioloop
40 import tornado.ioloop
41 tornado.ioloop.IOLoop = ioloop.IOLoop
41 tornado.ioloop.IOLoop = ioloop.IOLoop
42
42
43 from tornado import httpserver
43 from tornado import httpserver
44 from tornado import web
44 from tornado import web
45
45
46 # Our own libraries
46 # Our own libraries
47 from .kernelmanager import MappingKernelManager
47 from .kernelmanager import MappingKernelManager
48 from .handlers import (LoginHandler, LogoutHandler,
48 from .handlers import (LoginHandler, LogoutHandler,
49 ProjectDashboardHandler, NewHandler, NamedNotebookHandler,
49 ProjectDashboardHandler, NewHandler, NamedNotebookHandler,
50 MainKernelHandler, KernelHandler, KernelActionHandler, IOPubHandler,
50 MainKernelHandler, KernelHandler, KernelActionHandler, IOPubHandler,
51 ShellHandler, NotebookRootHandler, NotebookHandler, NotebookCopyHandler,
51 ShellHandler, NotebookRootHandler, NotebookHandler, NotebookCopyHandler,
52 RSTHandler, AuthenticatedFileHandler, PrintNotebookHandler
52 RSTHandler, AuthenticatedFileHandler, PrintNotebookHandler
53 )
53 )
54 from .notebookmanager import NotebookManager
54 from .notebookmanager import NotebookManager
55
55
56 from IPython.config.application import catch_config_error, boolean_flag
56 from IPython.config.application import catch_config_error, boolean_flag
57 from IPython.core.application import BaseIPythonApplication
57 from IPython.core.application import BaseIPythonApplication
58 from IPython.core.profiledir import ProfileDir
58 from IPython.core.profiledir import ProfileDir
59 from IPython.lib.kernel import swallow_argv
59 from IPython.lib.kernel import swallow_argv
60 from IPython.zmq.session import Session, default_secure
60 from IPython.zmq.session import Session, default_secure
61 from IPython.zmq.zmqshell import ZMQInteractiveShell
61 from IPython.zmq.zmqshell import ZMQInteractiveShell
62 from IPython.zmq.ipkernel import (
62 from IPython.zmq.ipkernel import (
63 flags as ipkernel_flags,
63 flags as ipkernel_flags,
64 aliases as ipkernel_aliases,
64 aliases as ipkernel_aliases,
65 IPKernelApp
65 IPKernelApp
66 )
66 )
67 from IPython.utils.traitlets import Dict, Unicode, Integer, List, Enum, Bool
67 from IPython.utils.traitlets import Dict, Unicode, Integer, List, Enum, Bool
68 from IPython.utils import py3compat
68 from IPython.utils import py3compat
69
69
70 #-----------------------------------------------------------------------------
70 #-----------------------------------------------------------------------------
71 # Module globals
71 # Module globals
72 #-----------------------------------------------------------------------------
72 #-----------------------------------------------------------------------------
73
73
74 _kernel_id_regex = r"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)"
74 _kernel_id_regex = r"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)"
75 _kernel_action_regex = r"(?P<action>restart|interrupt)"
75 _kernel_action_regex = r"(?P<action>restart|interrupt)"
76 _notebook_id_regex = r"(?P<notebook_id>\w+-\w+-\w+-\w+-\w+)"
76 _notebook_id_regex = r"(?P<notebook_id>\w+-\w+-\w+-\w+-\w+)"
77
77
78 LOCALHOST = '127.0.0.1'
78 LOCALHOST = '127.0.0.1'
79
79
80 _examples = """
80 _examples = """
81 ipython notebook # start the notebook
81 ipython notebook # start the notebook
82 ipython notebook --profile=sympy # use the sympy profile
82 ipython notebook --profile=sympy # use the sympy profile
83 ipython notebook --pylab=inline # pylab in inline plotting mode
83 ipython notebook --pylab=inline # pylab in inline plotting mode
84 ipython notebook --certfile=mycert.pem # use SSL/TLS certificate
84 ipython notebook --certfile=mycert.pem # use SSL/TLS certificate
85 ipython notebook --port=5555 --ip=* # Listen on port 5555, all interfaces
85 ipython notebook --port=5555 --ip=* # Listen on port 5555, all interfaces
86 """
86 """
87
87
88 #-----------------------------------------------------------------------------
88 #-----------------------------------------------------------------------------
89 # Helper functions
89 # Helper functions
90 #-----------------------------------------------------------------------------
90 #-----------------------------------------------------------------------------
91
91
92 def url_path_join(a,b):
92 def url_path_join(a,b):
93 if a.endswith('/') and b.startswith('/'):
93 if a.endswith('/') and b.startswith('/'):
94 return a[:-1]+b
94 return a[:-1]+b
95 else:
95 else:
96 return a+b
96 return a+b
97
97
98 #-----------------------------------------------------------------------------
98 #-----------------------------------------------------------------------------
99 # The Tornado web application
99 # The Tornado web application
100 #-----------------------------------------------------------------------------
100 #-----------------------------------------------------------------------------
101
101
102 class NotebookWebApplication(web.Application):
102 class NotebookWebApplication(web.Application):
103
103
104 def __init__(self, ipython_app, kernel_manager, notebook_manager, log,
104 def __init__(self, ipython_app, kernel_manager, notebook_manager, log,
105 base_project_url, settings_overrides):
105 base_project_url, settings_overrides):
106 handlers = [
106 handlers = [
107 (r"/", ProjectDashboardHandler),
107 (r"/", ProjectDashboardHandler),
108 (r"/login", LoginHandler),
108 (r"/login", LoginHandler),
109 (r"/logout", LogoutHandler),
109 (r"/logout", LogoutHandler),
110 (r"/new", NewHandler),
110 (r"/new", NewHandler),
111 (r"/%s" % _notebook_id_regex, NamedNotebookHandler),
111 (r"/%s" % _notebook_id_regex, NamedNotebookHandler),
112 (r"/%s/copy" % _notebook_id_regex, NotebookCopyHandler),
112 (r"/%s/copy" % _notebook_id_regex, NotebookCopyHandler),
113 (r"/%s/print" % _notebook_id_regex, PrintNotebookHandler),
113 (r"/%s/print" % _notebook_id_regex, PrintNotebookHandler),
114 (r"/kernels", MainKernelHandler),
114 (r"/kernels", MainKernelHandler),
115 (r"/kernels/%s" % _kernel_id_regex, KernelHandler),
115 (r"/kernels/%s" % _kernel_id_regex, KernelHandler),
116 (r"/kernels/%s/%s" % (_kernel_id_regex, _kernel_action_regex), KernelActionHandler),
116 (r"/kernels/%s/%s" % (_kernel_id_regex, _kernel_action_regex), KernelActionHandler),
117 (r"/kernels/%s/iopub" % _kernel_id_regex, IOPubHandler),
117 (r"/kernels/%s/iopub" % _kernel_id_regex, IOPubHandler),
118 (r"/kernels/%s/shell" % _kernel_id_regex, ShellHandler),
118 (r"/kernels/%s/shell" % _kernel_id_regex, ShellHandler),
119 (r"/notebooks", NotebookRootHandler),
119 (r"/notebooks", NotebookRootHandler),
120 (r"/notebooks/%s" % _notebook_id_regex, NotebookHandler),
120 (r"/notebooks/%s" % _notebook_id_regex, NotebookHandler),
121 (r"/rstservice/render", RSTHandler),
121 (r"/rstservice/render", RSTHandler),
122 (r"/files/(.*)", AuthenticatedFileHandler, {'path' : notebook_manager.notebook_dir}),
122 (r"/files/(.*)", AuthenticatedFileHandler, {'path' : notebook_manager.notebook_dir}),
123 ]
123 ]
124 settings = dict(
124 settings = dict(
125 template_path=os.path.join(os.path.dirname(__file__), "templates"),
125 template_path=os.path.join(os.path.dirname(__file__), "templates"),
126 static_path=os.path.join(os.path.dirname(__file__), "static"),
126 static_path=os.path.join(os.path.dirname(__file__), "static"),
127 cookie_secret=os.urandom(1024),
127 cookie_secret=os.urandom(1024),
128 login_url="/login",
128 login_url="/login",
129 )
129 )
130
130
131 # allow custom overrides for the tornado web app.
131 # allow custom overrides for the tornado web app.
132 settings.update(settings_overrides)
132 settings.update(settings_overrides)
133
133
134 # Python < 2.6.5 doesn't accept unicode keys in f(**kwargs), and
134 # Python < 2.6.5 doesn't accept unicode keys in f(**kwargs), and
135 # base_project_url will always be unicode, which will in turn
135 # base_project_url will always be unicode, which will in turn
136 # make the patterns unicode, and ultimately result in unicode
136 # make the patterns unicode, and ultimately result in unicode
137 # keys in kwargs to handler._execute(**kwargs) in tornado.
137 # keys in kwargs to handler._execute(**kwargs) in tornado.
138 # This enforces that base_project_url be ascii in that situation.
138 # This enforces that base_project_url be ascii in that situation.
139 #
139 #
140 # Note that the URLs these patterns check against are escaped,
140 # Note that the URLs these patterns check against are escaped,
141 # and thus guaranteed to be ASCII: 'hΓ©llo' is really 'h%C3%A9llo'.
141 # and thus guaranteed to be ASCII: 'hΓ©llo' is really 'h%C3%A9llo'.
142 base_project_url = py3compat.unicode_to_str(base_project_url, 'ascii')
142 base_project_url = py3compat.unicode_to_str(base_project_url, 'ascii')
143
143
144 # prepend base_project_url onto the patterns that we match
144 # prepend base_project_url onto the patterns that we match
145 new_handlers = []
145 new_handlers = []
146 for handler in handlers:
146 for handler in handlers:
147 pattern = url_path_join(base_project_url, handler[0])
147 pattern = url_path_join(base_project_url, handler[0])
148 new_handler = tuple([pattern]+list(handler[1:]))
148 new_handler = tuple([pattern]+list(handler[1:]))
149 new_handlers.append( new_handler )
149 new_handlers.append( new_handler )
150
150
151 super(NotebookWebApplication, self).__init__(new_handlers, **settings)
151 super(NotebookWebApplication, self).__init__(new_handlers, **settings)
152
152
153 self.kernel_manager = kernel_manager
153 self.kernel_manager = kernel_manager
154 self.log = log
154 self.log = log
155 self.notebook_manager = notebook_manager
155 self.notebook_manager = notebook_manager
156 self.ipython_app = ipython_app
156 self.ipython_app = ipython_app
157 self.read_only = self.ipython_app.read_only
157 self.read_only = self.ipython_app.read_only
158
158
159
159
160 #-----------------------------------------------------------------------------
160 #-----------------------------------------------------------------------------
161 # Aliases and Flags
161 # Aliases and Flags
162 #-----------------------------------------------------------------------------
162 #-----------------------------------------------------------------------------
163
163
164 flags = dict(ipkernel_flags)
164 flags = dict(ipkernel_flags)
165 flags['no-browser']=(
165 flags['no-browser']=(
166 {'NotebookApp' : {'open_browser' : False}},
166 {'NotebookApp' : {'open_browser' : False}},
167 "Don't open the notebook in a browser after startup."
167 "Don't open the notebook in a browser after startup."
168 )
168 )
169 flags['no-mathjax']=(
169 flags['no-mathjax']=(
170 {'NotebookApp' : {'enable_mathjax' : False}},
170 {'NotebookApp' : {'enable_mathjax' : False}},
171 """Disable MathJax
171 """Disable MathJax
172
172
173 MathJax is the javascript library IPython uses to render math/LaTeX. It is
173 MathJax is the javascript library IPython uses to render math/LaTeX. It is
174 very large, so you may want to disable it if you have a slow internet
174 very large, so you may want to disable it if you have a slow internet
175 connection, or for offline use of the notebook.
175 connection, or for offline use of the notebook.
176
176
177 When disabled, equations etc. will appear as their untransformed TeX source.
177 When disabled, equations etc. will appear as their untransformed TeX source.
178 """
178 """
179 )
179 )
180 flags['read-only'] = (
180 flags['read-only'] = (
181 {'NotebookApp' : {'read_only' : True}},
181 {'NotebookApp' : {'read_only' : True}},
182 """Allow read-only access to notebooks.
182 """Allow read-only access to notebooks.
183
183
184 When using a password to protect the notebook server, this flag
184 When using a password to protect the notebook server, this flag
185 allows unauthenticated clients to view the notebook list, and
185 allows unauthenticated clients to view the notebook list, and
186 individual notebooks, but not edit them, start kernels, or run
186 individual notebooks, but not edit them, start kernels, or run
187 code.
187 code.
188
188
189 If no password is set, the server will be entirely read-only.
189 If no password is set, the server will be entirely read-only.
190 """
190 """
191 )
191 )
192
192
193 # Add notebook manager flags
193 # Add notebook manager flags
194 flags.update(boolean_flag('script', 'NotebookManager.save_script',
194 flags.update(boolean_flag('script', 'NotebookManager.save_script',
195 'Auto-save a .py script everytime the .ipynb notebook is saved',
195 'Auto-save a .py script everytime the .ipynb notebook is saved',
196 'Do not auto-save .py scripts for every notebook'))
196 'Do not auto-save .py scripts for every notebook'))
197
197
198 # the flags that are specific to the frontend
198 # the flags that are specific to the frontend
199 # these must be scrubbed before being passed to the kernel,
199 # these must be scrubbed before being passed to the kernel,
200 # or it will raise an error on unrecognized flags
200 # or it will raise an error on unrecognized flags
201 notebook_flags = ['no-browser', 'no-mathjax', 'read-only', 'script', 'no-script']
201 notebook_flags = ['no-browser', 'no-mathjax', 'read-only', 'script', 'no-script']
202
202
203 aliases = dict(ipkernel_aliases)
203 aliases = dict(ipkernel_aliases)
204
204
205 aliases.update({
205 aliases.update({
206 'ip': 'NotebookApp.ip',
206 'ip': 'NotebookApp.ip',
207 'port': 'NotebookApp.port',
207 'port': 'NotebookApp.port',
208 'keyfile': 'NotebookApp.keyfile',
208 'keyfile': 'NotebookApp.keyfile',
209 'certfile': 'NotebookApp.certfile',
209 'certfile': 'NotebookApp.certfile',
210 'notebook-dir': 'NotebookManager.notebook_dir',
210 'notebook-dir': 'NotebookManager.notebook_dir',
211 'browser': 'NotebookApp.browser',
211 'browser': 'NotebookApp.browser',
212 })
212 })
213
213
214 # remove ipkernel flags that are singletons, and don't make sense in
214 # remove ipkernel flags that are singletons, and don't make sense in
215 # multi-kernel evironment:
215 # multi-kernel evironment:
216 aliases.pop('f', None)
216 aliases.pop('f', None)
217
217
218 notebook_aliases = [u'port', u'ip', u'keyfile', u'certfile',
218 notebook_aliases = [u'port', u'ip', u'keyfile', u'certfile',
219 u'notebook-dir']
219 u'notebook-dir']
220
220
221 #-----------------------------------------------------------------------------
221 #-----------------------------------------------------------------------------
222 # NotebookApp
222 # NotebookApp
223 #-----------------------------------------------------------------------------
223 #-----------------------------------------------------------------------------
224
224
225 class NotebookApp(BaseIPythonApplication):
225 class NotebookApp(BaseIPythonApplication):
226
226
227 name = 'ipython-notebook'
227 name = 'ipython-notebook'
228 default_config_file_name='ipython_notebook_config.py'
228 default_config_file_name='ipython_notebook_config.py'
229
229
230 description = """
230 description = """
231 The IPython HTML Notebook.
231 The IPython HTML Notebook.
232
232
233 This launches a Tornado based HTML Notebook Server that serves up an
233 This launches a Tornado based HTML Notebook Server that serves up an
234 HTML5/Javascript Notebook client.
234 HTML5/Javascript Notebook client.
235 """
235 """
236 examples = _examples
236 examples = _examples
237
237
238 classes = [IPKernelApp, ZMQInteractiveShell, ProfileDir, Session,
238 classes = [IPKernelApp, ZMQInteractiveShell, ProfileDir, Session,
239 MappingKernelManager, NotebookManager]
239 MappingKernelManager, NotebookManager]
240 flags = Dict(flags)
240 flags = Dict(flags)
241 aliases = Dict(aliases)
241 aliases = Dict(aliases)
242
242
243 kernel_argv = List(Unicode)
243 kernel_argv = List(Unicode)
244
244
245 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
245 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
246 default_value=logging.INFO,
246 default_value=logging.INFO,
247 config=True,
247 config=True,
248 help="Set the log level by value or name.")
248 help="Set the log level by value or name.")
249
249
250 # create requested profiles by default, if they don't exist:
250 # create requested profiles by default, if they don't exist:
251 auto_create = Bool(True)
251 auto_create = Bool(True)
252
252
253 # Network related information.
253 # Network related information.
254
254
255 ip = Unicode(LOCALHOST, config=True,
255 ip = Unicode(LOCALHOST, config=True,
256 help="The IP address the notebook server will listen on."
256 help="The IP address the notebook server will listen on."
257 )
257 )
258
258
259 def _ip_changed(self, name, old, new):
259 def _ip_changed(self, name, old, new):
260 if new == u'*': self.ip = u''
260 if new == u'*': self.ip = u''
261
261
262 port = Integer(8888, config=True,
262 port = Integer(8888, config=True,
263 help="The port the notebook server will listen on."
263 help="The port the notebook server will listen on."
264 )
264 )
265
265
266 certfile = Unicode(u'', config=True,
266 certfile = Unicode(u'', config=True,
267 help="""The full path to an SSL/TLS certificate file."""
267 help="""The full path to an SSL/TLS certificate file."""
268 )
268 )
269
269
270 keyfile = Unicode(u'', config=True,
270 keyfile = Unicode(u'', config=True,
271 help="""The full path to a private key file for usage with SSL/TLS."""
271 help="""The full path to a private key file for usage with SSL/TLS."""
272 )
272 )
273
273
274 password = Unicode(u'', config=True,
274 password = Unicode(u'', config=True,
275 help="""Hashed password to use for web authentication.
275 help="""Hashed password to use for web authentication.
276
276
277 To generate, type in a python/IPython shell:
277 To generate, type in a python/IPython shell:
278
278
279 from IPython.lib import passwd; passwd()
279 from IPython.lib import passwd; passwd()
280
280
281 The string should be of the form type:salt:hashed-password.
281 The string should be of the form type:salt:hashed-password.
282 """
282 """
283 )
283 )
284
284
285 open_browser = Bool(True, config=True,
285 open_browser = Bool(True, config=True,
286 help="""Whether to open in a browser after starting.
286 help="""Whether to open in a browser after starting.
287 The specific browser used is platform dependent and
287 The specific browser used is platform dependent and
288 determined by the python standard library `webbrowser`
288 determined by the python standard library `webbrowser`
289 module, unless it is overridden using the --browser
289 module, unless it is overridden using the --browser
290 (NotebookApp.browser) configuration option.
290 (NotebookApp.browser) configuration option.
291 """)
291 """)
292
292
293 browser = Unicode(u'', config=True,
293 browser = Unicode(u'', config=True,
294 help="""Specify what command to use to invoke a web
294 help="""Specify what command to use to invoke a web
295 browser when opening the notebook. If not specified, the
295 browser when opening the notebook. If not specified, the
296 default browser will be determined by the `webbrowser`
296 default browser will be determined by the `webbrowser`
297 standard library module, which allows setting of the
297 standard library module, which allows setting of the
298 BROWSER environment variable to override it.
298 BROWSER environment variable to override it.
299 """)
299 """)
300
300
301 read_only = Bool(False, config=True,
301 read_only = Bool(False, config=True,
302 help="Whether to prevent editing/execution of notebooks."
302 help="Whether to prevent editing/execution of notebooks."
303 )
303 )
304
304
305 webapp_settings = Dict(config=True,
305 webapp_settings = Dict(config=True,
306 help="Supply overrides for the tornado.web.Application that the "
306 help="Supply overrides for the tornado.web.Application that the "
307 "IPython notebook uses.")
307 "IPython notebook uses.")
308
308
309 enable_mathjax = Bool(True, config=True,
309 enable_mathjax = Bool(True, config=True,
310 help="""Whether to enable MathJax for typesetting math/TeX
310 help="""Whether to enable MathJax for typesetting math/TeX
311
311
312 MathJax is the javascript library IPython uses to render math/LaTeX. It is
312 MathJax is the javascript library IPython uses to render math/LaTeX. It is
313 very large, so you may want to disable it if you have a slow internet
313 very large, so you may want to disable it if you have a slow internet
314 connection, or for offline use of the notebook.
314 connection, or for offline use of the notebook.
315
315
316 When disabled, equations etc. will appear as their untransformed TeX source.
316 When disabled, equations etc. will appear as their untransformed TeX source.
317 """
317 """
318 )
318 )
319 def _enable_mathjax_changed(self, name, old, new):
319 def _enable_mathjax_changed(self, name, old, new):
320 """set mathjax url to empty if mathjax is disabled"""
320 """set mathjax url to empty if mathjax is disabled"""
321 if not new:
321 if not new:
322 self.mathjax_url = u''
322 self.mathjax_url = u''
323
323
324 base_project_url = Unicode('/', config=True,
324 base_project_url = Unicode('/', config=True,
325 help='''The base URL for the notebook server''')
325 help='''The base URL for the notebook server''')
326 base_kernel_url = Unicode('/', config=True,
326 base_kernel_url = Unicode('/', config=True,
327 help='''The base URL for the kernel server''')
327 help='''The base URL for the kernel server''')
328 websocket_host = Unicode("", config=True,
328 websocket_host = Unicode("", config=True,
329 help="""The hostname for the websocket server."""
329 help="""The hostname for the websocket server."""
330 )
330 )
331
331
332 mathjax_url = Unicode("", config=True,
332 mathjax_url = Unicode("", config=True,
333 help="""The url for MathJax.js."""
333 help="""The url for MathJax.js."""
334 )
334 )
335 def _mathjax_url_default(self):
335 def _mathjax_url_default(self):
336 if not self.enable_mathjax:
336 if not self.enable_mathjax:
337 return u''
337 return u''
338 static_path = self.webapp_settings.get("static_path", os.path.join(os.path.dirname(__file__), "static"))
338 static_path = self.webapp_settings.get("static_path", os.path.join(os.path.dirname(__file__), "static"))
339 static_url_prefix = self.webapp_settings.get("static_url_prefix",
339 static_url_prefix = self.webapp_settings.get("static_url_prefix",
340 "/static/")
340 "/static/")
341 if os.path.exists(os.path.join(static_path, 'mathjax', "MathJax.js")):
341 if os.path.exists(os.path.join(static_path, 'mathjax', "MathJax.js")):
342 self.log.info("Using local MathJax")
342 self.log.info("Using local MathJax")
343 return static_url_prefix+u"mathjax/MathJax.js"
343 return static_url_prefix+u"mathjax/MathJax.js"
344 else:
344 else:
345 self.log.info("Using MathJax from CDN")
345 self.log.info("Using MathJax from CDN")
346 return u"http://cdn.mathjax.org/mathjax/latest/MathJax.js"
346 return u"http://cdn.mathjax.org/mathjax/latest/MathJax.js"
347
347
348 def _mathjax_url_changed(self, name, old, new):
348 def _mathjax_url_changed(self, name, old, new):
349 if new and not self.enable_mathjax:
349 if new and not self.enable_mathjax:
350 # enable_mathjax=False overrides mathjax_url
350 # enable_mathjax=False overrides mathjax_url
351 self.mathjax_url = u''
351 self.mathjax_url = u''
352 else:
352 else:
353 self.log.info("Using MathJax: %s", new)
353 self.log.info("Using MathJax: %s", new)
354
354
355 def parse_command_line(self, argv=None):
355 def parse_command_line(self, argv=None):
356 super(NotebookApp, self).parse_command_line(argv)
356 super(NotebookApp, self).parse_command_line(argv)
357 if argv is None:
357 if argv is None:
358 argv = sys.argv[1:]
358 argv = sys.argv[1:]
359
359
360 # Scrub frontend-specific flags
360 # Scrub frontend-specific flags
361 self.kernel_argv = swallow_argv(argv, notebook_aliases, notebook_flags)
361 self.kernel_argv = swallow_argv(argv, notebook_aliases, notebook_flags)
362 # Kernel should inherit default config file from frontend
362 # Kernel should inherit default config file from frontend
363 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
363 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
364
364
365 def init_configurables(self):
365 def init_configurables(self):
366 # force Session default to be secure
366 # force Session default to be secure
367 default_secure(self.config)
367 default_secure(self.config)
368 # Create a KernelManager and start a kernel.
368 # Create a KernelManager and start a kernel.
369 self.kernel_manager = MappingKernelManager(
369 self.kernel_manager = MappingKernelManager(
370 config=self.config, log=self.log, kernel_argv=self.kernel_argv,
370 config=self.config, log=self.log, kernel_argv=self.kernel_argv,
371 connection_dir = self.profile_dir.security_dir,
371 connection_dir = self.profile_dir.security_dir,
372 )
372 )
373 self.notebook_manager = NotebookManager(config=self.config, log=self.log)
373 self.notebook_manager = NotebookManager(config=self.config, log=self.log)
374 self.notebook_manager.list_notebooks()
374 self.notebook_manager.list_notebooks()
375
375
376 def init_logging(self):
376 def init_logging(self):
377 super(NotebookApp, self).init_logging()
377 super(NotebookApp, self).init_logging()
378 # This prevents double log messages because tornado use a root logger that
378 # This prevents double log messages because tornado use a root logger that
379 # self.log is a child of. The logging module dipatches log messages to a log
379 # self.log is a child of. The logging module dipatches log messages to a log
380 # and all of its ancenstors until propagate is set to False.
380 # and all of its ancenstors until propagate is set to False.
381 self.log.propagate = False
381 self.log.propagate = False
382
382
383 def init_webapp(self):
383 def init_webapp(self):
384 """initialize tornado webapp and httpserver"""
384 """initialize tornado webapp and httpserver"""
385 self.web_app = NotebookWebApplication(
385 self.web_app = NotebookWebApplication(
386 self, self.kernel_manager, self.notebook_manager, self.log,
386 self, self.kernel_manager, self.notebook_manager, self.log,
387 self.base_project_url, self.webapp_settings
387 self.base_project_url, self.webapp_settings
388 )
388 )
389 if self.certfile:
389 if self.certfile:
390 ssl_options = dict(certfile=self.certfile)
390 ssl_options = dict(certfile=self.certfile)
391 if self.keyfile:
391 if self.keyfile:
392 ssl_options['keyfile'] = self.keyfile
392 ssl_options['keyfile'] = self.keyfile
393 else:
393 else:
394 ssl_options = None
394 ssl_options = None
395 self.web_app.password = self.password
395 self.web_app.password = self.password
396 self.http_server = httpserver.HTTPServer(self.web_app, ssl_options=ssl_options)
396 self.http_server = httpserver.HTTPServer(self.web_app, ssl_options=ssl_options)
397 if ssl_options is None and not self.ip and not (self.read_only and not self.password):
397 if ssl_options is None and not self.ip and not (self.read_only and not self.password):
398 self.log.critical('WARNING: the notebook server is listening on all IP addresses '
398 self.log.critical('WARNING: the notebook server is listening on all IP addresses '
399 'but not using any encryption or authentication. This is highly '
399 'but not using any encryption or authentication. This is highly '
400 'insecure and not recommended.')
400 'insecure and not recommended.')
401
401
402 # Try random ports centered around the default.
402 # Try random ports centered around the default.
403 from random import randint
403 from random import randint
404 n = 50 # Max number of attempts, keep reasonably large.
404 n = 50 # Max number of attempts, keep reasonably large.
405 for port in range(self.port, self.port+5) + [self.port + randint(-2*n, 2*n) for i in range(n-5)]:
405 for port in range(self.port, self.port+5) + [self.port + randint(-2*n, 2*n) for i in range(n-5)]:
406 try:
406 try:
407 self.http_server.listen(port, self.ip)
407 self.http_server.listen(port, self.ip)
408 except socket.error, e:
408 except socket.error, e:
409 if e.errno != errno.EADDRINUSE:
409 if e.errno != errno.EADDRINUSE:
410 raise
410 raise
411 self.log.info('The port %i is already in use, trying another random port.' % port)
411 self.log.info('The port %i is already in use, trying another random port.' % port)
412 else:
412 else:
413 self.port = port
413 self.port = port
414 break
414 break
415
415
416 @catch_config_error
416 @catch_config_error
417 def initialize(self, argv=None):
417 def initialize(self, argv=None):
418 super(NotebookApp, self).initialize(argv)
418 super(NotebookApp, self).initialize(argv)
419 self.init_configurables()
419 self.init_configurables()
420 self.init_webapp()
420 self.init_webapp()
421
421
422 def cleanup_kernels(self):
422 def cleanup_kernels(self):
423 """shutdown all kernels
423 """shutdown all kernels
424
424
425 The kernels will shutdown themselves when this process no longer exists,
425 The kernels will shutdown themselves when this process no longer exists,
426 but explicit shutdown allows the KernelManagers to cleanup the connection files.
426 but explicit shutdown allows the KernelManagers to cleanup the connection files.
427 """
427 """
428 self.log.info('Shutting down kernels')
428 self.log.info('Shutting down kernels')
429 km = self.kernel_manager
429 km = self.kernel_manager
430 # copy list, since kill_kernel deletes keys
430 # copy list, since kill_kernel deletes keys
431 for kid in list(km.kernel_ids):
431 for kid in list(km.kernel_ids):
432 km.kill_kernel(kid)
432 km.kill_kernel(kid)
433
433
434 def start(self):
434 def start(self):
435 ip = self.ip if self.ip else '[all ip addresses on your system]'
435 ip = self.ip if self.ip else '[all ip addresses on your system]'
436 proto = 'https' if self.certfile else 'http'
436 proto = 'https' if self.certfile else 'http'
437 info = self.log.info
437 info = self.log.info
438 info("The IPython Notebook is running at: %s://%s:%i%s" %
438 info("The IPython Notebook is running at: %s://%s:%i%s" %
439 (proto, ip, self.port,self.base_project_url) )
439 (proto, ip, self.port,self.base_project_url) )
440 info("Use Control-C to stop this server and shut down all kernels.")
440 info("Use Control-C to stop this server and shut down all kernels.")
441
441
442 if self.open_browser:
442 if self.open_browser:
443 ip = self.ip or '127.0.0.1'
443 ip = self.ip or '127.0.0.1'
444 if self.browser:
444 if self.browser:
445 browser = webbrowser.get()
446 else:
447 browser = webbrowser.get(self.browser)
445 browser = webbrowser.get(self.browser)
446 else:
447 browser = webbrowser.get()
448 b = lambda : browser.open("%s://%s:%i%s" % (proto, ip, self.port,
448 b = lambda : browser.open("%s://%s:%i%s" % (proto, ip, self.port,
449 self.base_project_url),
449 self.base_project_url),
450 new=2)
450 new=2)
451 threading.Thread(target=b).start()
451 threading.Thread(target=b).start()
452 try:
452 try:
453 ioloop.IOLoop.instance().start()
453 ioloop.IOLoop.instance().start()
454 except KeyboardInterrupt:
454 except KeyboardInterrupt:
455 info("Interrupted...")
455 info("Interrupted...")
456 finally:
456 finally:
457 self.cleanup_kernels()
457 self.cleanup_kernels()
458
458
459
459
460 #-----------------------------------------------------------------------------
460 #-----------------------------------------------------------------------------
461 # Main entry point
461 # Main entry point
462 #-----------------------------------------------------------------------------
462 #-----------------------------------------------------------------------------
463
463
464 def launch_new_instance():
464 def launch_new_instance():
465 app = NotebookApp.instance()
465 app = NotebookApp.instance()
466 app.initialize()
466 app.initialize()
467 app.start()
467 app.start()
468
468
General Comments 0
You need to be logged in to leave comments. Login now