Permalink
Browse files

Merge pull request #899 from minrk/nbwork

Internal notebook refactoring and cleanup, plus fixing a bug that prevented Tornado from authenticating users with password.
  • Loading branch information...
fperez committed Oct 19, 2011
2 parents d2b3a0c + b7e6ff5 commit 284cfec13725eed01e755c04f300b71d2d258aa1
@@ -194,15 +194,15 @@ def init_config_files(self):
else:
apps.append(IPythonQtConsoleApp)
try:
- from IPython.frontend.html.notebook.notebookapp import IPythonNotebookApp
+ from IPython.frontend.html.notebook.notebookapp import NotebookApp
except ImportError:
pass
except Exception:
- self.log.debug('Unexpected error when importing IPythonNotebookApp',
+ self.log.debug('Unexpected error when importing NotebookApp',
exc_info=True
)
else:
- apps.append(IPythonNotebookApp)
+ apps.append(NotebookApp)
if self.parallel:
from IPython.parallel.apps.ipcontrollerapp import IPControllerApp
from IPython.parallel.apps.ipengineapp import IPEngineApp
@@ -18,6 +18,7 @@
import logging
import Cookie
+import uuid
from tornado import web
from tornado import websocket
@@ -40,51 +41,74 @@
class AuthenticatedHandler(web.RequestHandler):
"""A RequestHandler with an authenticated user."""
+
def get_current_user(self):
- user_id = self.get_secure_cookie("user")
+ user_id = self.get_secure_cookie("username")
+ # For now the user_id should not return empty, but it could eventually
if user_id == '':
user_id = 'anonymous'
if user_id is None:
# prevent extra Invalid cookie sig warnings:
- self.clear_cookie('user')
+ self.clear_cookie('username')
if not self.application.password:
user_id = 'anonymous'
return user_id
-class NBBrowserHandler(AuthenticatedHandler):
+class ProjectDashboardHandler(AuthenticatedHandler):
+
@web.authenticated
def get(self):
nbm = self.application.notebook_manager
project = nbm.notebook_dir
- self.render('nbbrowser.html', project=project)
+ self.render(
+ 'projectdashboard.html', project=project,
+ base_project_url=u'/', base_kernel_url=u'/'
+ )
+
class LoginHandler(AuthenticatedHandler):
+
def get(self):
- user_id = self.get_secure_cookie("user") or ''
- self.render('login.html', user_id=user_id)
+ self.render('login.html', next='/')
def post(self):
- pwd = self.get_argument("password", default=u'')
+ pwd = self.get_argument('password', default=u'')
if self.application.password and pwd == self.application.password:
- self.set_secure_cookie("user", self.get_argument("name", default=u''))
- url = self.get_argument("next", default="/")
+ self.set_secure_cookie('username', str(uuid.uuid4()))
+ url = self.get_argument('next', default='/')
self.redirect(url)
+
class NewHandler(AuthenticatedHandler):
+
@web.authenticated
def get(self):
- notebook_id = self.application.notebook_manager.new_notebook()
- self.render('notebook.html', notebook_id=notebook_id)
+ nbm = self.application.notebook_manager
+ project = nbm.notebook_dir
+ notebook_id = nbm.new_notebook()
+ self.render(
+ 'notebook.html', project=project,
+ notebook_id=notebook_id,
+ base_project_url=u'/', base_kernel_url=u'/',
+ kill_kernel=False
+ )
class NamedNotebookHandler(AuthenticatedHandler):
+
@web.authenticated
def get(self, notebook_id):
nbm = self.application.notebook_manager
+ project = nbm.notebook_dir
if not nbm.notebook_exists(notebook_id):
raise web.HTTPError(404, u'Notebook does not exist: %s' % notebook_id)
- self.render('notebook.html', notebook_id=notebook_id)
+ self.render(
+ 'notebook.html', project=project,
+ notebook_id=notebook_id,
+ base_project_url=u'/', base_kernel_url=u'/',
+ kill_kernel=False
+ )
#-----------------------------------------------------------------------------
@@ -166,11 +190,13 @@ def _on_zmq_reply(self, msg_list):
try:
msg = self._reserialize_reply(msg_list)
except:
- self.application.kernel_manager.log.critical("Malformed message: %r" % msg_list)
+ self.application.log.critical("Malformed message: %r" % msg_list)
else:
self.write_message(msg)
+
class AuthenticatedZMQStreamHandler(ZMQStreamHandler):
+
def open(self, kernel_id):
self.kernel_id = kernel_id.decode('ascii')
try:
@@ -184,7 +210,7 @@ def open(self, kernel_id):
self.on_message = self.on_first_message
def get_current_user(self):
- user_id = self.get_secure_cookie("user")
+ user_id = self.get_secure_cookie("username")
if user_id == '' or (user_id is None and not self.application.password):
user_id = 'anonymous'
return user_id
@@ -196,7 +222,7 @@ def _inject_cookie_message(self, msg):
# Cookie can't constructor doesn't accept unicode strings for some reason
msg = msg.encode('utf8', 'replace')
try:
- self._cookies = Cookie.SimpleCookie(msg)
+ self.request._cookies = Cookie.SimpleCookie(msg)
except:
logging.warn("couldn't parse cookie string: %s",msg, exc_info=True)
@@ -37,7 +37,7 @@
from .kernelmanager import MappingKernelManager
from .handlers import (LoginHandler,
- NBBrowserHandler, NewHandler, NamedNotebookHandler,
+ ProjectDashboardHandler, NewHandler, NamedNotebookHandler,
MainKernelHandler, KernelHandler, KernelActionHandler, IOPubHandler,
ShellHandler, NotebookRootHandler, NotebookHandler, RSTHandler
)
@@ -80,7 +80,7 @@ class NotebookWebApplication(web.Application):
def __init__(self, ipython_app, kernel_manager, notebook_manager, log):
handlers = [
- (r"/", NBBrowserHandler),
+ (r"/", ProjectDashboardHandler),
(r"/login", LoginHandler),
(r"/new", NewHandler),
(r"/%s" % _notebook_id_regex, NamedNotebookHandler),
@@ -125,11 +125,11 @@ def __init__(self, ipython_app, kernel_manager, notebook_manager, log):
aliases = dict(ipkernel_aliases)
aliases.update({
- 'ip': 'IPythonNotebookApp.ip',
- 'port': 'IPythonNotebookApp.port',
- 'keyfile': 'IPythonNotebookApp.keyfile',
- 'certfile': 'IPythonNotebookApp.certfile',
- 'ws-hostname': 'IPythonNotebookApp.ws_hostname',
+ 'ip': 'NotebookApp.ip',
+ 'port': 'NotebookApp.port',
+ 'keyfile': 'NotebookApp.keyfile',
+ 'certfile': 'NotebookApp.certfile',
+ 'ws-hostname': 'NotebookApp.ws_hostname',
'notebook-dir': 'NotebookManager.notebook_dir',
})
@@ -141,10 +141,10 @@ def __init__(self, ipython_app, kernel_manager, notebook_manager, log):
u'notebook-dir']
#-----------------------------------------------------------------------------
-# IPythonNotebookApp
+# NotebookApp
#-----------------------------------------------------------------------------
-class IPythonNotebookApp(BaseIPythonApplication):
+class NotebookApp(BaseIPythonApplication):
name = 'ipython-notebook'
default_config_file_name='ipython_notebook_config.py'
@@ -213,7 +213,7 @@ def get_ws_url(self):
return prefix + self.ws_hostname + u':' + unicode(self.port)
def parse_command_line(self, argv=None):
- super(IPythonNotebookApp, self).parse_command_line(argv)
+ super(NotebookApp, self).parse_command_line(argv)
if argv is None:
argv = sys.argv[1:]
@@ -254,14 +254,14 @@ def init_configurables(self):
self.notebook_manager.list_notebooks()
def init_logging(self):
- super(IPythonNotebookApp, self).init_logging()
+ super(NotebookApp, self).init_logging()
# This prevents double log messages because tornado use a root logger that
# self.log is a child of. The logging module dipatches log messages to a log
# and all of its ancenstors until propagate is set to False.
self.log.propagate = False
def initialize(self, argv=None):
- super(IPythonNotebookApp, self).initialize(argv)
+ super(NotebookApp, self).initialize(argv)
self.init_configurables()
self.web_app = NotebookWebApplication(
self, self.kernel_manager, self.notebook_manager, self.log
@@ -309,7 +309,7 @@ def start(self):
#-----------------------------------------------------------------------------
def launch_new_instance():
- app = IPythonNotebookApp()
+ app = NotebookApp()
app.initialize()
app.start()
@@ -37,9 +37,8 @@ input#notebook_name {
}
span#kernel_status {
- position: absolute;
- padding: 8px 5px 5px 5px;
- right: 10px;
+ float: right;
+ padding: 0px 5px;
font-weight: bold;
}
@@ -65,10 +64,14 @@ div#left_panel {
position: absolute;
}
-h3.section_header {
+div.section_header {
padding: 5px;
}
+div.section_header h3 {
+ display: inline;
+}
+
div.section_content {
padding: 5px;
}
@@ -15,12 +15,10 @@ var IPython = (function (IPython) {
var Kernel = function () {
this.kernel_id = null;
- this.base_url = "/kernels";
- this.kernel_url = null;
this.shell_channel = null;
this.iopub_channel = null;
+ this.base_url = $('body').data('baseKernelUrl') + "kernels";
this.running = false;
-
this.username = "username";
this.session_id = utils.uuid();
@@ -52,7 +50,8 @@ var IPython = (function (IPython) {
var that = this;
if (!this.running) {
var qs = $.param({notebook:notebook_id});
- $.post(this.base_url + '?' + qs,
+ var url = this.base_url + '?' + qs
+ $.post(url,
function (kernel_id) {
that._handle_start_kernel(kernel_id, callback);
},
@@ -97,7 +96,6 @@ var IPython = (function (IPython) {
this.iopub_channel = new this.WebSocket(ws_url + "/iopub");
send_cookie = function(){
this.send(document.cookie);
- console.log(this);
}
this.shell_channel.onopen = send_cookie;
this.iopub_channel.onopen = send_cookie;
@@ -0,0 +1,30 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2008-2011 The IPython Development Team
+//
+// Distributed under the terms of the BSD License. The full license is in
+// the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// On document ready
+//============================================================================
+
+
+$(document).ready(function () {
+
+ $('div#header').addClass('border-box-sizing');
+ $('div#header_border').addClass('border-box-sizing ui-widget ui-widget-content');
+
+ $('div#main_app').addClass('border-box-sizing ui-widget');
+ $('div#app_hbox').addClass('hbox');
+
+ $('div#left_panel').addClass('box-flex');
+ $('div#right_panel').addClass('box-flex');
+ $('input#signin').button();
+
+ // These have display: none in the css file and are made visible here to prevent FLOUC.
+ $('div#header').css('display','block');
+ $('div#main_app').css('display','block');
+
+});
+
@@ -931,23 +931,24 @@ var IPython = (function (IPython) {
error : $.proxy(this.notebook_save_failed,this)
};
IPython.save_widget.status_saving();
- $.ajax("/notebooks/" + notebook_id, settings);
+ var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id
+ $.ajax(url, settings);
};
};
Notebook.prototype.notebook_saved = function (data, status, xhr) {
this.dirty = false;
IPython.save_widget.notebook_saved();
- setTimeout($.proxy(IPython.save_widget.status_save,IPython.save_widget),500);
+ IPython.save_widget.status_save();
}
Notebook.prototype.notebook_save_failed = function (xhr, status, error_msg) {
// Notify the user and reset the save button
// TODO: Handle different types of errors (timeout etc.)
alert('An unexpected error occured while saving the notebook.');
- setTimeout($.proxy(IPython.save_widget.reset_status,IPython.save_widget),500);
+ IPython.save_widget.reset_status();
}
@@ -968,7 +969,8 @@ var IPython = (function (IPython) {
}
};
IPython.save_widget.status_loading();
- $.ajax("/notebooks/" + notebook_id, settings);
+ var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id
+ $.ajax(url, settings);
}
@@ -989,8 +991,10 @@ var IPython = (function (IPython) {
}, 50);
};
+
IPython.Notebook = Notebook;
+
return IPython;
}(IPython));
Oops, something went wrong.

0 comments on commit 284cfec

Please sign in to comment.