##// END OF EJS Templates
fix --no-browser flag in notebook after rename
MinRK -
Show More
@@ -1,315 +1,315 b''
1 """A tornado based IPython notebook server.
1 """A tornado based IPython notebook server.
2
2
3 Authors:
3 Authors:
4
4
5 * Brian Granger
5 * Brian Granger
6 """
6 """
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 import errno
19 import errno
20 import logging
20 import logging
21 import os
21 import os
22 import signal
22 import signal
23 import socket
23 import socket
24 import sys
24 import sys
25 import webbrowser
25 import webbrowser
26
26
27 import zmq
27 import zmq
28
28
29 # Install the pyzmq ioloop. This has to be done before anything else from
29 # Install the pyzmq ioloop. This has to be done before anything else from
30 # tornado is imported.
30 # tornado is imported.
31 from zmq.eventloop import ioloop
31 from zmq.eventloop import ioloop
32 import tornado.ioloop
32 import tornado.ioloop
33 tornado.ioloop.IOLoop = ioloop.IOLoop
33 tornado.ioloop.IOLoop = ioloop.IOLoop
34
34
35 from tornado import httpserver
35 from tornado import httpserver
36 from tornado import web
36 from tornado import web
37
37
38 from .kernelmanager import MappingKernelManager
38 from .kernelmanager import MappingKernelManager
39 from .handlers import (LoginHandler,
39 from .handlers import (LoginHandler,
40 ProjectDashboardHandler, NewHandler, NamedNotebookHandler,
40 ProjectDashboardHandler, NewHandler, NamedNotebookHandler,
41 MainKernelHandler, KernelHandler, KernelActionHandler, IOPubHandler,
41 MainKernelHandler, KernelHandler, KernelActionHandler, IOPubHandler,
42 ShellHandler, NotebookRootHandler, NotebookHandler, RSTHandler
42 ShellHandler, NotebookRootHandler, NotebookHandler, RSTHandler
43 )
43 )
44 from .notebookmanager import NotebookManager
44 from .notebookmanager import NotebookManager
45
45
46 from IPython.core.application import BaseIPythonApplication
46 from IPython.core.application import BaseIPythonApplication
47 from IPython.core.profiledir import ProfileDir
47 from IPython.core.profiledir import ProfileDir
48 from IPython.zmq.session import Session, default_secure
48 from IPython.zmq.session import Session, default_secure
49 from IPython.zmq.zmqshell import ZMQInteractiveShell
49 from IPython.zmq.zmqshell import ZMQInteractiveShell
50 from IPython.zmq.ipkernel import (
50 from IPython.zmq.ipkernel import (
51 flags as ipkernel_flags,
51 flags as ipkernel_flags,
52 aliases as ipkernel_aliases,
52 aliases as ipkernel_aliases,
53 IPKernelApp
53 IPKernelApp
54 )
54 )
55 from IPython.utils.traitlets import Dict, Unicode, Int, List, Enum, Bool
55 from IPython.utils.traitlets import Dict, Unicode, Int, List, Enum, Bool
56
56
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58 # Module globals
58 # Module globals
59 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
60
60
61 _kernel_id_regex = r"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)"
61 _kernel_id_regex = r"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)"
62 _kernel_action_regex = r"(?P<action>restart|interrupt)"
62 _kernel_action_regex = r"(?P<action>restart|interrupt)"
63 _notebook_id_regex = r"(?P<notebook_id>\w+-\w+-\w+-\w+-\w+)"
63 _notebook_id_regex = r"(?P<notebook_id>\w+-\w+-\w+-\w+-\w+)"
64
64
65 LOCALHOST = '127.0.0.1'
65 LOCALHOST = '127.0.0.1'
66
66
67 _examples = """
67 _examples = """
68 ipython notebook # start the notebook
68 ipython notebook # start the notebook
69 ipython notebook --profile=sympy # use the sympy profile
69 ipython notebook --profile=sympy # use the sympy profile
70 ipython notebook --pylab=inline # pylab in inline plotting mode
70 ipython notebook --pylab=inline # pylab in inline plotting mode
71 ipython notebook --certfile=mycert.pem # use SSL/TLS certificate
71 ipython notebook --certfile=mycert.pem # use SSL/TLS certificate
72 ipython notebook --port=5555 --ip=* # Listen on port 5555, all interfaces
72 ipython notebook --port=5555 --ip=* # Listen on port 5555, all interfaces
73 """
73 """
74
74
75 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
76 # The Tornado web application
76 # The Tornado web application
77 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
78
78
79 class NotebookWebApplication(web.Application):
79 class NotebookWebApplication(web.Application):
80
80
81 def __init__(self, ipython_app, kernel_manager, notebook_manager, log):
81 def __init__(self, ipython_app, kernel_manager, notebook_manager, log):
82 handlers = [
82 handlers = [
83 (r"/", ProjectDashboardHandler),
83 (r"/", ProjectDashboardHandler),
84 (r"/login", LoginHandler),
84 (r"/login", LoginHandler),
85 (r"/new", NewHandler),
85 (r"/new", NewHandler),
86 (r"/%s" % _notebook_id_regex, NamedNotebookHandler),
86 (r"/%s" % _notebook_id_regex, NamedNotebookHandler),
87 (r"/kernels", MainKernelHandler),
87 (r"/kernels", MainKernelHandler),
88 (r"/kernels/%s" % _kernel_id_regex, KernelHandler),
88 (r"/kernels/%s" % _kernel_id_regex, KernelHandler),
89 (r"/kernels/%s/%s" % (_kernel_id_regex, _kernel_action_regex), KernelActionHandler),
89 (r"/kernels/%s/%s" % (_kernel_id_regex, _kernel_action_regex), KernelActionHandler),
90 (r"/kernels/%s/iopub" % _kernel_id_regex, IOPubHandler),
90 (r"/kernels/%s/iopub" % _kernel_id_regex, IOPubHandler),
91 (r"/kernels/%s/shell" % _kernel_id_regex, ShellHandler),
91 (r"/kernels/%s/shell" % _kernel_id_regex, ShellHandler),
92 (r"/notebooks", NotebookRootHandler),
92 (r"/notebooks", NotebookRootHandler),
93 (r"/notebooks/%s" % _notebook_id_regex, NotebookHandler),
93 (r"/notebooks/%s" % _notebook_id_regex, NotebookHandler),
94 (r"/rstservice/render", RSTHandler)
94 (r"/rstservice/render", RSTHandler)
95 ]
95 ]
96 settings = dict(
96 settings = dict(
97 template_path=os.path.join(os.path.dirname(__file__), "templates"),
97 template_path=os.path.join(os.path.dirname(__file__), "templates"),
98 static_path=os.path.join(os.path.dirname(__file__), "static"),
98 static_path=os.path.join(os.path.dirname(__file__), "static"),
99 cookie_secret=os.urandom(1024),
99 cookie_secret=os.urandom(1024),
100 login_url="/login",
100 login_url="/login",
101 )
101 )
102 web.Application.__init__(self, handlers, **settings)
102 web.Application.__init__(self, handlers, **settings)
103
103
104 self.kernel_manager = kernel_manager
104 self.kernel_manager = kernel_manager
105 self.log = log
105 self.log = log
106 self.notebook_manager = notebook_manager
106 self.notebook_manager = notebook_manager
107 self.ipython_app = ipython_app
107 self.ipython_app = ipython_app
108
108
109
109
110 #-----------------------------------------------------------------------------
110 #-----------------------------------------------------------------------------
111 # Aliases and Flags
111 # Aliases and Flags
112 #-----------------------------------------------------------------------------
112 #-----------------------------------------------------------------------------
113
113
114 flags = dict(ipkernel_flags)
114 flags = dict(ipkernel_flags)
115 flags['no-browser']=(
115 flags['no-browser']=(
116 {'IPythonNotebookApp' : {'open_browser' : False}},
116 {'NotebookApp' : {'open_browser' : False}},
117 "Don't open the notebook in a browser after startup."
117 "Don't open the notebook in a browser after startup."
118 )
118 )
119
119
120 # the flags that are specific to the frontend
120 # the flags that are specific to the frontend
121 # these must be scrubbed before being passed to the kernel,
121 # these must be scrubbed before being passed to the kernel,
122 # or it will raise an error on unrecognized flags
122 # or it will raise an error on unrecognized flags
123 notebook_flags = ['no-browser']
123 notebook_flags = ['no-browser']
124
124
125 aliases = dict(ipkernel_aliases)
125 aliases = dict(ipkernel_aliases)
126
126
127 aliases.update({
127 aliases.update({
128 'ip': 'NotebookApp.ip',
128 'ip': 'NotebookApp.ip',
129 'port': 'NotebookApp.port',
129 'port': 'NotebookApp.port',
130 'keyfile': 'NotebookApp.keyfile',
130 'keyfile': 'NotebookApp.keyfile',
131 'certfile': 'NotebookApp.certfile',
131 'certfile': 'NotebookApp.certfile',
132 'ws-hostname': 'NotebookApp.ws_hostname',
132 'ws-hostname': 'NotebookApp.ws_hostname',
133 'notebook-dir': 'NotebookManager.notebook_dir',
133 'notebook-dir': 'NotebookManager.notebook_dir',
134 })
134 })
135
135
136 # remove ipkernel flags that are singletons, and don't make sense in
136 # remove ipkernel flags that are singletons, and don't make sense in
137 # multi-kernel evironment:
137 # multi-kernel evironment:
138 aliases.pop('f', None)
138 aliases.pop('f', None)
139
139
140 notebook_aliases = [u'port', u'ip', u'keyfile', u'certfile', u'ws-hostname',
140 notebook_aliases = [u'port', u'ip', u'keyfile', u'certfile', u'ws-hostname',
141 u'notebook-dir']
141 u'notebook-dir']
142
142
143 #-----------------------------------------------------------------------------
143 #-----------------------------------------------------------------------------
144 # NotebookApp
144 # NotebookApp
145 #-----------------------------------------------------------------------------
145 #-----------------------------------------------------------------------------
146
146
147 class NotebookApp(BaseIPythonApplication):
147 class NotebookApp(BaseIPythonApplication):
148
148
149 name = 'ipython-notebook'
149 name = 'ipython-notebook'
150 default_config_file_name='ipython_notebook_config.py'
150 default_config_file_name='ipython_notebook_config.py'
151
151
152 description = """
152 description = """
153 The IPython HTML Notebook.
153 The IPython HTML Notebook.
154
154
155 This launches a Tornado based HTML Notebook Server that serves up an
155 This launches a Tornado based HTML Notebook Server that serves up an
156 HTML5/Javascript Notebook client.
156 HTML5/Javascript Notebook client.
157 """
157 """
158 examples = _examples
158 examples = _examples
159
159
160 classes = [IPKernelApp, ZMQInteractiveShell, ProfileDir, Session,
160 classes = [IPKernelApp, ZMQInteractiveShell, ProfileDir, Session,
161 MappingKernelManager, NotebookManager]
161 MappingKernelManager, NotebookManager]
162 flags = Dict(flags)
162 flags = Dict(flags)
163 aliases = Dict(aliases)
163 aliases = Dict(aliases)
164
164
165 kernel_argv = List(Unicode)
165 kernel_argv = List(Unicode)
166
166
167 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
167 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
168 default_value=logging.INFO,
168 default_value=logging.INFO,
169 config=True,
169 config=True,
170 help="Set the log level by value or name.")
170 help="Set the log level by value or name.")
171
171
172 # Network related information.
172 # Network related information.
173
173
174 ip = Unicode(LOCALHOST, config=True,
174 ip = Unicode(LOCALHOST, config=True,
175 help="The IP address the notebook server will listen on."
175 help="The IP address the notebook server will listen on."
176 )
176 )
177
177
178 def _ip_changed(self, name, old, new):
178 def _ip_changed(self, name, old, new):
179 if new == u'*': self.ip = u''
179 if new == u'*': self.ip = u''
180
180
181 port = Int(8888, config=True,
181 port = Int(8888, config=True,
182 help="The port the notebook server will listen on."
182 help="The port the notebook server will listen on."
183 )
183 )
184
184
185 ws_hostname = Unicode(LOCALHOST, config=True,
185 ws_hostname = Unicode(LOCALHOST, config=True,
186 help="""The FQDN or IP for WebSocket connections. The default will work
186 help="""The FQDN or IP for WebSocket connections. The default will work
187 fine when the server is listening on localhost, but this needs to
187 fine when the server is listening on localhost, but this needs to
188 be set if the ip option is used. It will be used as the hostname part
188 be set if the ip option is used. It will be used as the hostname part
189 of the WebSocket url: ws://hostname/path."""
189 of the WebSocket url: ws://hostname/path."""
190 )
190 )
191
191
192 certfile = Unicode(u'', config=True,
192 certfile = Unicode(u'', config=True,
193 help="""The full path to an SSL/TLS certificate file."""
193 help="""The full path to an SSL/TLS certificate file."""
194 )
194 )
195
195
196 keyfile = Unicode(u'', config=True,
196 keyfile = Unicode(u'', config=True,
197 help="""The full path to a private key file for usage with SSL/TLS."""
197 help="""The full path to a private key file for usage with SSL/TLS."""
198 )
198 )
199
199
200 password = Unicode(u'', config=True,
200 password = Unicode(u'', config=True,
201 help="""Password to use for web authentication"""
201 help="""Password to use for web authentication"""
202 )
202 )
203
203
204 open_browser = Bool(True, config=True,
204 open_browser = Bool(True, config=True,
205 help="Whether to open in a browser after starting.")
205 help="Whether to open in a browser after starting.")
206
206
207 def get_ws_url(self):
207 def get_ws_url(self):
208 """Return the WebSocket URL for this server."""
208 """Return the WebSocket URL for this server."""
209 if self.certfile:
209 if self.certfile:
210 prefix = u'wss://'
210 prefix = u'wss://'
211 else:
211 else:
212 prefix = u'ws://'
212 prefix = u'ws://'
213 return prefix + self.ws_hostname + u':' + unicode(self.port)
213 return prefix + self.ws_hostname + u':' + unicode(self.port)
214
214
215 def parse_command_line(self, argv=None):
215 def parse_command_line(self, argv=None):
216 super(NotebookApp, self).parse_command_line(argv)
216 super(NotebookApp, self).parse_command_line(argv)
217 if argv is None:
217 if argv is None:
218 argv = sys.argv[1:]
218 argv = sys.argv[1:]
219
219
220 self.kernel_argv = list(argv) # copy
220 self.kernel_argv = list(argv) # copy
221 # Kernel should inherit default config file from frontend
221 # Kernel should inherit default config file from frontend
222 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
222 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
223 # Scrub frontend-specific flags
223 # Scrub frontend-specific flags
224 for a in argv:
224 for a in argv:
225 if a.startswith('-') and a.lstrip('-') in notebook_flags:
225 if a.startswith('-') and a.lstrip('-') in notebook_flags:
226 self.kernel_argv.remove(a)
226 self.kernel_argv.remove(a)
227 swallow_next = False
227 swallow_next = False
228 for a in argv:
228 for a in argv:
229 if swallow_next:
229 if swallow_next:
230 self.kernel_argv.remove(a)
230 self.kernel_argv.remove(a)
231 swallow_next = False
231 swallow_next = False
232 continue
232 continue
233 if a.startswith('-'):
233 if a.startswith('-'):
234 split = a.lstrip('-').split('=')
234 split = a.lstrip('-').split('=')
235 alias = split[0]
235 alias = split[0]
236 if alias in notebook_aliases:
236 if alias in notebook_aliases:
237 self.kernel_argv.remove(a)
237 self.kernel_argv.remove(a)
238 if len(split) == 1:
238 if len(split) == 1:
239 # alias passed with arg via space
239 # alias passed with arg via space
240 swallow_next = True
240 swallow_next = True
241
241
242 def init_configurables(self):
242 def init_configurables(self):
243 # Don't let Qt or ZMQ swallow KeyboardInterupts.
243 # Don't let Qt or ZMQ swallow KeyboardInterupts.
244 signal.signal(signal.SIGINT, signal.SIG_DFL)
244 signal.signal(signal.SIGINT, signal.SIG_DFL)
245
245
246 # force Session default to be secure
246 # force Session default to be secure
247 default_secure(self.config)
247 default_secure(self.config)
248 # Create a KernelManager and start a kernel.
248 # Create a KernelManager and start a kernel.
249 self.kernel_manager = MappingKernelManager(
249 self.kernel_manager = MappingKernelManager(
250 config=self.config, log=self.log, kernel_argv=self.kernel_argv,
250 config=self.config, log=self.log, kernel_argv=self.kernel_argv,
251 connection_dir = self.profile_dir.security_dir,
251 connection_dir = self.profile_dir.security_dir,
252 )
252 )
253 self.notebook_manager = NotebookManager(config=self.config, log=self.log)
253 self.notebook_manager = NotebookManager(config=self.config, log=self.log)
254 self.notebook_manager.list_notebooks()
254 self.notebook_manager.list_notebooks()
255
255
256 def init_logging(self):
256 def init_logging(self):
257 super(NotebookApp, self).init_logging()
257 super(NotebookApp, self).init_logging()
258 # This prevents double log messages because tornado use a root logger that
258 # This prevents double log messages because tornado use a root logger that
259 # self.log is a child of. The logging module dipatches log messages to a log
259 # self.log is a child of. The logging module dipatches log messages to a log
260 # and all of its ancenstors until propagate is set to False.
260 # and all of its ancenstors until propagate is set to False.
261 self.log.propagate = False
261 self.log.propagate = False
262
262
263 def initialize(self, argv=None):
263 def initialize(self, argv=None):
264 super(NotebookApp, self).initialize(argv)
264 super(NotebookApp, self).initialize(argv)
265 self.init_configurables()
265 self.init_configurables()
266 self.web_app = NotebookWebApplication(
266 self.web_app = NotebookWebApplication(
267 self, self.kernel_manager, self.notebook_manager, self.log
267 self, self.kernel_manager, self.notebook_manager, self.log
268 )
268 )
269 if self.certfile:
269 if self.certfile:
270 ssl_options = dict(certfile=self.certfile)
270 ssl_options = dict(certfile=self.certfile)
271 if self.keyfile:
271 if self.keyfile:
272 ssl_options['keyfile'] = self.keyfile
272 ssl_options['keyfile'] = self.keyfile
273 else:
273 else:
274 ssl_options = None
274 ssl_options = None
275 self.web_app.password = self.password
275 self.web_app.password = self.password
276 self.http_server = httpserver.HTTPServer(self.web_app, ssl_options=ssl_options)
276 self.http_server = httpserver.HTTPServer(self.web_app, ssl_options=ssl_options)
277 if ssl_options is None and not self.ip:
277 if ssl_options is None and not self.ip:
278 self.log.critical('WARNING: the notebook server is listening on all IP addresses '
278 self.log.critical('WARNING: the notebook server is listening on all IP addresses '
279 'but not using any encryption or authentication. This is highly '
279 'but not using any encryption or authentication. This is highly '
280 'insecure and not recommended.')
280 'insecure and not recommended.')
281
281
282 # Try random ports centered around the default.
282 # Try random ports centered around the default.
283 from random import randint
283 from random import randint
284 n = 50 # Max number of attempts, keep reasonably large.
284 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)]:
285 for port in [self.port] + [self.port + randint(-2*n, 2*n) for i in range(n)]:
286 try:
286 try:
287 self.http_server.listen(port, self.ip)
287 self.http_server.listen(port, self.ip)
288 except socket.error, e:
288 except socket.error, e:
289 if e.errno != errno.EADDRINUSE:
289 if e.errno != errno.EADDRINUSE:
290 raise
290 raise
291 self.log.info('The port %i is already in use, trying another random port.' % port)
291 self.log.info('The port %i is already in use, trying another random port.' % port)
292 else:
292 else:
293 self.port = port
293 self.port = port
294 break
294 break
295
295
296 def start(self):
296 def start(self):
297 ip = self.ip if self.ip else '[all ip addresses on your system]'
297 ip = self.ip if self.ip else '[all ip addresses on your system]'
298 proto = 'https' if self.certfile else 'http'
298 proto = 'https' if self.certfile else 'http'
299 self.log.info("The IPython Notebook is running at: %s://%s:%i" % (proto,
299 self.log.info("The IPython Notebook is running at: %s://%s:%i" % (proto,
300 ip,
300 ip,
301 self.port))
301 self.port))
302 if self.open_browser:
302 if self.open_browser:
303 ip = self.ip or '127.0.0.1'
303 ip = self.ip or '127.0.0.1'
304 webbrowser.open("%s://%s:%i" % (proto, ip, self.port), new=2)
304 webbrowser.open("%s://%s:%i" % (proto, ip, self.port), new=2)
305 ioloop.IOLoop.instance().start()
305 ioloop.IOLoop.instance().start()
306
306
307 #-----------------------------------------------------------------------------
307 #-----------------------------------------------------------------------------
308 # Main entry point
308 # Main entry point
309 #-----------------------------------------------------------------------------
309 #-----------------------------------------------------------------------------
310
310
311 def launch_new_instance():
311 def launch_new_instance():
312 app = NotebookApp()
312 app = NotebookApp()
313 app.initialize()
313 app.initialize()
314 app.start()
314 app.start()
315
315
General Comments 0
You need to be logged in to leave comments. Login now