diff --git a/IPython/html/services/notebooks/filenbmanager.py b/IPython/html/services/notebooks/filenbmanager.py index a9f2480..cb1cafb 100644 --- a/IPython/html/services/notebooks/filenbmanager.py +++ b/IPython/html/services/notebooks/filenbmanager.py @@ -21,6 +21,7 @@ import io import os import glob import shutil +import ast from unicodedata import normalize @@ -74,7 +75,6 @@ class FileNotebookManager(NotebookManager): filename_ext = Unicode(u'.ipynb') - rev_mapping = Dict() def get_notebook_names(self, path): """List all notebook names in the notebook dir.""" @@ -87,13 +87,29 @@ class FileNotebookManager(NotebookManager): def list_notebooks(self, path): """List all notebooks in the notebook dir.""" - names = self.get_notebook_names(path) + notebook_names = self.get_notebook_names(path) + notebook_mapping = [] + for name in notebook_names: + model = self.notebook_model(name, path) + notebook_mapping.append(model) + return notebook_mapping - data = [] - for name in names: - data.append(name) - #data = sorted(data, key=lambda item: item['name']) - return names + def change_notebook(self, data, notebook_name, notebook_path=None): + """Changes notebook""" + full_path = self.get_path(notebook_name, notebook_path) + changes = data.keys() + for change in changes: + if change == "notebook_name": + os.rename(notebook_name, data['notebook_name']) + notebook_name = data['notebook_name'] + if change == "notebook_path": + new_path = self.get_path(data['notebook_name'], data['notebook_path']) + stutil.move(old_path, new_path) + notebook_path = data['notebook_path'] + if change == "content": + self.save_notebook(data, notebook_name, notebook_path) + model = self.notebook_model(notebook_name, notebook_path) + return model def notebook_exists(self, notebook_name): """Does a notebook exist?""" @@ -103,7 +119,6 @@ class FileNotebookManager(NotebookManager): path = self.get_path_by_name(self.mapping[notebook_name]) return os.path.isfile(path) - def get_path(self, notebook_name, notebook_path=None): """Return a full path to a notebook given its notebook_name.""" return self.get_path_by_name(notebook_name, notebook_path) @@ -145,16 +160,16 @@ class FileNotebookManager(NotebookManager): nb.metadata.name = os.path.splitext(os.path.basename(path))[0] return last_modified, nb - def write_notebook_object(self, nb, notebook_name=None, notebook_path=None): + def write_notebook_object(self, nb, notebook_name=None, notebook_path=None, new_name= None): """Save an existing notebook object by notebook_name.""" - try: - new_name = normalize('NFC', nb.metadata.name) - except AttributeError: - raise web.HTTPError(400, u'Missing notebook name') - + if new_name == None: + try: + new_name = normalize('NFC', nb.metadata.name) + except AttributeError: + raise web.HTTPError(400, u'Missing notebook name') + new_path = notebook_path old_name = notebook_name -# old_name = self.mapping[notebook_name] old_checkpoints = self.list_checkpoints(old_name) path = self.get_path_by_name(new_name, new_path) diff --git a/IPython/html/services/notebooks/handlers.py b/IPython/html/services/notebooks/handlers.py index 95fb3fa..3be4d23 100644 --- a/IPython/html/services/notebooks/handlers.py +++ b/IPython/html/services/notebooks/handlers.py @@ -17,6 +17,7 @@ Authors: #----------------------------------------------------------------------------- from tornado import web +import ast from zmq.utils import jsonapi @@ -35,11 +36,7 @@ class NotebookRootHandler(IPythonHandler): def get(self): nbm = self.notebook_manager km = self.kernel_manager - notebook_names = nbm.list_notebooks("") - notebooks = [] - for name in notebook_names: - model = nbm.notebook_model(name) - notebooks.append(model) + notebooks = nbm.list_notebooks("") self.finish(jsonapi.dumps(notebooks)) @web.authenticated @@ -60,7 +57,7 @@ class NotebookRootRedirect(IPythonHandler): class NotebookHandler(IPythonHandler): - SUPPORTED_METHODS = ('GET', 'PUT', 'DELETE') + SUPPORTED_METHODS = ('GET', 'PUT', 'PATCH', 'DELETE') @web.authenticated def get(self, notebook_path): @@ -68,11 +65,7 @@ class NotebookHandler(IPythonHandler): name, path = nbm.named_notebook_path(notebook_path) if name == None: - notebook_names = nbm.list_notebooks(path) - notebooks = [] - for name in notebook_names: - model = nbm.notebook_model(name,path) - notebooks.append(model) + notebooks = nbm.list_notebooks(path) self.finish(jsonapi.dumps(notebooks)) else: format = self.get_argument('format', default='json') @@ -89,6 +82,15 @@ class NotebookHandler(IPythonHandler): self.finish(jsonapi.dumps(model)) @web.authenticated + def patch(self, notebook_path): + nbm = self.notebook_manager + notebook_name, notebook_path = nbm.named_notebook_path(notebook_path) + data = jsonapi.loads(self.request.body) + model = nbm.change_notebook(data, notebook_name, notebook_path) + self.log.info(model) + self.finish(jsonapi.dumps(model)) + + @web.authenticated def put(self, notebook_path): nbm = self.notebook_manager notebook_name, notebook_path = nbm.named_notebook_path(notebook_path) diff --git a/IPython/html/services/notebooks/nbmanager.py b/IPython/html/services/notebooks/nbmanager.py index f6702be..4ba4b1a 100644 --- a/IPython/html/services/notebooks/nbmanager.py +++ b/IPython/html/services/notebooks/nbmanager.py @@ -150,17 +150,17 @@ class NotebookManager(LoggingConfigurable): raise web.HTTPError(400, u'Invalid JSON data') if name is None: - try: - name = nb.metadata.name - except AttributeError: - raise web.HTTPError(400, u'Missing notebook name') + try: + name = nb.metadata.name + except AttributeError: + raise web.HTTPError(400, u'Missing notebook name') nb.metadata.name = name notebook_name = self.write_notebook_object(nb, notebook_path=notebook_path) return notebook_name - def save_notebook(self, data, notebook_path=None, name=None, format=u'json'): - """Save an existing notebook by notebook_id.""" + def save_notebook(self, data, notebook_path=None, name=None, new_name=None, format=u'json'): + """Save an existing notebook by notebook_name.""" if format not in self.allowed_formats: raise web.HTTPError(415, u'Invalid notebook format: %s' % format) @@ -171,9 +171,9 @@ class NotebookManager(LoggingConfigurable): if name is not None: nb.metadata.name = name - self.write_notebook_object(nb, name, notebook_path) + self.write_notebook_object(nb, name, notebook_path, new_name) - def write_notebook_object(self, nb, notebook_name=None, notebook_path=None): + def write_notebook_object(self, nb, notebook_name=None, notebook_path=None, new_name=None): """Write a notebook object and return its notebook_name. If notebook_name is None, this method should create a new notebook_name. diff --git a/IPython/html/services/sessions/handlers.py b/IPython/html/services/sessions/handlers.py index 8ca801c..76338cd 100644 --- a/IPython/html/services/sessions/handlers.py +++ b/IPython/html/services/sessions/handlers.py @@ -59,26 +59,27 @@ class SessionRootHandler(IPythonHandler): class SessionHandler(IPythonHandler): - @web.authenticated + SUPPORTED_METHODS = ('GET', 'PATCH', 'DELETE') + + @authenticate_unless_readonly def get(self, session_id): sm = self.session_manager model = sm.get_session_from_id(session_id) self.finish(jsonapi.dumps(model)) - - - @authenticate_unless_readonly - def put(self, session_id): + + @web.authenticated + def patch(self, session_id): sm = self.session_manager nbm = self.notebook_manager km = self.kernel_manager - notebook_path = self.get_argument('notebook_path', default=None) + notebook_path = self.request.body notebook_name, path = nbm.named_notebook_path(notebook_path) kernel_id = sm.get_kernel_from_session(session_id) kernel = km.kernel_model(kernel_id, self.ws_url) sm.delete_mapping_for_session(session_id) model = sm.session_model(session_id, notebook_name, path, kernel) self.finish(jsonapi.dumps(model)) - + @web.authenticated def delete(self, session_id): sm = self.session_manager diff --git a/IPython/html/static/notebook/js/notebook.js b/IPython/html/static/notebook/js/notebook.js index 36dd30d..e169b04 100644 --- a/IPython/html/static/notebook/js/notebook.js +++ b/IPython/html/static/notebook/js/notebook.js @@ -1664,7 +1664,7 @@ var IPython = (function (IPython) { // time the ajax call for autosave tuning purposes. var start = new Date().getTime(); - + console.log(JSON.stringify(data)) // We do the call with settings so we can set cache to false. var settings = { processData : false, @@ -1730,6 +1730,32 @@ var IPython = (function (IPython) { Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) { $([IPython.events]).trigger('notebook_save_failed.Notebook'); }; + + + Notebook.prototype.notebook_rename = function (new_name) { + var that = this; + var name = {'notebook_name': new_name}; + var settings = { + processData : false, + cache : false, + type : "PATCH", + data : JSON.stringify(name), + dataType: "json", + headers : {'Content-Type': 'application/json'}, + success : $.proxy(that.rename_success, this) + }; + $([IPython.events]).trigger('notebook_rename.Notebook'); + var url = this.baseProjectUrl() + 'api/notebooks/' + this.notebookPath()+ this.notebook_name; + $.ajax(url, settings); + }; + + + Notebook.prototype.rename_success = function (json, status, xhr) { + this.notebook_name = json.notebook_name + var notebook_path = this.notebookPath() + this.notebook_name; + this.session.notebook_rename(notebook_path); + $([IPython.events]).trigger('notebook_renamed.Notebook'); + } /** * Request a notebook's data from the server. diff --git a/IPython/html/static/notebook/js/savewidget.js b/IPython/html/static/notebook/js/savewidget.js index 6fee780..36a01f3 100644 --- a/IPython/html/static/notebook/js/savewidget.js +++ b/IPython/html/static/notebook/js/savewidget.js @@ -46,6 +46,10 @@ var IPython = (function (IPython) { that.update_notebook_name(); that.update_document_title(); }); + $([IPython.events]).on('notebook_renamed.Notebook', function () { + that.update_notebook_name(); + that.update_document_title(); + }); $([IPython.events]).on('notebook_save_failed.Notebook', function () { that.set_save_status('Autosave Failed!'); }); @@ -90,8 +94,7 @@ var IPython = (function (IPython) { ); return false; } else { - IPython.notebook.set_notebook_name(new_name); - IPython.notebook.save_notebook(); + IPython.notebook.notebook_rename(new_name); } }} }, @@ -112,6 +115,7 @@ var IPython = (function (IPython) { SaveWidget.prototype.update_notebook_name = function () { var nbname = IPython.notebook.get_notebook_name(); + console.log("UPDATED") this.element.find('span#notebook_name').html(nbname); }; diff --git a/IPython/html/static/services/sessions/js/session.js b/IPython/html/static/services/sessions/js/session.js index fe8be64..dd5fd54 100644 --- a/IPython/html/static/services/sessions/js/session.js +++ b/IPython/html/static/services/sessions/js/session.js @@ -30,8 +30,33 @@ var IPython = (function (IPython) { ); }; + Session.prototype.notebook_rename = function (notebook_path) { + this.notebook_path = notebook_path; + console.log("TEST"); + var settings = { + processData : false, + cache : false, + type : "PATCH", + data: notebook_path, + dataType : "json", + }; + var url = this._baseProjectUrl + 'api/sessions/' + this.session_id; + $.ajax(url, settings); + } + + + Session.prototype.delete_session = function() { + var settings = { + processData : false, + cache : false, + type : "DELETE", + dataType : "json", + }; + var url = this._baseProjectUrl + 'api/sessions/' + this.session_id; + $.ajax(url, settings); + }; + // Kernel related things - /** * Start a new kernel and set it on each code cell. * @@ -67,16 +92,6 @@ var IPython = (function (IPython) { this.kernel.interrupt(); }; - Session.prototype.delete_session = function() { - var settings = { - processData : false, - cache : false, - type : "DELETE", - dataType : "json", - }; - var url = this._baseProjectUrl + 'api/sessions/' + this.session_id; - $.ajax(url, settings); - }; Session.prototype.kill_kernel = function() { this.kernel.kill(); diff --git a/IPython/html/static/tree/js/notebooklist.js b/IPython/html/static/tree/js/notebooklist.js index 1810b3d..c7de4f7 100644 --- a/IPython/html/static/tree/js/notebooklist.js +++ b/IPython/html/static/tree/js/notebooklist.js @@ -103,7 +103,6 @@ var IPython = (function (IPython) { }; NotebookList.prototype.load_sessions = function(){ - console.log("DID IT MAKE IT?"); var that = this; var settings = { processData : false,