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